add linux-v3.7

SVN-Revision: 34687
This commit is contained in:
John Crispin 2012-12-15 01:59:45 +00:00
parent 240a3a38e1
commit 3a948770cf
50 changed files with 16717 additions and 32 deletions

View file

@ -12,8 +12,8 @@ FEATURES:=squashfs jffs2
SUBTARGETS:=danube ar9 vr9 falcon svip_be
LINUX_VERSION:=3.3.8
#SUBTARGETS=xway ase
#LINUX_VERSION:=3.6.10
SUBTARGETS=xway ase falcon
LINUX_VERSION:=3.7-rc8
CFLAGS=-Os -pipe -mips32r2 -mtune=mips32r2 -fno-caller-saves

View file

@ -1,11 +1,19 @@
CONFIG_AR8216_PHY=y
CONFIG_INPUT=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_POLLDEV=y
# CONFIG_ISDN is not set
# CONFIG_LANTIQ_PHY is not set
# CONFIG_M25PXX_USE_FAST_READ is not set
CONFIG_MTD_M25P80=y
# CONFIG_RTL8366_SMI is not set
CONFIG_SOC_AMAZON_SE=y
# CONFIG_SOC_XWAY is not set
CONFIG_SPI=y
CONFIG_SPI_BITBANG=y
CONFIG_SPI_MASTER=y
CONFIG_SPI_XWAY=y
# CONFIG_USB_ARCH_HAS_EHCI is not set
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
# CONFIG_USB_ARCH_HAS_XHCI is not set
CONFIG_USB_SUPPORT=y

View file

@ -0,0 +1,165 @@
CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
CONFIG_ARCH_DISCARD_MEMBLOCK=y
CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_REQUIRE_GPIOLIB=y
CONFIG_ARCH_SUPPORTS_MSI=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
CONFIG_CEVT_R4K=y
CONFIG_CEVT_R4K_LIB=y
CONFIG_CLKDEV_LOOKUP=y
CONFIG_CPU_BIG_ENDIAN=y
CONFIG_CPU_GENERIC_DUMP_TLB=y
CONFIG_CPU_HAS_PREFETCH=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_CPU_MIPS32=y
# CONFIG_CPU_MIPS32_R1 is not set
CONFIG_CPU_MIPS32_R2=y
CONFIG_CPU_MIPSR2=y
CONFIG_CPU_R4K_CACHE_TLB=y
CONFIG_CPU_R4K_FPU=y
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CSRC_R4K=y
CONFIG_CSRC_R4K_LIB=y
# CONFIG_DEBUG_PINCTRL is not set
CONFIG_DECOMPRESS_LZMA=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DTC=y
CONFIG_DT_EASY50712=y
CONFIG_EARLY_PRINTK=y
CONFIG_ETHERNET_PACKET_MANGLE=y
CONFIG_GENERIC_ATOMIC64=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_GPIO=y
CONFIG_GENERIC_IO=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_MM_LANTIQ=y
CONFIG_GPIO_STP_XWAY=y
CONFIG_GPIO_SYSFS=y
CONFIG_HARDWARE_WATCHPOINTS=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAVE_ARCH_JUMP_LABEL=y
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_C_RECORDMCOUNT=y
CONFIG_HAVE_DEBUG_KMEMLEAK=y
CONFIG_HAVE_DMA_API_DEBUG=y
CONFIG_HAVE_DMA_ATTRS=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_HAVE_GENERIC_HARDIRQS=y
CONFIG_HAVE_IDE=y
CONFIG_HAVE_IRQ_WORK=y
CONFIG_HAVE_MACH_CLKDEV=y
CONFIG_HAVE_MEMBLOCK=y
CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_PERF_EVENTS=y
CONFIG_HW_HAS_PCI=y
CONFIG_HW_RANDOM=y
CONFIG_HZ=250
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_IRQ_CPU=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_LANTIQ=y
CONFIG_LANTIQ_ETOP=y
CONFIG_LANTIQ_PHY=y
CONFIG_LANTIQ_WDT=y
CONFIG_LANTIQ_XRX200=y
CONFIG_LEDS_GPIO=y
CONFIG_MDIO_BOARDINFO=y
CONFIG_MIPS=y
CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_MIPS_MACHINE is not set
CONFIG_MIPS_MT_DISABLED=y
# CONFIG_MIPS_MT_SMP is not set
# CONFIG_MIPS_MT_SMTC is not set
# CONFIG_MIPS_SEAD3 is not set
# CONFIG_MIPS_VPE_LOADER is not set
CONFIG_MODULES_USE_ELF_REL=y
CONFIG_MTD_CFI_ADV_OPTIONS=y
CONFIG_MTD_CFI_GEOMETRY=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_LANTIQ=y
CONFIG_MTD_OF_PARTS=y
CONFIG_MTD_PHYSMAP_OF=y
CONFIG_MTD_UIMAGE_SPLIT=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NEED_PER_CPU_KM=y
CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_DEVICE=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_FLATTREE=y
CONFIG_OF_GPIO=y
CONFIG_OF_IRQ=y
CONFIG_OF_MDIO=y
CONFIG_OF_MTD=y
CONFIG_OF_NET=y
CONFIG_OF_PCI=y
CONFIG_OF_PCI_IRQ=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_PCI=y
# CONFIG_PCIE_LANTIQ is not set
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_LANTIQ=y
CONFIG_PERF_USE_VMALLOC=y
CONFIG_PHYLIB=y
CONFIG_PINCONF=y
CONFIG_PINCTRL=y
# CONFIG_PINCTRL_EXYNOS4 is not set
CONFIG_PINCTRL_LANTIQ=y
# CONFIG_PINCTRL_SAMSUNG is not set
# CONFIG_PINCTRL_SINGLE is not set
CONFIG_PINCTRL_XWAY=y
CONFIG_PINMUX=y
# CONFIG_PREEMPT_RCU is not set
CONFIG_PROC_DEVICETREE=y
CONFIG_PSB6970_PHY=y
CONFIG_RTL8366RB_PHY=y
CONFIG_RTL8366_SMI=y
# CONFIG_SCSI_DMA is not set
# CONFIG_SERIAL_8250 is not set
CONFIG_SERIAL_LANTIQ=y
# CONFIG_SOC_AMAZON_SE is not set
# CONFIG_SOC_FALCON is not set
# CONFIG_SOC_SVIP is not set
CONFIG_SOC_TYPE_XWAY=y
CONFIG_SOC_XWAY=y
CONFIG_SWAP_IO_SPACE=y
CONFIG_SWCONFIG=y
CONFIG_SYS_HAS_CPU_MIPS32_R1=y
CONFIG_SYS_HAS_CPU_MIPS32_R2=y
CONFIG_SYS_HAS_EARLY_PRINTK=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
CONFIG_SYS_SUPPORTS_MULTITHREADING=y
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_UIDGID_CONVERTED=y
CONFIG_USB_ARCH_HAS_XHCI=y
CONFIG_USE_OF=y
CONFIG_XRX200_PHY_FW=y
CONFIG_ZONE_DMA_FLAG=0

View file

@ -1,20 +1,19 @@
# CONFIG_ATMEL_PWM is not set
CONFIG_CLKDEV_LOOKUP=y
CONFIG_FSNOTIFY=y
CONFIG_HAVE_MACH_CLKDEV=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_GPIO_FALCON=y
CONFIG_GPIO_GENERIC=y
CONFIG_M25PXX_USE_FAST_READ=y
CONFIG_MDIO_BOARDINFO=y
CONFIG_MTD_M25P80=y
CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_ECC=y
CONFIG_MTD_NAND_FALCON=y
CONFIG_MTD_NAND_PLATFORM=y
# CONFIG_MTD_SM_COMMON is not set
# CONFIG_SOC_AMAZON_SE is not set
CONFIG_PINCTRL_FALCON=y
CONFIG_SOC_FALCON=y
# CONFIG_SOC_SVIP is not set
# CONFIG_SOC_TYPE_XWAY is not set
# CONFIG_SOC_XWAY is not set
CONFIG_SPI=y
CONFIG_SPI_FALCON=y
CONFIG_SPI_MASTER=y
# CONFIG_USB_ARCH_HAS_EHCI is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
# CONFIG_USB_ARCH_HAS_XHCI is not set

View file

@ -21,12 +21,8 @@ endef
define PatchKernelLzma
cp $(KDIR)/vmlinux $(KDIR)/vmlinux-$(1)
ifeq ($(CONFIG_LINUX_3_6),y)
$(LINUX_DIR)/scripts/dtc/dtc -O dtb -o $(KDIR)/$(1).dtb ./$(1).dts
$(STAGING_DIR_HOST)/bin/patch-dtb $(KDIR)/vmlinux-$(1) $(KDIR)/$(1).dtb
else
$(STAGING_DIR_HOST)/bin/patch-cmdline $(KDIR)/vmlinux-$(1) '$(strip $(2))'
endif
$(call CompressLzma,$(KDIR)/vmlinux-$(1),$(KDIR)/vmlinux-$(1).lzma)
endef

View file

@ -0,0 +1,41 @@
From a15d129a352e5f6ab821b81bc3f692ecc952a815 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 9 Nov 2012 12:09:57 +0100
Subject: [PATCH 1/6] MIPS: lantiq: unbreak devicetree init
The bootmem was incorrectly freed resulting in lots of dangling pointers.
Additionally we should use of_platform_populate() as the Documentaion tells us
to do so.
Signed-off-by: John Crispin <blogic@openwrt.org>
Patchwork: http://patchwork.linux-mips.org/patch/4518
---
arch/mips/lantiq/prom.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
index 6cfd611..9f9e875 100644
--- a/arch/mips/lantiq/prom.c
+++ b/arch/mips/lantiq/prom.c
@@ -87,9 +87,6 @@ void __init device_tree_init(void)
reserve_bootmem(base, size, BOOTMEM_DEFAULT);
unflatten_device_tree();
-
- /* free the space reserved for the dt blob */
- free_bootmem(base, size);
}
void __init prom_init(void)
@@ -119,7 +116,7 @@ int __init plat_of_setup(void)
sizeof(of_ids[0].compatible));
strncpy(of_ids[1].compatible, "simple-bus",
sizeof(of_ids[1].compatible));
- return of_platform_bus_probe(NULL, of_ids, NULL);
+ return of_platform_populate(NULL, of_ids, NULL, NULL);
}
arch_initcall(plat_of_setup);
--
1.7.10.4

View file

@ -0,0 +1,71 @@
From 15753b6586710d788f36cfd5fbb98d0805b390ab Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 9 Nov 2012 13:31:51 +0100
Subject: [PATCH 2/6] MIPS: lantiq: fix bootselect bits on XRX200 SoC
The XRX200 SoC family has a different register layout for reading the boot
selection bits.
Signed-off-by: John Crispin <blogic@openwrt.org>
Patchwork: http://patchwork.linux-mips.org/patch/4519
---
arch/mips/lantiq/xway/reset.c | 22 +++++++++++++++-------
1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
index 22c55f7..2799212 100644
--- a/arch/mips/lantiq/xway/reset.c
+++ b/arch/mips/lantiq/xway/reset.c
@@ -34,11 +34,12 @@
/* reset cause */
#define RCU_STAT_SHIFT 26
/* boot selection */
-#define RCU_BOOT_SEL_SHIFT 26
-#define RCU_BOOT_SEL_MASK 0x7
+#define RCU_BOOT_SEL(x) ((x >> 18) & 0x7)
+#define RCU_BOOT_SEL_XRX200(x) (((x >> 17) & 0xf) | ((x >> 8) & 0x10))
/* remapped base addr of the reset control unit */
static void __iomem *ltq_rcu_membase;
+static struct device_node *ltq_rcu_np;
/* This function is used by the watchdog driver */
int ltq_reset_cause(void)
@@ -52,7 +53,11 @@ EXPORT_SYMBOL_GPL(ltq_reset_cause);
unsigned char ltq_boot_select(void)
{
u32 val = ltq_rcu_r32(RCU_RST_STAT);
- return (val >> RCU_BOOT_SEL_SHIFT) & RCU_BOOT_SEL_MASK;
+
+ if (of_device_is_compatible(ltq_rcu_np, "lantiq,rcu-xrx200"))
+ return RCU_BOOT_SEL_XRX200(val);
+
+ return RCU_BOOT_SEL(val);
}
/* reset a io domain for u micro seconds */
@@ -85,14 +90,17 @@ static void ltq_machine_power_off(void)
static int __init mips_reboot_setup(void)
{
struct resource res;
- struct device_node *np =
- of_find_compatible_node(NULL, NULL, "lantiq,rcu-xway");
+
+ ltq_rcu_np = of_find_compatible_node(NULL, NULL, "lantiq,rcu-xway");
+ if (!ltq_rcu_np)
+ ltq_rcu_np = of_find_compatible_node(NULL, NULL,
+ "lantiq,rcu-xrx200");
/* check if all the reset register range is available */
- if (!np)
+ if (!ltq_rcu_np)
panic("Failed to load reset resources from devicetree");
- if (of_address_to_resource(np, 0, &res))
+ if (of_address_to_resource(ltq_rcu_np, 0, &res))
panic("Failed to get rcu memory range");
if (request_mem_region(res.start, resource_size(&res), res.name) < 0)
--
1.7.10.4

View file

@ -0,0 +1,50 @@
From b8b3acbe6077b4736f641ec445be8a42cdd1f08b Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 9 Nov 2012 12:16:14 +0100
Subject: [PATCH 3/6] MIPS: lantiq: verbose init of dma core
Print the hardware revision and port/channel info when starting the dma core.
Signed-off-by: John Crispin <blogic@openwrt.org>
Patchwork: http://patchwork.linux-mips.org/patch/4520
---
arch/mips/lantiq/xway/dma.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c
index 55d2c4f..b5d76d1 100644
--- a/arch/mips/lantiq/xway/dma.c
+++ b/arch/mips/lantiq/xway/dma.c
@@ -25,6 +25,7 @@
#include <lantiq_soc.h>
#include <xway_dma.h>
+#define LTQ_DMA_ID 0x08
#define LTQ_DMA_CTRL 0x10
#define LTQ_DMA_CPOLL 0x14
#define LTQ_DMA_CS 0x18
@@ -214,6 +215,7 @@ ltq_dma_init(struct platform_device *pdev)
{
struct clk *clk;
struct resource *res;
+ unsigned id;
int i;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -243,7 +245,12 @@ ltq_dma_init(struct platform_device *pdev)
ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL);
ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
}
- dev_info(&pdev->dev, "init done\n");
+
+ id = ltq_dma_r32(LTQ_DMA_ID);
+ dev_info(&pdev->dev,
+ "Init done - hw rev: %X, ports: %d, channels: %d\n",
+ id & 0x1f, (id >> 16) & 0xf, id >> 20);
+
return 0;
}
--
1.7.10.4

View file

@ -0,0 +1,29 @@
From f2bbe41c507b475c6f0ae1fca69c7aac6d31d228 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 9 Nov 2012 13:34:18 +0100
Subject: [PATCH 4/6] MIPS: lantiq: adds xrx200 ethernet clock definition
Signed-off-by: John Crispin <blogic@openwrt.org>
Patchwork: http://patchwork.linux-mips.org/patch/4521
---
arch/mips/lantiq/xway/sysctrl.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
index 2917b56..3925e66 100644
--- a/arch/mips/lantiq/xway/sysctrl.c
+++ b/arch/mips/lantiq/xway/sysctrl.c
@@ -370,6 +370,10 @@ void __init ltq_soc_init(void)
clkdev_add_pmu("1d900000.pcie", "pdi", 1, PMU1_PCIE_PDI);
clkdev_add_pmu("1d900000.pcie", "ctl", 1, PMU1_PCIE_CTL);
clkdev_add_pmu("1d900000.pcie", "ahb", 0, PMU_AHBM | PMU_AHBS);
+ clkdev_add_pmu("1e108000.eth", NULL, 0,
+ PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM |
+ PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
+ PMU_PPE_QSB | PMU_PPE_TOP);
} else if (of_machine_is_compatible("lantiq,ar9")) {
clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(),
ltq_ar9_fpi_hz());
--
1.7.10.4

View file

@ -0,0 +1,89 @@
From af14a456c58c153c6d761e6c0af48157692b52ad Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 9 Nov 2012 13:43:30 +0100
Subject: [PATCH 5/6] MIPS: lantiq: adds code for booting GPHY
The XRX200 family of SoCs has embedded gigabit PHYs. This patch adds code to
boot them up.
Signed-off-by: John Crispin <blogic@openwrt.org>
Patchwork: http://patchwork.linux-mips.org/patch/4522
---
.../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 3 ++
arch/mips/lantiq/xway/reset.c | 36 ++++++++++++++++++++
2 files changed, 39 insertions(+)
diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
index 6a2df70..133336b 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -82,6 +82,9 @@ extern __iomem void *ltq_cgu_membase;
#define LTQ_MPS_BASE_ADDR (KSEG1 + 0x1F107000)
#define LTQ_MPS_CHIPID ((u32 *)(LTQ_MPS_BASE_ADDR + 0x0344))
+/* allow booting xrx200 phys */
+int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr);
+
/* request a non-gpio and set the PIO config */
#define PMU_PPE BIT(13)
extern void ltq_pmu_enable(unsigned int module);
diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
index 2799212..544dbb7 100644
--- a/arch/mips/lantiq/xway/reset.c
+++ b/arch/mips/lantiq/xway/reset.c
@@ -28,9 +28,15 @@
#define RCU_RST_REQ 0x0010
/* reset status register */
#define RCU_RST_STAT 0x0014
+/* vr9 gphy registers */
+#define RCU_GFS_ADD0_XRX200 0x0020
+#define RCU_GFS_ADD1_XRX200 0x0068
/* reboot bit */
+#define RCU_RD_GPHY0_XRX200 BIT(31)
#define RCU_RD_SRST BIT(30)
+#define RCU_RD_GPHY1_XRX200 BIT(29)
+
/* reset cause */
#define RCU_STAT_SHIFT 26
/* boot selection */
@@ -60,6 +66,36 @@ unsigned char ltq_boot_select(void)
return RCU_BOOT_SEL(val);
}
+/* reset / boot a gphy */
+static struct ltq_xrx200_gphy_reset {
+ u32 rd;
+ u32 addr;
+} xrx200_gphy[] = {
+ {RCU_RD_GPHY0_XRX200, RCU_GFS_ADD0_XRX200},
+ {RCU_RD_GPHY1_XRX200, RCU_GFS_ADD1_XRX200},
+};
+
+/* reset and boot a gphy. these phys only exist on xrx200 SoC */
+int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr)
+{
+ if (!of_device_is_compatible(ltq_rcu_np, "lantiq,rcu-xrx200")) {
+ dev_err(dev, "this SoC has no GPHY\n");
+ return -EINVAL;
+ }
+ if (id > 1) {
+ dev_err(dev, "%u is an invalid gphy id\n", id);
+ return -EINVAL;
+ }
+ dev_info(dev, "booting GPHY%u firmware at %X\n", id, dev_addr);
+
+ ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | xrx200_gphy[id].rd,
+ RCU_RST_REQ);
+ ltq_rcu_w32(dev_addr, xrx200_gphy[id].addr);
+ ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~xrx200_gphy[id].rd,
+ RCU_RST_REQ);
+ return 0;
+}
+
/* reset a io domain for u micro seconds */
void ltq_reset_once(unsigned int module, ulong u)
{
--
1.7.10.4

View file

@ -0,0 +1,144 @@
From 0224cde212df4abf251f89c3724a800b1949a774 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 22 Oct 2012 07:52:50 +0200
Subject: [PATCH 6/6] MIPS: lantiq: adds GPHY firmware loader
The internal GPHYs need a firmware blob to function properly. This patch adds
the code needed to request the blob and load it to the PHY.
Signed-off-by: John Crispin <blogic@openwrt.org>
Patchwork: http://patchwork.linux-mips.org/patch/4523
---
arch/mips/lantiq/Kconfig | 4 ++
arch/mips/lantiq/xway/Makefile | 2 +
arch/mips/lantiq/xway/xrx200_phy_fw.c | 97 +++++++++++++++++++++++++++++++++
3 files changed, 103 insertions(+)
create mode 100644 arch/mips/lantiq/xway/xrx200_phy_fw.c
diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
index d84f361..c002191 100644
--- a/arch/mips/lantiq/Kconfig
+++ b/arch/mips/lantiq/Kconfig
@@ -36,4 +36,8 @@ config PCI_LANTIQ
bool "PCI Support"
depends on SOC_XWAY && PCI
+config XRX200_PHY_FW
+ bool "XRX200 PHY firmware loader"
+ depends on SOC_XWAY
+
endif
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
index 70a58c7..7a13660 100644
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1 +1,3 @@
obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o
+
+obj-$(CONFIG_XRX200_PHY_FW) += xrx200_phy_fw.o
diff --git a/arch/mips/lantiq/xway/xrx200_phy_fw.c b/arch/mips/lantiq/xway/xrx200_phy_fw.c
new file mode 100644
index 0000000..fe808bf
--- /dev/null
+++ b/arch/mips/lantiq/xway/xrx200_phy_fw.c
@@ -0,0 +1,97 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/of_platform.h>
+
+#include <lantiq_soc.h>
+
+#define XRX200_GPHY_FW_ALIGN (16 * 1024)
+
+static dma_addr_t xway_gphy_load(struct platform_device *pdev)
+{
+ const struct firmware *fw;
+ dma_addr_t dev_addr = 0;
+ const char *fw_name;
+ void *fw_addr;
+ size_t size;
+
+ if (of_property_read_string(pdev->dev.of_node, "firmware", &fw_name)) {
+ dev_err(&pdev->dev, "failed to load firmware filename\n");
+ return 0;
+ }
+
+ dev_info(&pdev->dev, "requesting %s\n", fw_name);
+ if (request_firmware(&fw, fw_name, &pdev->dev)) {
+ dev_err(&pdev->dev, "failed to load firmware: %s\n", fw_name);
+ return 0;
+ }
+
+ /*
+ * GPHY cores need the firmware code in a persistent and contiguous
+ * memory area with a 16 kB boundary aligned start address
+ */
+ size = fw->size + XRX200_GPHY_FW_ALIGN;
+
+ fw_addr = dma_alloc_coherent(&pdev->dev, size, &dev_addr, GFP_KERNEL);
+ if (fw_addr) {
+ fw_addr = PTR_ALIGN(fw_addr, XRX200_GPHY_FW_ALIGN);
+ dev_addr = ALIGN(dev_addr, XRX200_GPHY_FW_ALIGN);
+ memcpy(fw_addr, fw->data, fw->size);
+ } else {
+ dev_err(&pdev->dev, "failed to alloc firmware memory\n");
+ }
+
+ release_firmware(fw);
+ return dev_addr;
+}
+
+static int __devinit xway_phy_fw_probe(struct platform_device *pdev)
+{
+ dma_addr_t fw_addr;
+ struct property *pp;
+ unsigned char *phyids;
+ int i, ret = 0;
+
+ fw_addr = xway_gphy_load(pdev);
+ if (!fw_addr)
+ return -EINVAL;
+ pp = of_find_property(pdev->dev.of_node, "phys", NULL);
+ if (!pp)
+ return -ENOENT;
+ phyids = pp->value;
+ for (i = 0; i < pp->length && !ret; i++)
+ ret = xrx200_gphy_boot(&pdev->dev, phyids[i], fw_addr);
+ if (!ret)
+ mdelay(100);
+ return ret;
+}
+
+static const struct of_device_id xway_phy_match[] = {
+ { .compatible = "lantiq,phy-xrx200" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, xway_phy_match);
+
+static struct platform_driver xway_phy_driver = {
+ .probe = xway_phy_fw_probe,
+ .driver = {
+ .name = "phy-xrx200",
+ .owner = THIS_MODULE,
+ .of_match_table = xway_phy_match,
+ },
+};
+
+module_platform_driver(xway_phy_driver);
+
+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+MODULE_DESCRIPTION("Lantiq XRX200 PHY Firmware Loader");
+MODULE_LICENSE("GPL");
--
1.7.10.4

View file

@ -0,0 +1,59 @@
From 60bc3043590bf74ca1c9dd88a4e5f28a40d5b348 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 6 Dec 2012 10:26:05 +0100
Subject: [PATCH 100/123] MIPS: lantiq: honour model property inside
devicetree during board init
---
arch/mips/lantiq/prom.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
index 9f9e875..fa12dc1 100644
--- a/arch/mips/lantiq/prom.c
+++ b/arch/mips/lantiq/prom.c
@@ -57,6 +57,21 @@ static void __init prom_init_cmdline(void)
}
}
+int __init early_init_dt_scan_model(unsigned long node,
+ const char *uname, int depth,
+ void *data)
+{
+ if (!depth) {
+ char *model = of_get_flat_dt_prop(node, "model", NULL);
+ if (model) {
+ pr_info("Board: %s\n", model);
+ snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN, "%s - %s",
+ soc_info.sys_type, model);
+ }
+ }
+ return 0;
+}
+
void __init plat_mem_setup(void)
{
ioport_resource.start = IOPORT_RESOURCE_START;
@@ -71,6 +86,8 @@ void __init plat_mem_setup(void)
* parsed resulting in our memory appearing
*/
__dt_setup_arch(&__dtb_start);
+
+ of_scan_flat_dt(early_init_dt_scan_model, NULL);
}
void __init device_tree_init(void)
@@ -93,9 +110,8 @@ void __init prom_init(void)
{
/* call the soc specific detetcion code and get it to fill soc_info */
ltq_soc_detect(&soc_info);
- snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev %s",
+ snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN, "%s rev %s",
soc_info.name, soc_info.rev_type);
- soc_info.sys_type[LTQ_SYS_TYPE_LEN - 1] = '\0';
pr_info("SoC: %s\n", soc_info.sys_type);
prom_init_cmdline();
--
1.7.10.4

View file

@ -0,0 +1,439 @@
From 4d77ad216ad86b3b25c196a189fa28f3e53c3ffd Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 30 Nov 2012 21:32:00 +0100
Subject: [PATCH 101/123] MIPS: lantiq: adds support for SVIP SoC Family
---
arch/mips/kernel/cevt-r4k.c | 4 +-
arch/mips/lantiq/Kconfig | 4 ++
arch/mips/lantiq/Makefile | 1 +
arch/mips/lantiq/Platform | 1 +
arch/mips/lantiq/clk.c | 7 +++
arch/mips/lantiq/clk.h | 4 ++
arch/mips/lantiq/svip/Makefile | 1 +
arch/mips/lantiq/svip/clk.c | 70 ++++++++++++++++++++++++++
arch/mips/lantiq/svip/prom.c | 43 ++++++++++++++++
arch/mips/lantiq/svip/reset.c | 105 +++++++++++++++++++++++++++++++++++++++
arch/mips/lantiq/svip/sysctrl.c | 81 ++++++++++++++++++++++++++++++
11 files changed, 320 insertions(+), 1 deletion(-)
create mode 100644 arch/mips/lantiq/svip/Makefile
create mode 100644 arch/mips/lantiq/svip/clk.c
create mode 100644 arch/mips/lantiq/svip/prom.c
create mode 100644 arch/mips/lantiq/svip/reset.c
create mode 100644 arch/mips/lantiq/svip/sysctrl.c
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index 7532392..06b45e4 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -176,8 +176,10 @@ int __cpuinit r4k_clockevent_init(void)
if (!cpu_has_counter || !mips_hpt_frequency)
return -ENXIO;
- if (!c0_compare_int_usable())
+ if (!c0_compare_int_usable()) {
+ printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
return -ENXIO;
+ }
/*
* With vectored interrupts things are getting platform specific.
diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
index c002191..edeb58c 100644
--- a/arch/mips/lantiq/Kconfig
+++ b/arch/mips/lantiq/Kconfig
@@ -22,6 +22,10 @@ config SOC_FALCON
bool "FALCON"
select PINCTRL_FALCON
+config SOC_SVIP
+ bool "SVIP"
+ select MIPS_CPU_SCACHE
+
endchoice
choice
diff --git a/arch/mips/lantiq/Makefile b/arch/mips/lantiq/Makefile
index d6bdc57..edeb30b 100644
--- a/arch/mips/lantiq/Makefile
+++ b/arch/mips/lantiq/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_SOC_TYPE_XWAY) += xway/
obj-$(CONFIG_SOC_FALCON) += falcon/
+obj-$(CONFIG_SOC_SVIP) += svip/
diff --git a/arch/mips/lantiq/Platform b/arch/mips/lantiq/Platform
index b3ec498..857548c 100644
--- a/arch/mips/lantiq/Platform
+++ b/arch/mips/lantiq/Platform
@@ -7,3 +7,4 @@ cflags-$(CONFIG_LANTIQ) += -I$(srctree)/arch/mips/include/asm/mach-lantiq
load-$(CONFIG_LANTIQ) = 0xffffffff80002000
cflags-$(CONFIG_SOC_TYPE_XWAY) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/xway
cflags-$(CONFIG_SOC_FALCON) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/falcon
+cflags-$(CONFIG_SOC_SVIP) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/svip
diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c
index ce2f129..9128ff8 100644
--- a/arch/mips/lantiq/clk.c
+++ b/arch/mips/lantiq/clk.c
@@ -163,8 +163,15 @@ void __init plat_time_init(void)
ltq_soc_init();
clk = clk_get_cpu();
+#ifdef CONFIG_SOC_SVIP
+ mips_hpt_frequency = ltq_svip_cpu_hz() / get_counter_resolution();
+ write_c0_count(0);
+ write_c0_compare(mips_hpt_frequency / HZ);
+ enable_irq(MIPS_CPU_TIMER_IRQ);
+#else
mips_hpt_frequency = clk_get_rate(clk) / get_counter_resolution();
write_c0_compare(read_c0_count());
+#endif
pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);
clk_put(clk);
}
diff --git a/arch/mips/lantiq/clk.h b/arch/mips/lantiq/clk.h
index fa67060..c169e2b 100644
--- a/arch/mips/lantiq/clk.h
+++ b/arch/mips/lantiq/clk.h
@@ -75,4 +75,8 @@ extern unsigned long ltq_ar9_fpi_hz(void);
extern unsigned long ltq_vr9_cpu_hz(void);
extern unsigned long ltq_vr9_fpi_hz(void);
+extern unsigned long ltq_svip_cpu_hz(void);
+extern unsigned long ltq_svip_fpi_hz(void);
+extern unsigned long ltq_svip_io_hz(void);
+
#endif
diff --git a/arch/mips/lantiq/svip/Makefile b/arch/mips/lantiq/svip/Makefile
new file mode 100644
index 0000000..74308b2
--- /dev/null
+++ b/arch/mips/lantiq/svip/Makefile
@@ -0,0 +1 @@
+obj-y := prom.o reset.o sysctrl.o clk.o
diff --git a/arch/mips/lantiq/svip/clk.c b/arch/mips/lantiq/svip/clk.c
new file mode 100644
index 0000000..3a7b665
--- /dev/null
+++ b/arch/mips/lantiq/svip/clk.c
@@ -0,0 +1,70 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/io.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+
+#include <asm/time.h>
+#include <asm/irq.h>
+#include <asm/div64.h>
+
+#include <lantiq_soc.h>
+
+#include "../clk.h"
+
+#define STATUS_CONFIG_CLK_MODE (0x1 << 1)
+#define STATUS_CONFIG_CLK_MODE_GET(val) ((((val) & STATUS_CONFIG_CLK_MODE) >> 4) & 0x1)
+#define STATUS_CONFIG 0x0010
+
+#define SYS0_PLL1CR_PLLDIV (0x3)
+#define SYS0_PLL1CR_PLLDIV_GET(val) ((((val) & SYS0_PLL1CR_PLLDIV) >> 0) & 0x3)
+#define SYS0_PLL1CR 0x0008
+
+#define SYS1_FPICR_FPIDIV (0x1)
+#define SYS1_FPICR_FPIDIV_GET(val) ((((val) & SYS1_FPICR_FPIDIV) >> 0) & 0x1)
+#define SYS1_FPICR 0x0014
+
+unsigned long ltq_svip_io_hz(void)
+{
+ return 200000000; /* 200 MHz */
+}
+
+unsigned long ltq_svip_cpu_hz(void)
+{
+ /* Magic BootROM speed location... */
+ if ((*(u32 *)0x9fc07ff0) == 1)
+ return *(u32 *)0x9fc07ff4;
+
+ if (STATUS_CONFIG_CLK_MODE_GET(ltq_status_r32(STATUS_CONFIG)) == 1) {
+ /* xT16 */
+ return 393216000;
+ } else {
+ switch (SYS0_PLL1CR_PLLDIV_GET(ltq_sys0_r32(SYS0_PLL1CR))) {
+ case 3:
+ return 475000000;
+ case 2:
+ return 450000000;
+ case 1:
+ return 425000000;
+ default:
+ break;
+ }
+ }
+ return 400000000;
+}
+
+unsigned long ltq_svip_fpi_hz(void)
+{
+ u32 fbs0_div[2] = {4, 8};
+ u32 div;
+
+ div = SYS1_FPICR_FPIDIV_GET(ltq_sys1_r32(SYS1_FPICR));
+ return ltq_svip_cpu_hz() / fbs0_div[div];
+}
diff --git a/arch/mips/lantiq/svip/prom.c b/arch/mips/lantiq/svip/prom.c
new file mode 100644
index 0000000..01d2018
--- /dev/null
+++ b/arch/mips/lantiq/svip/prom.c
@@ -0,0 +1,43 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2012 Thomas Langer <thomas.langer@lantiq.com>
+ * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/kernel.h>
+#include <asm/io.h>
+
+#include <lantiq_soc.h>
+
+#include "../prom.h"
+
+#define SOC_SVIP "SVIP"
+
+#define COMP_SVIP "lantiq,svip"
+
+#define PART_SHIFT 12
+#define PART_MASK 0x0FFFF000
+#define REV_SHIFT 28
+#define REV_MASK 0xF0000000
+
+void __init ltq_soc_detect(struct ltq_soc_info *i)
+{
+ i->partnum = (ltq_r32(LTQ_STATUS_CHIPID) & PART_MASK) >> PART_SHIFT;
+ i->rev = (ltq_r32(LTQ_STATUS_CHIPID) & REV_MASK) >> REV_SHIFT;
+ sprintf(i->rev_type, "1.%d", i->rev);
+
+ switch (i->partnum) {
+ case SOC_ID_SVIP:
+ i->name = SOC_SVIP;
+ i->type = SOC_TYPE_SVIP;
+ i->compatible = COMP_SVIP;
+ break;
+
+ default:
+ printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
+ break;
+ }
+}
diff --git a/arch/mips/lantiq/svip/reset.c b/arch/mips/lantiq/svip/reset.c
new file mode 100644
index 0000000..4b41dd1
--- /dev/null
+++ b/arch/mips/lantiq/svip/reset.c
@@ -0,0 +1,105 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/pm.h>
+#include <linux/module.h>
+#include <asm/reboot.h>
+
+#include <lantiq_soc.h>
+
+#define CPLD_CMDREG3 ((volatile unsigned char*)(KSEG1 + 0x120000f3))
+
+#define LTQ_EBU_ADDRSEL2 0x0028
+#define LTQ_EBU_BUSCON2 0x0068
+#define LTQ_BOOT_CPU_OFFSET 0x20
+
+#define LTQ_L2_SPRAM_BASE (KSEG1 + 0x1F1E8000)
+#define LTQ_BOOT_RVEC(cpu) (volatile u32*)(LTQ_L2_SPRAM_BASE + \
+ (cpu * LTQ_BOOT_CPU_OFFSET))
+
+#define SYS0_BCR 0x0004
+#define BMODE_SHIFT 16
+#define BMODE_MASK 0x1f
+
+#define SYS1_CLKCLR 0x0008
+#define SYS1_RREQR 0x0044
+#define SYS1_RRLSR 0x0048
+#define SYS1_RBTR 0x004c
+#define SYS1_CPU0RSR 0x0060
+#define SYS1_CPU0RSR_MASK 0x0007
+
+/* This function is used by the watchdog driver */
+int ltq_reset_cause(void)
+{
+ return ltq_sys1_r32(SYS1_CPU0RSR) & SYS1_CPU0RSR_MASK;
+}
+EXPORT_SYMBOL_GPL(ltq_reset_cause);
+
+/* allow platform code to find out what source we booted from */
+unsigned char ltq_boot_select(void)
+{
+ return (ltq_sys0_r32(SYS0_BCR) >> BMODE_SHIFT) & BMODE_MASK;
+}
+
+static void ltq_machine_restart(char *command)
+{
+ local_irq_disable();
+ if (/*mips_machtype == LANTIQ_MACH_EASY33016 ||
+ mips_machtype == LANTIQ_MACH_EASY336)*/
+ 1) {
+ /* We just use the CPLD function to reset the entire system as a
+ workaround for the switch reset problem */
+ local_irq_disable();
+ ltq_ebu_w32(0x120000f1, LTQ_EBU_ADDRSEL2);
+ ltq_ebu_w32(0x404027ff, LTQ_EBU_BUSCON2);
+
+ if (/*mips_machtype == LANTIQ_MACH_EASY336*/
+ 0)
+ /* set bit 0 to reset SVIP */
+ *CPLD_CMDREG3 = (1<<0);
+ else
+ /* set bit 7 to reset SVIP, set bit 3 to reset xT */
+ *CPLD_CMDREG3 = (1<<7) | (1<<3);
+ } else {
+ *LTQ_BOOT_RVEC(0) = 0;
+ /* reset all except PER, SUBSYS and CPU0 */
+ ltq_sys1_w32(0x00043F3E, SYS1_RREQR);
+ /* release WDT0 reset */
+ ltq_sys1_w32(0x00000100, SYS1_RRLSR);
+ /* restore reset value for clock enables */
+ ltq_sys1_w32(~0x0c000040, SYS1_CLKCLR);
+ /* reset SUBSYS (incl. DDR2) and CPU0 */
+ ltq_sys1_w32(0x00030001, SYS1_RBTR);
+ }
+
+ unreachable();
+}
+
+static void ltq_machine_halt(void)
+{
+ local_irq_disable();
+ unreachable();
+}
+
+static void ltq_machine_power_off(void)
+{
+ local_irq_disable();
+}
+
+static int __init mips_reboot_setup(void)
+{
+ _machine_restart = ltq_machine_restart;
+ _machine_halt = ltq_machine_halt;
+ pm_power_off = ltq_machine_power_off;
+ return 0;
+}
+
+arch_initcall(mips_reboot_setup);
diff --git a/arch/mips/lantiq/svip/sysctrl.c b/arch/mips/lantiq/svip/sysctrl.c
new file mode 100644
index 0000000..d2b636b
--- /dev/null
+++ b/arch/mips/lantiq/svip/sysctrl.c
@@ -0,0 +1,81 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2011-2012 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/ioport.h>
+#include <linux/export.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+
+#include <lantiq_soc.h>
+
+#include "../clk.h"
+#include "../prom.h"
+
+void __iomem *ltq_sys0_membase;
+void __iomem *ltq_sys1_membase;
+void __iomem *ltq_sys2_membase;
+void __iomem *ltq_status_membase;
+void __iomem *ltq_ebu_membase;
+
+/* bring up all register ranges that we need for basic system control */
+void __init ltq_soc_init(void)
+{
+ struct resource res_sys0, res_sys1, res_sys2, res_status, res_ebu;
+ struct device_node *np_sys0 =
+ of_find_compatible_node(NULL, NULL, "lantiq,sys0-svip");
+ struct device_node *np_sys1 =
+ of_find_compatible_node(NULL, NULL, "lantiq,sys1-svip");
+ struct device_node *np_sys2 =
+ of_find_compatible_node(NULL, NULL, "lantiq,sys2-svip");
+ struct device_node *np_status =
+ of_find_compatible_node(NULL, NULL, "lantiq,status-svip");
+ struct device_node *np_ebu =
+ of_find_compatible_node(NULL, NULL, "lantiq,ebu-svip");
+
+ /* check if all the core register ranges are available */
+ if (!np_sys0 || !np_sys1 || !np_sys2 || !np_status || !np_ebu)
+ panic("Failed to load core nodes from devicetree");
+
+ if (of_address_to_resource(np_sys0, 0, &res_sys0) ||
+ of_address_to_resource(np_sys1, 0, &res_sys1) ||
+ of_address_to_resource(np_sys2, 0, &res_sys2) ||
+ of_address_to_resource(np_status, 0, &res_status) ||
+ of_address_to_resource(np_ebu, 0, &res_ebu))
+ panic("Failed to get core resources");
+
+ if ((request_mem_region(res_sys0.start, resource_size(&res_sys0),
+ res_sys0.name) < 0) ||
+ (request_mem_region(res_sys1.start, resource_size(&res_sys1),
+ res_sys1.name) < 0) ||
+ (request_mem_region(res_sys2.start, resource_size(&res_sys2),
+ res_sys2.name) < 0) ||
+ (request_mem_region(res_status.start, resource_size(&res_status),
+ res_status.name) < 0) ||
+ (request_mem_region(res_ebu.start, resource_size(&res_ebu),
+ res_ebu.name) < 0))
+ pr_err("Failed to request core reources");
+
+ ltq_sys0_membase = ioremap_nocache(res_sys0.start,
+ resource_size(&res_sys0));
+ ltq_sys1_membase = ioremap_nocache(res_sys1.start,
+ resource_size(&res_sys1));
+ ltq_sys2_membase = ioremap_nocache(res_sys2.start,
+ resource_size(&res_sys2));
+ ltq_status_membase = ioremap_nocache(res_status.start,
+ resource_size(&res_status));
+ ltq_ebu_membase = ioremap_nocache(res_ebu.start,
+ resource_size(&res_ebu));
+ if (!ltq_sys0_membase || !ltq_sys1_membase || !ltq_sys2_membase ||
+ !ltq_status_membase || !ltq_ebu_membase)
+ panic("Failed to remap core resources");
+
+ clkdev_add_static(ltq_svip_cpu_hz(), ltq_svip_fpi_hz(),
+ ltq_svip_io_hz());
+}
--
1.7.10.4

View file

@ -0,0 +1,52 @@
From 05d6c964722224e8cf2902606744e29a835e7d5f Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 3 Dec 2012 21:35:01 +0100
Subject: [PATCH 102/123] MIPS: lantiq: add GPHY clock gate bits
Explicitly enable the clock gate of the internal GPHYs found on xrx200.
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/lantiq/xway/reset.c | 9 +++++++++
arch/mips/lantiq/xway/sysctrl.c | 1 +
2 files changed, 10 insertions(+)
diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
index 544dbb7..1fa0f17 100644
--- a/arch/mips/lantiq/xway/reset.c
+++ b/arch/mips/lantiq/xway/reset.c
@@ -78,10 +78,19 @@ static struct ltq_xrx200_gphy_reset {
/* reset and boot a gphy. these phys only exist on xrx200 SoC */
int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr)
{
+ struct clk *clk;
+
if (!of_device_is_compatible(ltq_rcu_np, "lantiq,rcu-xrx200")) {
dev_err(dev, "this SoC has no GPHY\n");
return -EINVAL;
}
+
+ clk = clk_get_sys("1f203000.rcu", "gphy");
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ clk_enable(clk);
+
if (id > 1) {
dev_err(dev, "%u is an invalid gphy id\n", id);
return -EINVAL;
diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
index 3925e66..6e0e135 100644
--- a/arch/mips/lantiq/xway/sysctrl.c
+++ b/arch/mips/lantiq/xway/sysctrl.c
@@ -374,6 +374,7 @@ void __init ltq_soc_init(void)
PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM |
PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
PMU_PPE_QSB | PMU_PPE_TOP);
+ clkdev_add_pmu("1f203000.rcu", "gphy", 0, PMU_GPHY);
} else if (of_machine_is_compatible("lantiq,ar9")) {
clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(),
ltq_ar9_fpi_hz());
--
1.7.10.4

View file

@ -0,0 +1,219 @@
From 8cbac4b30bed1552503b95bc0ac6276e3cdda9d8 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 30 Nov 2012 21:08:49 +0100
Subject: [PATCH 103/123] MIPS: lantiq: adds static clock for PP32
The Lantiq DSL SoCs have an internal networking processor. Add code to read
the static clock rate.
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/include/asm/mach-lantiq/lantiq.h | 1 +
arch/mips/lantiq/clk.c | 12 ++++++--
arch/mips/lantiq/clk.h | 7 ++++-
arch/mips/lantiq/falcon/sysctrl.c | 4 +--
arch/mips/lantiq/xway/clk.c | 43 ++++++++++++++++++++++++++++
arch/mips/lantiq/xway/sysctrl.c | 12 ++++----
6 files changed, 69 insertions(+), 10 deletions(-)
diff --git a/arch/mips/include/asm/mach-lantiq/lantiq.h b/arch/mips/include/asm/mach-lantiq/lantiq.h
index 5e8a6e9..76be7a0 100644
--- a/arch/mips/include/asm/mach-lantiq/lantiq.h
+++ b/arch/mips/include/asm/mach-lantiq/lantiq.h
@@ -41,6 +41,7 @@ extern void clk_deactivate(struct clk *clk);
extern struct clk *clk_get_cpu(void);
extern struct clk *clk_get_fpi(void);
extern struct clk *clk_get_io(void);
+extern struct clk *clk_get_ppe(void);
/* find out what bootsource we have */
extern unsigned char ltq_boot_select(void);
diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c
index 9128ff8..292ef1a 100644
--- a/arch/mips/lantiq/clk.c
+++ b/arch/mips/lantiq/clk.c
@@ -26,13 +26,15 @@
#include "prom.h"
/* lantiq socs have 3 static clocks */
-static struct clk cpu_clk_generic[3];
+static struct clk cpu_clk_generic[4];
-void clkdev_add_static(unsigned long cpu, unsigned long fpi, unsigned long io)
+void clkdev_add_static(unsigned long cpu, unsigned long fpi,
+ unsigned long io, unsigned long ppe)
{
cpu_clk_generic[0].rate = cpu;
cpu_clk_generic[1].rate = fpi;
cpu_clk_generic[2].rate = io;
+ cpu_clk_generic[3].rate = ppe;
}
struct clk *clk_get_cpu(void)
@@ -51,6 +53,12 @@ struct clk *clk_get_io(void)
return &cpu_clk_generic[2];
}
+struct clk *clk_get_ppe(void)
+{
+ return &cpu_clk_generic[3];
+}
+EXPORT_SYMBOL_GPL(clk_get_ppe);
+
static inline int clk_good(struct clk *clk)
{
return clk && !IS_ERR(clk);
diff --git a/arch/mips/lantiq/clk.h b/arch/mips/lantiq/clk.h
index c169e2b..4739366 100644
--- a/arch/mips/lantiq/clk.h
+++ b/arch/mips/lantiq/clk.h
@@ -27,12 +27,15 @@
#define CLOCK_167M 166666667
#define CLOCK_196_608M 196608000
#define CLOCK_200M 200000000
+#define CLOCK_222M 222000000
+#define CLOCK_240M 240000000
#define CLOCK_250M 250000000
#define CLOCK_266M 266666666
#define CLOCK_300M 300000000
#define CLOCK_333M 333333333
#define CLOCK_393M 393215332
#define CLOCK_400M 400000000
+#define CLOCK_450M 450000000
#define CLOCK_500M 500000000
#define CLOCK_600M 600000000
@@ -64,16 +67,18 @@ struct clk {
};
extern void clkdev_add_static(unsigned long cpu, unsigned long fpi,
- unsigned long io);
+ unsigned long io, unsigned long ppe);
extern unsigned long ltq_danube_cpu_hz(void);
extern unsigned long ltq_danube_fpi_hz(void);
+extern unsigned long ltq_danube_pp32_hz(void);
extern unsigned long ltq_ar9_cpu_hz(void);
extern unsigned long ltq_ar9_fpi_hz(void);
extern unsigned long ltq_vr9_cpu_hz(void);
extern unsigned long ltq_vr9_fpi_hz(void);
+extern unsigned long ltq_vr9_pp32_hz(void);
extern unsigned long ltq_svip_cpu_hz(void);
extern unsigned long ltq_svip_fpi_hz(void);
diff --git a/arch/mips/lantiq/falcon/sysctrl.c b/arch/mips/lantiq/falcon/sysctrl.c
index 2d4ced3..ff4894a 100644
--- a/arch/mips/lantiq/falcon/sysctrl.c
+++ b/arch/mips/lantiq/falcon/sysctrl.c
@@ -241,9 +241,9 @@ void __init ltq_soc_init(void)
/* get our 3 static rates for cpu, fpi and io clocks */
if (ltq_sys1_r32(SYS1_CPU0CC) & CPU0CC_CPUDIV)
- clkdev_add_static(CLOCK_200M, CLOCK_100M, CLOCK_200M);
+ clkdev_add_static(CLOCK_200M, CLOCK_100M, CLOCK_200M, 0);
else
- clkdev_add_static(CLOCK_400M, CLOCK_100M, CLOCK_200M);
+ clkdev_add_static(CLOCK_400M, CLOCK_100M, CLOCK_200M, 0);
/* add our clock domains */
clkdev_add_sys("1d810000.gpio", SYSCTL_SYSETH, ACTS_P0);
diff --git a/arch/mips/lantiq/xway/clk.c b/arch/mips/lantiq/xway/clk.c
index 9aa17f7..1ab576d 100644
--- a/arch/mips/lantiq/xway/clk.c
+++ b/arch/mips/lantiq/xway/clk.c
@@ -53,6 +53,29 @@ unsigned long ltq_danube_cpu_hz(void)
}
}
+unsigned long ltq_danube_pp32_hz(void)
+{
+ unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 7) & 3;
+ unsigned long clk;
+
+ switch (clksys) {
+ case 1:
+ clk = CLOCK_240M;
+ break;
+ case 2:
+ clk = CLOCK_222M;
+ break;
+ case 3:
+ clk = CLOCK_133M;
+ break;
+ default:
+ clk = CLOCK_266M;
+ break;
+ }
+
+ return clk;
+}
+
unsigned long ltq_ar9_sys_hz(void)
{
if (((ltq_cgu_r32(CGU_SYS) >> 3) & 0x3) == 0x2)
@@ -149,3 +172,23 @@ unsigned long ltq_vr9_fpi_hz(void)
return clk;
}
+
+unsigned long ltq_vr9_pp32_hz(void)
+{
+ unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 3;
+ unsigned long clk;
+
+ switch (clksys) {
+ case 1:
+ clk = CLOCK_450M;
+ break;
+ case 2:
+ clk = CLOCK_300M;
+ break;
+ default:
+ clk = CLOCK_500M;
+ break;
+ }
+
+ return clk;
+}
diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
index 6e0e135..75e1b7d 100644
--- a/arch/mips/lantiq/xway/sysctrl.c
+++ b/arch/mips/lantiq/xway/sysctrl.c
@@ -356,14 +356,16 @@ void __init ltq_soc_init(void)
if (of_machine_is_compatible("lantiq,ase")) {
if (ltq_cgu_r32(CGU_SYS) & (1 << 5))
- clkdev_add_static(CLOCK_266M, CLOCK_133M, CLOCK_133M);
+ clkdev_add_static(CLOCK_266M, CLOCK_133M,
+ CLOCK_133M, CLOCK_266M);
else
- clkdev_add_static(CLOCK_133M, CLOCK_133M, CLOCK_133M);
+ clkdev_add_static(CLOCK_133M, CLOCK_133M,
+ CLOCK_133M, CLOCK_133M);
clkdev_add_cgu("1e180000.etop", "ephycgu", CGU_EPHY),
clkdev_add_pmu("1e180000.etop", "ephy", 0, PMU_EPHY);
} else if (of_machine_is_compatible("lantiq,vr9")) {
clkdev_add_static(ltq_vr9_cpu_hz(), ltq_vr9_fpi_hz(),
- ltq_vr9_fpi_hz());
+ ltq_vr9_fpi_hz(), ltq_vr9_pp32_hz());
clkdev_add_pmu("1d900000.pcie", "phy", 1, PMU1_PCIE_PHY);
clkdev_add_pmu("1d900000.pcie", "bus", 0, PMU_PCIE_CLK);
clkdev_add_pmu("1d900000.pcie", "msi", 1, PMU1_PCIE_MSI);
@@ -377,10 +379,10 @@ void __init ltq_soc_init(void)
clkdev_add_pmu("1f203000.rcu", "gphy", 0, PMU_GPHY);
} else if (of_machine_is_compatible("lantiq,ar9")) {
clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(),
- ltq_ar9_fpi_hz());
+ ltq_ar9_fpi_hz(), CLOCK_250M);
clkdev_add_pmu("1e180000.etop", "switch", 0, PMU_SWITCH);
} else {
clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(),
- ltq_danube_fpi_hz());
+ ltq_danube_fpi_hz(), ltq_danube_pp32_hz());
}
}
--
1.7.10.4

View file

@ -0,0 +1,34 @@
From 07f7321c0f79c0b800d28898a480d044f839e813 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 6 Dec 2012 11:59:23 +0100
Subject: [PATCH 104/123] MIPS: lantiq: adds 4dword burst length for dma
---
arch/mips/lantiq/xway/dma.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c
index b5d76d1..986fbce 100644
--- a/arch/mips/lantiq/xway/dma.c
+++ b/arch/mips/lantiq/xway/dma.c
@@ -47,6 +47,7 @@
#define DMA_IRQ_ACK 0x7e /* IRQ status register */
#define DMA_POLL BIT(31) /* turn on channel polling */
#define DMA_CLK_DIV4 BIT(6) /* polling clock divider */
+#define DMA_4W_BURST BIT(2) /* 4 word burst length */
#define DMA_2W_BURST BIT(1) /* 2 word burst length */
#define DMA_MAX_CHANNEL 20 /* the soc has 20 channels */
#define DMA_ETOP_ENDIANESS (0xf << 8) /* endianess swap etop channels */
@@ -195,7 +196,8 @@ ltq_dma_init_port(int p)
* Tell the DMA engine to swap the endianess of data frames and
* drop packets if the channel arbitration fails.
*/
- ltq_dma_w32_mask(0, DMA_ETOP_ENDIANESS | DMA_PDEN,
+ ltq_dma_w32_mask(0, (DMA_4W_BURST << 4) | (DMA_4W_BURST << 2) |
+ DMA_ETOP_ENDIANESS | DMA_PDEN,
LTQ_DMA_PCTRL);
break;
--
1.7.10.4

View file

@ -0,0 +1,214 @@
From edd237c93d564e698e169a89d1b1b35248c5ef4a Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 3 Dec 2012 21:44:30 +0100
Subject: [PATCH 105/123] MIPS: lantiq: rework external irq code
This code makes the irqs used by the EIU loadable from the DT. Additionally we
add a helper that allows the pinctrl layer to map external irqs to real irq
numbers.
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/include/asm/mach-lantiq/lantiq.h | 1 +
arch/mips/lantiq/irq.c | 104 +++++++++++++++++++---------
2 files changed, 73 insertions(+), 32 deletions(-)
diff --git a/arch/mips/include/asm/mach-lantiq/lantiq.h b/arch/mips/include/asm/mach-lantiq/lantiq.h
index 76be7a0..f196cce 100644
--- a/arch/mips/include/asm/mach-lantiq/lantiq.h
+++ b/arch/mips/include/asm/mach-lantiq/lantiq.h
@@ -34,6 +34,7 @@ extern spinlock_t ebu_lock;
extern void ltq_disable_irq(struct irq_data *data);
extern void ltq_mask_and_ack_irq(struct irq_data *data);
extern void ltq_enable_irq(struct irq_data *data);
+extern int ltq_eiu_get_irq(int exin);
/* clock handling */
extern int clk_activate(struct clk *clk);
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index f36acd1..48407f6 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -33,17 +33,10 @@
/* register definitions - external irqs */
#define LTQ_EIU_EXIN_C 0x0000
#define LTQ_EIU_EXIN_INIC 0x0004
+#define LTQ_EIU_EXIN_INC 0x0008
#define LTQ_EIU_EXIN_INEN 0x000C
-/* irq numbers used by the external interrupt unit (EIU) */
-#define LTQ_EIU_IR0 (INT_NUM_IM4_IRL0 + 30)
-#define LTQ_EIU_IR1 (INT_NUM_IM3_IRL0 + 31)
-#define LTQ_EIU_IR2 (INT_NUM_IM1_IRL0 + 26)
-#define LTQ_EIU_IR3 INT_NUM_IM1_IRL0
-#define LTQ_EIU_IR4 (INT_NUM_IM1_IRL0 + 1)
-#define LTQ_EIU_IR5 (INT_NUM_IM1_IRL0 + 2)
-#define LTQ_EIU_IR6 (INT_NUM_IM2_IRL0 + 30)
-#define XWAY_EXIN_COUNT 3
+/* number of external interrupts */
#define MAX_EIU 6
/* the performance counter */
@@ -72,20 +65,19 @@
int gic_present;
#endif
-static unsigned short ltq_eiu_irq[MAX_EIU] = {
- LTQ_EIU_IR0,
- LTQ_EIU_IR1,
- LTQ_EIU_IR2,
- LTQ_EIU_IR3,
- LTQ_EIU_IR4,
- LTQ_EIU_IR5,
-};
-
static int exin_avail;
+static struct resource ltq_eiu_irq[MAX_EIU];
static void __iomem *ltq_icu_membase[MAX_IM];
static void __iomem *ltq_eiu_membase;
static struct irq_domain *ltq_domain;
+int ltq_eiu_get_irq(int exin)
+{
+ if (exin < exin_avail)
+ return ltq_eiu_irq[exin].start;
+ return -1;
+}
+
void ltq_disable_irq(struct irq_data *d)
{
u32 ier = LTQ_ICU_IM0_IER;
@@ -128,19 +120,64 @@ void ltq_enable_irq(struct irq_data *d)
ltq_icu_w32(im, ltq_icu_r32(im, ier) | BIT(offset), ier);
}
+static int ltq_eiu_settype(struct irq_data *d, unsigned int type)
+{
+ int i;
+
+ for (i = 0; i < MAX_EIU; i++) {
+ if (d->hwirq == ltq_eiu_irq[i].start) {
+ int val = 0;
+ int edge = 0;
+
+ switch (type) {
+ case IRQF_TRIGGER_NONE:
+ break;
+ case IRQF_TRIGGER_RISING:
+ val = 1;
+ edge = 1;
+ break;
+ case IRQF_TRIGGER_FALLING:
+ val = 2;
+ edge = 1;
+ break;
+ case IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING:
+ val = 3;
+ edge = 1;
+ break;
+ case IRQF_TRIGGER_HIGH:
+ val = 5;
+ break;
+ case IRQF_TRIGGER_LOW:
+ val = 6;
+ break;
+ default:
+ pr_err("invalid type %d for irq %ld\n", type, d->hwirq);
+ return -EINVAL;
+ }
+
+ if (edge)
+ irq_set_handler(d->hwirq, handle_edge_irq);
+
+ ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_C) |
+ (val << (i * 4)), LTQ_EIU_EXIN_C);
+ }
+ }
+
+ return 0;
+}
+
static unsigned int ltq_startup_eiu_irq(struct irq_data *d)
{
int i;
ltq_enable_irq(d);
for (i = 0; i < MAX_EIU; i++) {
- if (d->hwirq == ltq_eiu_irq[i]) {
- /* low level - we should really handle set_type */
- ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_C) |
- (0x6 << (i * 4)), LTQ_EIU_EXIN_C);
+ if (d->hwirq == ltq_eiu_irq[i].start) {
+ /* by default we are low level triggered */
+ ltq_eiu_settype(d, IRQF_TRIGGER_LOW);
/* clear all pending */
- ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INIC) & ~BIT(i),
- LTQ_EIU_EXIN_INIC);
+ ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INC) & ~BIT(i),
+ LTQ_EIU_EXIN_INC);
/* enable */
ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) | BIT(i),
LTQ_EIU_EXIN_INEN);
@@ -157,7 +194,7 @@ static void ltq_shutdown_eiu_irq(struct irq_data *d)
ltq_disable_irq(d);
for (i = 0; i < MAX_EIU; i++) {
- if (d->hwirq == ltq_eiu_irq[i]) {
+ if (d->hwirq == ltq_eiu_irq[i].start) {
/* disable */
ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) & ~BIT(i),
LTQ_EIU_EXIN_INEN);
@@ -186,6 +223,7 @@ static struct irq_chip ltq_eiu_type = {
.irq_ack = ltq_ack_irq,
.irq_mask = ltq_disable_irq,
.irq_mask_ack = ltq_mask_and_ack_irq,
+ .irq_set_type = ltq_eiu_settype,
};
static void ltq_hw_irqdispatch(int module)
@@ -301,7 +339,7 @@ static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
return 0;
for (i = 0; i < exin_avail; i++)
- if (hw == ltq_eiu_irq[i])
+ if (hw == ltq_eiu_irq[i].start)
chip = &ltq_eiu_type;
irq_set_chip_and_handler(hw, chip, handle_level_irq);
@@ -323,7 +361,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
{
struct device_node *eiu_node;
struct resource res;
- int i;
+ int i, ret;
for (i = 0; i < MAX_IM; i++) {
if (of_address_to_resource(node, i, &res))
@@ -340,17 +378,19 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
}
/* the external interrupts are optional and xway only */
- eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu");
+ eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu-xway");
if (eiu_node && !of_address_to_resource(eiu_node, 0, &res)) {
/* find out how many external irq sources we have */
- const __be32 *count = of_get_property(node,
- "lantiq,count", NULL);
+ exin_avail = of_irq_count(eiu_node);
- if (count)
- exin_avail = *count;
if (exin_avail > MAX_EIU)
exin_avail = MAX_EIU;
+ ret = of_irq_to_resource_table(eiu_node,
+ ltq_eiu_irq, exin_avail);
+ if (ret != exin_avail)
+ panic("failed to load external irq resources\n");
+
if (request_mem_region(res.start, resource_size(&res),
res.name) < 0)
pr_err("Failed to request eiu memory");
--
1.7.10.4

View file

@ -0,0 +1,106 @@
From 3aa46ed76b27df771f75db9c74ff011aca505fc5 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Wed, 5 Dec 2012 17:38:48 +0100
Subject: [PATCH 106/123] MIPS: lantiq: adds minimal dcdc driver
This driver so far only reads the core voltage.
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/lantiq/xway/Makefile | 2 +-
arch/mips/lantiq/xway/dcdc.c | 74 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 75 insertions(+), 1 deletion(-)
create mode 100644 arch/mips/lantiq/xway/dcdc.c
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
index 7a13660..087497d 100644
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1,3 +1,3 @@
-obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o
+obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o dcdc.o
obj-$(CONFIG_XRX200_PHY_FW) += xrx200_phy_fw.o
diff --git a/arch/mips/lantiq/xway/dcdc.c b/arch/mips/lantiq/xway/dcdc.c
new file mode 100644
index 0000000..0ac73a5
--- /dev/null
+++ b/arch/mips/lantiq/xway/dcdc.c
@@ -0,0 +1,74 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2010 Sameer Ahmad, Lantiq GmbH
+ */
+
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+
+#include <lantiq_soc.h>
+
+/* Bias and regulator Setup Register */
+#define DCDC_BIAS_VREG0 0xa
+/* Bias and regulator Setup Register */
+#define DCDC_BIAS_VREG1 0xb
+
+#define dcdc_w8(x, y) ltq_w8((x), dcdc_membase + (y))
+#define dcdc_r8(x) ltq_r8(dcdc_membase + (x))
+
+static void __iomem *dcdc_membase;
+
+static int __devinit dcdc_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Failed to get resource\n");
+ return -ENOMEM;
+ }
+
+ /* remap dcdc register range */
+ dcdc_membase = devm_request_and_ioremap(&pdev->dev, res);
+ if (!dcdc_membase) {
+ dev_err(&pdev->dev, "Failed to remap resource\n");
+ return -ENOMEM;
+ }
+
+ dev_info(&pdev->dev, "Core Voltage : %d mV\n", dcdc_r8(DCDC_BIAS_VREG1) * 8);
+
+ return 0;
+}
+
+static const struct of_device_id dcdc_match[] = {
+ { .compatible = "lantiq,dcdc-xrx200" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, dcdc_match);
+
+static struct platform_driver dcdc_driver = {
+ .probe = dcdc_probe,
+ .driver = {
+ .name = "dcdc-xrx200",
+ .owner = THIS_MODULE,
+ .of_match_table = dcdc_match,
+ },
+};
+
+int __init dcdc_init(void)
+{
+ int ret = platform_driver_register(&dcdc_driver);
+
+ if (ret)
+ pr_info("dcdc: Error registering platform driver\n");
+ return ret;
+}
+
+arch_initcall(dcdc_init);
--
1.7.10.4

View file

@ -0,0 +1,92 @@
From 84ce6d4b2802fd428a76e5f2692fd4c102ed35ea Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 30 Nov 2012 21:11:22 +0100
Subject: [PATCH 107/123] PINCTRL: lantiq: pinconf uses port instead of pin
The XWAY pinctrl driver invalidly uses the port and not the pin number to work
out the registeres and bits to be set for the opendrain and pullup/down
resistors.
Signed-off-by: John Crispin <blogic@openwrt.org>
---
drivers/pinctrl/pinctrl-xway.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c
index b9bcaec..48ab09b 100644
--- a/drivers/pinctrl/pinctrl-xway.c
+++ b/drivers/pinctrl/pinctrl-xway.c
@@ -441,17 +441,17 @@ static int xway_pinconf_get(struct pinctrl_dev *pctldev,
if (port == PORT3)
reg = GPIO3_OD;
else
- reg = GPIO_OD(port);
+ reg = GPIO_OD(pin);
*config = LTQ_PINCONF_PACK(param,
- !!gpio_getbit(info->membase[0], reg, PORT_PIN(port)));
+ !!gpio_getbit(info->membase[0], reg, PORT_PIN(pin)));
break;
case LTQ_PINCONF_PARAM_PULL:
if (port == PORT3)
reg = GPIO3_PUDEN;
else
- reg = GPIO_PUDEN(port);
- if (!gpio_getbit(info->membase[0], reg, PORT_PIN(port))) {
+ reg = GPIO_PUDEN(pin);
+ if (!gpio_getbit(info->membase[0], reg, PORT_PIN(pin))) {
*config = LTQ_PINCONF_PACK(param, 0);
break;
}
@@ -459,8 +459,8 @@ static int xway_pinconf_get(struct pinctrl_dev *pctldev,
if (port == PORT3)
reg = GPIO3_PUDSEL;
else
- reg = GPIO_PUDSEL(port);
- if (!gpio_getbit(info->membase[0], reg, PORT_PIN(port)))
+ reg = GPIO_PUDSEL(pin);
+ if (!gpio_getbit(info->membase[0], reg, PORT_PIN(pin)))
*config = LTQ_PINCONF_PACK(param, 2);
else
*config = LTQ_PINCONF_PACK(param, 1);
@@ -488,29 +488,29 @@ static int xway_pinconf_set(struct pinctrl_dev *pctldev,
if (port == PORT3)
reg = GPIO3_OD;
else
- reg = GPIO_OD(port);
- gpio_setbit(info->membase[0], reg, PORT_PIN(port));
+ reg = GPIO_OD(pin);
+ gpio_setbit(info->membase[0], reg, PORT_PIN(pin));
break;
case LTQ_PINCONF_PARAM_PULL:
if (port == PORT3)
reg = GPIO3_PUDEN;
else
- reg = GPIO_PUDEN(port);
+ reg = GPIO_PUDEN(pin);
if (arg == 0) {
- gpio_clearbit(info->membase[0], reg, PORT_PIN(port));
+ gpio_clearbit(info->membase[0], reg, PORT_PIN(pin));
break;
}
- gpio_setbit(info->membase[0], reg, PORT_PIN(port));
+ gpio_setbit(info->membase[0], reg, PORT_PIN(pin));
if (port == PORT3)
reg = GPIO3_PUDSEL;
else
- reg = GPIO_PUDSEL(port);
+ reg = GPIO_PUDSEL(pin);
if (arg == 1)
- gpio_clearbit(info->membase[0], reg, PORT_PIN(port));
+ gpio_clearbit(info->membase[0], reg, PORT_PIN(pin));
else if (arg == 2)
- gpio_setbit(info->membase[0], reg, PORT_PIN(port));
+ gpio_setbit(info->membase[0], reg, PORT_PIN(pin));
else
dev_err(pctldev->dev, "Invalid pull value %d\n", arg);
break;
--
1.7.10.4

View file

@ -0,0 +1,281 @@
From 13e754b5fff5be1930e2b8fe534a52b608c9e479 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 3 Dec 2012 19:27:28 +0100
Subject: [PATCH] PINCTRL: lantiq: fixes
---
drivers/pinctrl/pinctrl-lantiq.c | 54 ++++++++++++++++++-----------
drivers/pinctrl/pinctrl-lantiq.h | 1 +
drivers/pinctrl/pinctrl-xway.c | 70 ++++++++++++++++++++++++++++++++++----
3 files changed, 99 insertions(+), 26 deletions(-)
Index: linux-3.7-rc8/drivers/pinctrl/pinctrl-lantiq.c
===================================================================
--- linux-3.7-rc8.orig/drivers/pinctrl/pinctrl-lantiq.c 2012-12-03 20:22:37.000000000 +0100
+++ linux-3.7-rc8/drivers/pinctrl/pinctrl-lantiq.c 2012-12-14 22:59:40.687563565 +0100
@@ -64,11 +64,13 @@
seq_printf(s, " %s", dev_name(pctldev->dev));
}
-static int ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
+static void ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
struct device_node *np,
struct pinctrl_map **map)
{
struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctldev);
+ struct property *pins = of_find_property(np, "lantiq,pins", NULL);
+ struct property *groups = of_find_property(np, "lantiq,groups", NULL);
unsigned long configs[3];
unsigned num_configs = 0;
struct property *prop;
@@ -76,8 +78,20 @@
const char *function;
int ret, i;
+ if (!pins && !groups) {
+ dev_err(pctldev->dev, "%s defines neither pins nor groups\n",
+ np->name);
+ return;
+ }
+
+ if (pins && groups) {
+ dev_err(pctldev->dev, "%s defines both pins and groups\n",
+ np->name);
+ return;
+ }
+
ret = of_property_read_string(np, "lantiq,function", &function);
- if (!ret) {
+ if (groups && !ret) {
of_property_for_each_string(np, "lantiq,groups", prop, group) {
(*map)->type = PIN_MAP_TYPE_MUX_GROUP;
(*map)->name = function;
@@ -85,11 +99,6 @@
(*map)->data.mux.function = function;
(*map)++;
}
- if (of_find_property(np, "lantiq,pins", NULL))
- dev_err(pctldev->dev,
- "%s mixes pins and groups settings\n",
- np->name);
- return 0;
}
for (i = 0; i < info->num_params; i++) {
@@ -103,7 +112,7 @@
}
if (!num_configs)
- return -EINVAL;
+ return;
of_property_for_each_string(np, "lantiq,pins", prop, pin) {
(*map)->data.configs.configs = kmemdup(configs,
@@ -115,7 +124,16 @@
(*map)->data.configs.num_configs = num_configs;
(*map)++;
}
- return 0;
+ of_property_for_each_string(np, "lantiq,groups", prop, group) {
+ (*map)->data.configs.configs = kmemdup(configs,
+ num_configs * sizeof(unsigned long),
+ GFP_KERNEL);
+ (*map)->type = PIN_MAP_TYPE_CONFIGS_GROUP;
+ (*map)->name = group;
+ (*map)->data.configs.group_or_pin = group;
+ (*map)->data.configs.num_configs = num_configs;
+ (*map)++;
+ }
}
static int ltq_pinctrl_dt_subnode_size(struct device_node *np)
@@ -135,23 +153,19 @@
{
struct pinctrl_map *tmp;
struct device_node *np;
- int ret;
+ int max_maps = 0;
- *num_maps = 0;
for_each_child_of_node(np_config, np)
- *num_maps += ltq_pinctrl_dt_subnode_size(np);
- *map = kzalloc(*num_maps * sizeof(struct pinctrl_map), GFP_KERNEL);
+ max_maps += ltq_pinctrl_dt_subnode_size(np);
+ *map = kzalloc(max_maps * sizeof(struct pinctrl_map) * 2, GFP_KERNEL);
if (!*map)
return -ENOMEM;
tmp = *map;
- for_each_child_of_node(np_config, np) {
- ret = ltq_pinctrl_dt_subnode_to_map(pctldev, np, &tmp);
- if (ret < 0) {
- ltq_pinctrl_dt_free_map(pctldev, *map, *num_maps);
- return ret;
- }
- }
+ for_each_child_of_node(np_config, np)
+ ltq_pinctrl_dt_subnode_to_map(pctldev, np, &tmp);
+ *num_maps = ((int)(tmp - *map));
+
return 0;
}
Index: linux-3.7-rc8/drivers/pinctrl/pinctrl-lantiq.h
===================================================================
--- linux-3.7-rc8.orig/drivers/pinctrl/pinctrl-lantiq.h 2012-12-03 20:22:37.000000000 +0100
+++ linux-3.7-rc8/drivers/pinctrl/pinctrl-lantiq.h 2012-12-14 22:55:26.591557194 +0100
@@ -34,6 +34,7 @@
LTQ_PINCONF_PARAM_OPEN_DRAIN,
LTQ_PINCONF_PARAM_DRIVE_CURRENT,
LTQ_PINCONF_PARAM_SLEW_RATE,
+ LTQ_PINCONF_PARAM_OUTPUT,
};
struct ltq_cfg_param {
Index: linux-3.7-rc8/drivers/pinctrl/pinctrl-xway.c
===================================================================
--- linux-3.7-rc8.orig/drivers/pinctrl/pinctrl-xway.c 2012-12-14 22:55:26.567557195 +0100
+++ linux-3.7-rc8/drivers/pinctrl/pinctrl-xway.c 2012-12-14 22:55:26.595557195 +0100
@@ -443,7 +443,7 @@
else
reg = GPIO_OD(pin);
*config = LTQ_PINCONF_PACK(param,
- !!gpio_getbit(info->membase[0], reg, PORT_PIN(pin)));
+ !gpio_getbit(info->membase[0], reg, PORT_PIN(pin)));
break;
case LTQ_PINCONF_PARAM_PULL:
@@ -466,6 +466,11 @@
*config = LTQ_PINCONF_PACK(param, 1);
break;
+ case LTQ_PINCONF_PARAM_OUTPUT:
+ reg = GPIO_DIR(pin);
+ *config = LTQ_PINCONF_PACK(param,
+ gpio_getbit(info->membase[0], reg, PORT_PIN(pin)));
+ break;
default:
dev_err(pctldev->dev, "Invalid config param %04x\n", param);
return -ENOTSUPP;
@@ -489,7 +494,10 @@
reg = GPIO3_OD;
else
reg = GPIO_OD(pin);
- gpio_setbit(info->membase[0], reg, PORT_PIN(pin));
+ if (arg == 0)
+ gpio_setbit(info->membase[0], reg, PORT_PIN(pin));
+ else
+ gpio_clearbit(info->membase[0], reg, PORT_PIN(pin));
break;
case LTQ_PINCONF_PARAM_PULL:
@@ -515,6 +523,14 @@
dev_err(pctldev->dev, "Invalid pull value %d\n", arg);
break;
+ case LTQ_PINCONF_PARAM_OUTPUT:
+ reg = GPIO_DIR(pin);
+ if (arg == 0)
+ gpio_clearbit(info->membase[0], reg, PORT_PIN(pin));
+ else
+ gpio_setbit(info->membase[0], reg, PORT_PIN(pin));
+ break;
+
default:
dev_err(pctldev->dev, "Invalid config param %04x\n", param);
return -ENOTSUPP;
@@ -522,9 +538,25 @@
return 0;
}
+int xway_pinconf_group_set(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ unsigned long config)
+{
+ struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctldev);
+ int i, ret = 0;
+
+ for (i = 0; i < info->grps[selector].npins && !ret; i++)
+ ret = xway_pinconf_set(pctldev,
+ info->grps[selector].pins[i], config);
+
+ return ret;
+}
+
+
struct pinconf_ops xway_pinconf_ops = {
.pin_config_get = xway_pinconf_get,
.pin_config_set = xway_pinconf_set,
+ .pin_config_group_set = xway_pinconf_group_set,
};
static struct pinctrl_desc xway_pctrl_desc = {
@@ -532,10 +564,9 @@
.confops = &xway_pinconf_ops,
};
-static inline int xway_mux_apply(struct pinctrl_dev *pctrldev,
+static int mux_apply(struct ltq_pinmux_info *info,
int pin, int mux)
{
- struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
int port = PORT(pin);
u32 alt1_reg = GPIO_ALT1(pin);
@@ -555,9 +586,18 @@
return 0;
}
+static inline int xway_mux_apply(struct pinctrl_dev *pctrldev,
+ int pin, int mux)
+{
+ struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+
+ return mux_apply(info, pin, mux);
+}
+
static const struct ltq_cfg_param xway_cfg_params[] = {
{"lantiq,pull", LTQ_PINCONF_PARAM_PULL},
{"lantiq,open-drain", LTQ_PINCONF_PARAM_OPEN_DRAIN},
+ {"lantiq,output", LTQ_PINCONF_PARAM_OUTPUT},
};
static struct ltq_pinmux_info xway_info = {
@@ -598,6 +638,10 @@
{
struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev);
+ if (PORT(pin) == PORT3)
+ gpio_setbit(info->membase[0], GPIO3_OD, PORT_PIN(pin));
+ else
+ gpio_setbit(info->membase[0], GPIO_OD(pin), PORT_PIN(pin));
gpio_setbit(info->membase[0], GPIO_DIR(pin), PORT_PIN(pin));
xway_gpio_set(chip, pin, val);
@@ -618,6 +662,18 @@
pinctrl_free_gpio(gpio);
}
+static int xway_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev);
+ int i;
+
+ for (i = 0; i < info->num_exin; i++)
+ if (info->exin[i] == offset)
+ return ltq_eiu_get_irq(i);
+
+ return -1;
+}
+
static struct gpio_chip xway_chip = {
.label = "gpio-xway",
.direction_input = xway_gpio_dir_in,
@@ -626,6 +682,7 @@
.set = xway_gpio_set,
.request = xway_gpio_req,
.free = xway_gpio_free,
+ .to_irq = xway_gpio_to_irq,
.base = -1,
};

View file

@ -0,0 +1,404 @@
From d4911be1cc44c8d3ca72b03d5da13f792d4a02d2 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sat, 23 Jun 2012 15:32:33 +0200
Subject: [PATCH 109/123] GPIO: MIPS: add gpio driver for falcon SoC
Add driver for GPIO blocks found on Lantiq FALCON SoC. The SoC has 5 banks of
up to 32 pads. The GPIO blocks have a per pin IRQs.
Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
Cc: linux-kernel@vger.kernel.org
---
drivers/gpio/Kconfig | 5 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-falcon.c | 349 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 355 insertions(+)
create mode 100644 drivers/gpio/gpio-falcon.c
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 47150f5..0647e07 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -114,6 +114,11 @@ config GPIO_EP93XX
depends on ARCH_EP93XX
select GPIO_GENERIC
+config GPIO_FALCON
+ def_bool y
+ depends on MIPS && SOC_FALCON
+ select GPIO_GENERIC
+
config GPIO_MM_LANTIQ
bool "Lantiq Memory mapped GPIOs"
depends on LANTIQ && SOC_XWAY
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 9aeed67..2a9e4a2 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o
obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o
obj-$(CONFIG_GPIO_EM) += gpio-em.o
obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
+obj-$(CONFIG_GPIO_FALCON) += gpio-falcon.o
obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
obj-$(CONFIG_GPIO_ICH) += gpio-ich.o
obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o
diff --git a/drivers/gpio/gpio-falcon.c b/drivers/gpio/gpio-falcon.c
new file mode 100644
index 0000000..ae8b55d
--- /dev/null
+++ b/drivers/gpio/gpio-falcon.c
@@ -0,0 +1,349 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2012 Thomas Langer <thomas.langer@lantiq.com>
+ * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+
+#include <lantiq_soc.h>
+
+/* Data Output Register */
+#define GPIO_OUT 0x00000000
+/* Data Input Register */
+#define GPIO_IN 0x00000004
+/* Direction Register */
+#define GPIO_DIR 0x00000008
+/* External Interrupt Control Register 0 */
+#define GPIO_EXINTCR0 0x00000018
+/* External Interrupt Control Register 1 */
+#define GPIO_EXINTCR1 0x0000001C
+/* IRN Capture Register */
+#define GPIO_IRNCR 0x00000020
+/* IRN Interrupt Configuration Register */
+#define GPIO_IRNCFG 0x0000002C
+/* IRN Interrupt Enable Set Register */
+#define GPIO_IRNRNSET 0x00000030
+/* IRN Interrupt Enable Clear Register */
+#define GPIO_IRNENCLR 0x00000034
+/* Output Set Register */
+#define GPIO_OUTSET 0x00000040
+/* Output Cler Register */
+#define GPIO_OUTCLR 0x00000044
+/* Direction Clear Register */
+#define GPIO_DIRSET 0x00000048
+/* Direction Set Register */
+#define GPIO_DIRCLR 0x0000004C
+
+/* turn a gpio_chip into a falcon_gpio_port */
+#define ctop(c) container_of(c, struct falcon_gpio_port, gpio_chip)
+/* turn a irq_data into a falcon_gpio_port */
+#define itop(i) ((struct falcon_gpio_port *) irq_get_chip_data(i->irq))
+
+#define port_r32(p, reg) ltq_r32(p->port + reg)
+#define port_w32(p, val, reg) ltq_w32(val, p->port + reg)
+#define port_w32_mask(p, clear, set, reg) \
+ port_w32(p, (port_r32(p, reg) & ~(clear)) | (set), reg)
+
+#define MAX_PORTS 5
+#define PINS_PER_PORT 32
+
+struct falcon_gpio_port {
+ struct gpio_chip gpio_chip;
+ void __iomem *port;
+ unsigned int irq_base;
+ unsigned int chained_irq;
+ struct clk *clk;
+ char name[6];
+};
+
+static int falcon_gpio_direction_input(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ port_w32(ctop(chip), 1 << offset, GPIO_DIRCLR);
+
+ return 0;
+}
+
+static void falcon_gpio_set(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ if (value)
+ port_w32(ctop(chip), 1 << offset, GPIO_OUTSET);
+ else
+ port_w32(ctop(chip), 1 << offset, GPIO_OUTCLR);
+}
+
+static int falcon_gpio_direction_output(struct gpio_chip *chip,
+ unsigned int offset, int value)
+{
+ falcon_gpio_set(chip, offset, value);
+ port_w32(ctop(chip), 1 << offset, GPIO_DIRSET);
+
+ return 0;
+}
+
+static int falcon_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ if ((port_r32(ctop(chip), GPIO_DIR) >> offset) & 1)
+ return (port_r32(ctop(chip), GPIO_OUT) >> offset) & 1;
+ else
+ return (port_r32(ctop(chip), GPIO_IN) >> offset) & 1;
+}
+
+static int falcon_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ int gpio = chip->base + offset;
+
+ return pinctrl_request_gpio(gpio);
+}
+
+static void falcon_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+ int gpio = chip->base + offset;
+
+ pinctrl_free_gpio(gpio);
+}
+
+static int falcon_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ return ctop(chip)->irq_base + offset;
+}
+
+static void falcon_gpio_disable_irq(struct irq_data *d)
+{
+ unsigned int offset = d->irq - itop(d)->irq_base;
+
+ port_w32(itop(d), 1 << offset, GPIO_IRNENCLR);
+}
+
+static void falcon_gpio_enable_irq(struct irq_data *d)
+{
+ unsigned int offset = d->irq - itop(d)->irq_base;
+
+ port_w32(itop(d), 1 << offset, GPIO_IRNRNSET);
+}
+
+static void falcon_gpio_ack_irq(struct irq_data *d)
+{
+ unsigned int offset = d->irq - itop(d)->irq_base;
+
+ port_w32(itop(d), 1 << offset, GPIO_IRNCR);
+}
+
+static void falcon_gpio_mask_and_ack_irq(struct irq_data *d)
+{
+ unsigned int offset = d->irq - itop(d)->irq_base;
+
+ port_w32(itop(d), 1 << offset, GPIO_IRNENCLR);
+ port_w32(itop(d), 1 << offset, GPIO_IRNCR);
+}
+
+static struct irq_chip falcon_gpio_irq_chip;
+static int falcon_gpio_irq_type(struct irq_data *d, unsigned int type)
+{
+ unsigned int offset = d->irq - itop(d)->irq_base;
+ unsigned int mask = 1 << offset;
+
+ if ((type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_NONE)
+ return 0;
+
+ if ((type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) != 0) {
+ /* level triggered */
+ port_w32_mask(itop(d), 0, mask, GPIO_IRNCFG);
+ irq_set_chip_and_handler_name(d->irq,
+ &falcon_gpio_irq_chip, handle_level_irq, "mux");
+ } else {
+ /* edge triggered */
+ port_w32_mask(itop(d), mask, 0, GPIO_IRNCFG);
+ irq_set_chip_and_handler_name(d->irq,
+ &falcon_gpio_irq_chip, handle_simple_irq, "mux");
+ }
+
+ if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
+ port_w32_mask(itop(d), mask, 0, GPIO_EXINTCR0);
+ port_w32_mask(itop(d), 0, mask, GPIO_EXINTCR1);
+ } else {
+ if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)) != 0)
+ /* positive logic: rising edge, high level */
+ port_w32_mask(itop(d), mask, 0, GPIO_EXINTCR0);
+ else
+ /* negative logic: falling edge, low level */
+ port_w32_mask(itop(d), 0, mask, GPIO_EXINTCR0);
+ port_w32_mask(itop(d), mask, 0, GPIO_EXINTCR1);
+ }
+
+ return gpio_direction_input(itop(d)->gpio_chip.base + offset);
+}
+
+static void falcon_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+ struct falcon_gpio_port *gpio_port = irq_desc_get_handler_data(desc);
+ unsigned long irncr;
+ int offset;
+
+ /* acknowledge interrupt */
+ irncr = port_r32(gpio_port, GPIO_IRNCR);
+ port_w32(gpio_port, irncr, GPIO_IRNCR);
+
+ desc->irq_data.chip->irq_ack(&desc->irq_data);
+
+ for_each_set_bit(offset, &irncr, gpio_port->gpio_chip.ngpio)
+ generic_handle_irq(gpio_port->irq_base + offset);
+}
+
+static int falcon_gpio_irq_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
+{
+ struct falcon_gpio_port *port = d->host_data;
+
+ irq_set_chip_and_handler_name(irq, &falcon_gpio_irq_chip,
+ handle_simple_irq, "mux");
+ irq_set_chip_data(irq, port);
+
+ /* set to negative logic (falling edge, low level) */
+ port_w32_mask(port, 0, 1 << hw, GPIO_EXINTCR0);
+ return 0;
+}
+
+static struct irq_chip falcon_gpio_irq_chip = {
+ .name = "gpio_irq_mux",
+ .irq_mask = falcon_gpio_disable_irq,
+ .irq_unmask = falcon_gpio_enable_irq,
+ .irq_ack = falcon_gpio_ack_irq,
+ .irq_mask_ack = falcon_gpio_mask_and_ack_irq,
+ .irq_set_type = falcon_gpio_irq_type,
+};
+
+static const struct irq_domain_ops irq_domain_ops = {
+ .xlate = irq_domain_xlate_onetwocell,
+ .map = falcon_gpio_irq_map,
+};
+
+static struct irqaction gpio_cascade = {
+ .handler = no_action,
+ .flags = IRQF_DISABLED,
+ .name = "gpio_cascade",
+};
+
+static int falcon_gpio_probe(struct platform_device *pdev)
+{
+ struct pinctrl_gpio_range *gpio_range;
+ struct device_node *node = pdev->dev.of_node;
+ const __be32 *bank = of_get_property(node, "lantiq,bank", NULL);
+ struct falcon_gpio_port *gpio_port;
+ struct resource *gpiores, irqres;
+ int ret, size;
+
+ if (!bank || *bank >= MAX_PORTS)
+ return -ENODEV;
+
+ size = pinctrl_falcon_get_range_size(*bank);
+ if (size < 1) {
+ dev_err(&pdev->dev, "pad not loaded for bank %d\n", *bank);
+ return size;
+ }
+
+ gpiores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!gpiores)
+ return -ENODEV;
+
+ gpio_range = devm_kzalloc(&pdev->dev, sizeof(struct pinctrl_gpio_range),
+ GFP_KERNEL);
+ if (!gpio_range)
+ return -ENOMEM;
+
+ gpio_port = devm_kzalloc(&pdev->dev, sizeof(struct falcon_gpio_port),
+ GFP_KERNEL);
+ if (!gpio_port)
+ return -ENOMEM;
+ snprintf(gpio_port->name, 6, "gpio%d", *bank);
+ gpio_port->gpio_chip.label = gpio_port->name;
+ gpio_port->gpio_chip.direction_input = falcon_gpio_direction_input;
+ gpio_port->gpio_chip.direction_output = falcon_gpio_direction_output;
+ gpio_port->gpio_chip.get = falcon_gpio_get;
+ gpio_port->gpio_chip.set = falcon_gpio_set;
+ gpio_port->gpio_chip.request = falcon_gpio_request;
+ gpio_port->gpio_chip.free = falcon_gpio_free;
+ gpio_port->gpio_chip.base = -1;
+ gpio_port->gpio_chip.ngpio = size;
+ gpio_port->gpio_chip.dev = &pdev->dev;
+
+ gpio_port->port = devm_request_and_ioremap(&pdev->dev, gpiores);
+ if (!gpio_port->port) {
+ dev_err(&pdev->dev, "Could not map io ranges\n");
+ return -ENOMEM;
+ }
+
+ gpio_port->clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(gpio_port->clk)) {
+ dev_err(&pdev->dev, "Could not get clock\n");
+ return PTR_ERR(gpio_port->clk);
+ }
+ clk_enable(gpio_port->clk);
+
+ if (of_irq_to_resource_table(node, &irqres, 1) == 1) {
+ gpio_port->irq_base = INT_NUM_EXTRA_START + (32 * *bank);
+ gpio_port->gpio_chip.to_irq = falcon_gpio_to_irq;
+ gpio_port->chained_irq = irqres.start;
+ irq_domain_add_legacy(node, size, gpio_port->irq_base, 0,
+ &irq_domain_ops, gpio_port);
+ setup_irq(irqres.start, &gpio_cascade);
+ irq_set_handler_data(irqres.start, gpio_port);
+ irq_set_chained_handler(irqres.start, falcon_gpio_irq_handler);
+ }
+
+ ret = gpiochip_add(&gpio_port->gpio_chip);
+ if (!ret)
+ platform_set_drvdata(pdev, gpio_port);
+
+ gpio_range->name = "FALCON GPIO";
+ gpio_range->id = *bank;
+ gpio_range->base = gpio_port->gpio_chip.base;
+ gpio_range->npins = gpio_port->gpio_chip.ngpio;
+ gpio_range->gc = &gpio_port->gpio_chip;
+ pinctrl_falcon_add_gpio_range(gpio_range);
+
+ return ret;
+}
+
+static const struct of_device_id falcon_gpio_match[] = {
+ { .compatible = "lantiq,gpio-falcon" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, falcon_gpio_match);
+
+static struct platform_driver falcon_gpio_driver = {
+ .probe = falcon_gpio_probe,
+ .driver = {
+ .name = "gpio-falcon",
+ .owner = THIS_MODULE,
+ .of_match_table = falcon_gpio_match,
+ },
+};
+
+int __init falcon_gpio_init(void)
+{
+ int ret;
+
+ pr_info("FALC(tm) ON GPIO Driver, (C) 2012 Lantiq Deutschland Gmbh\n");
+ ret = platform_driver_register(&falcon_gpio_driver);
+ if (ret)
+ pr_err("falcon_gpio: Error registering platform driver!");
+ return ret;
+}
+
+subsys_initcall(falcon_gpio_init);
--
1.7.10.4

View file

@ -0,0 +1,39 @@
From ed881db69430dd62765d02e2f4f1321ddc2f5fb5 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 20 Jul 2012 18:58:34 +0200
Subject: [PATCH 110/123] Document: devicetree: add OF documents for lantiq
serial port
Signed-off-by: John Crispin <blogic@openwrt.org>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: devicetree-discuss@lists.ozlabs.org
---
.../devicetree/bindings/serial/lantiq_asc.txt | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
create mode 100644 Documentation/devicetree/bindings/serial/lantiq_asc.txt
diff --git a/Documentation/devicetree/bindings/serial/lantiq_asc.txt b/Documentation/devicetree/bindings/serial/lantiq_asc.txt
new file mode 100644
index 0000000..5b78591
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/lantiq_asc.txt
@@ -0,0 +1,16 @@
+Lantiq SoC ASC serial controller
+
+Required properties:
+- compatible : Should be "lantiq,asc"
+- reg : Address and length of the register set for the device
+- interrupts: the 3 (tx rx err) interrupt numbers. The interrupt specifier
+ depends on the interrupt-parent interrupt controller.
+
+Example:
+
+asc1: serial@E100C00 {
+ compatible = "lantiq,asc";
+ reg = <0xE100C00 0x400>;
+ interrupt-parent = <&icu0>;
+ interrupts = <112 113 114>;
+};
--
1.7.10.4

View file

@ -0,0 +1,139 @@
From 72112b91624dca6c636bd3a592471642d3988b27 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 20 Jul 2012 19:09:01 +0200
Subject: [PATCH 111/123] MTD: MIPS: lantiq: Add NAND support on Lantiq FALCON
SoC.
The driver uses plat_nand. As the platform_device is loaded from DT, we need
to lookup the node and attach our falocn specific "struct platform_nand_data"
to it.
Signed-off-by: John Crispin <blogic@openwrt.org>
Cc: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Cc: linux-mtd@lists.infradead.org
---
drivers/mtd/nand/Kconfig | 8 ++++
drivers/mtd/nand/Makefile | 1 +
drivers/mtd/nand/falcon_nand.c | 82 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 91 insertions(+)
create mode 100644 drivers/mtd/nand/falcon_nand.c
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 4883139..a3b05be 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -572,4 +572,12 @@ config MTD_NAND_XWAY
Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached
to the External Bus Unit (EBU).
+config MTD_NAND_FALCON
+ tristate "Support for NAND on Lantiq FALC-ON SoC"
+ depends on LANTIQ && SOC_FALCON
+ select MTD_NAND_PLATFORM
+ help
+ Enables support for NAND Flash chips on Lantiq FALC-ON SoCs. NAND is
+ attached to the External Bus Unit (EBU).
+
endif # MTD_NAND
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 2cbd091..a97e1b5 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -53,5 +53,6 @@ obj-$(CONFIG_MTD_NAND_RICOH) += r852.o
obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o
obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/
obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o
+obj-$(CONFIG_MTD_NAND_FALCON) += falcon_nand.o
nand-objs := nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/falcon_nand.c b/drivers/mtd/nand/falcon_nand.c
new file mode 100644
index 0000000..b3b850c
--- /dev/null
+++ b/drivers/mtd/nand/falcon_nand.c
@@ -0,0 +1,82 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2011 Thomas Langer <thomas.langer@lantiq.com>
+ * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/mtd/nand.h>
+#include <linux/of_platform.h>
+
+#include <lantiq_soc.h>
+
+/* nand flash */
+/* address lines used for NAND control signals */
+#define NAND_ADDR_ALE 0x10000
+#define NAND_ADDR_CLE 0x20000
+/* Ready/Busy Status */
+#define MODCON_STS 0x0002
+/* Ready/Busy Status Edge */
+#define MODCON_STSEDGE 0x0004
+#define LTQ_EBU_MODCON 0x000C
+
+static const char *part_probes[] = { "cmdlinepart", "ofpart", NULL };
+
+static int falcon_nand_ready(struct mtd_info *mtd)
+{
+ u32 modcon = ltq_ebu_r32(LTQ_EBU_MODCON);
+
+ return (((modcon & (MODCON_STS | MODCON_STSEDGE)) ==
+ (MODCON_STS | MODCON_STSEDGE)));
+}
+
+static void falcon_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+ struct nand_chip *this = mtd->priv;
+ unsigned long nandaddr = (unsigned long) this->IO_ADDR_W;
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ nandaddr &= ~(NAND_ADDR_ALE | NAND_ADDR_CLE);
+
+ if (ctrl & NAND_CLE)
+ nandaddr |= NAND_ADDR_CLE;
+ if (ctrl & NAND_ALE)
+ nandaddr |= NAND_ADDR_ALE;
+
+ this->IO_ADDR_W = (void __iomem *) nandaddr;
+ }
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
+}
+
+static struct platform_nand_data falcon_nand_data = {
+ .chip = {
+ .nr_chips = 1,
+ .chip_delay = 25,
+ .part_probe_types = part_probes,
+ },
+ .ctrl = {
+ .cmd_ctrl = falcon_hwcontrol,
+ .dev_ready = falcon_nand_ready,
+ }
+};
+
+static int __init falcon_register_nand(void)
+{
+ struct device_node *node;
+ struct platform_device *pdev;
+
+ node = of_find_compatible_node(NULL, NULL, "lantiq,nand-falcon");
+ if (!node)
+ return -1;
+ pdev = of_find_device_by_node(node);
+ if (pdev)
+ pdev->dev.platform_data = &falcon_nand_data;
+ of_node_put(node);
+ return 0;
+}
+
+arch_initcall(falcon_register_nand);
--
1.7.10.4

View file

@ -0,0 +1,47 @@
From d8d9b9055d704d6f84ef6346d6826b8a9640f209 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 22 Oct 2012 10:25:39 +0200
Subject: [PATCH 112/123] MTD: lantiq: xway: fix NAND reset timeout handling
Fixes a possible deadlock in the code that resets the NAND flash.
http://lists.infradead.org/pipermail/linux-mtd/2012-September/044240.html
Signed-off-by: John Crispin <blogic@openwrt.org>
---
drivers/mtd/nand/xway_nand.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/xway_nand.c b/drivers/mtd/nand/xway_nand.c
index 3f81dc8..4731300 100644
--- a/drivers/mtd/nand/xway_nand.c
+++ b/drivers/mtd/nand/xway_nand.c
@@ -58,15 +58,23 @@ static void xway_reset_chip(struct nand_chip *chip)
{
unsigned long nandaddr = (unsigned long) chip->IO_ADDR_W;
unsigned long flags;
+ unsigned long timeout;
nandaddr &= ~NAND_WRITE_ADDR;
nandaddr |= NAND_WRITE_CMD;
/* finish with a reset */
+ timeout = jiffies + msecs_to_jiffies(200);
+
spin_lock_irqsave(&ebu_lock, flags);
+
writeb(NAND_WRITE_CMD_RESET, (void __iomem *) nandaddr);
- while ((ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0)
- ;
+ do {
+ if ((ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0)
+ break;
+ cond_resched();
+ } while (!time_after_eq(jiffies, timeout));
+
spin_unlock_irqrestore(&ebu_lock, flags);
}
--
1.7.10.4

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,228 @@
From 12f4b99d63edc15849357c09e22a36445c2752cc Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 22 Oct 2012 09:28:30 +0200
Subject: [PATCH 115/123] NET: PHY: adds driver for lantiq PHY11G
Signed-off-by: John Crispin <blogic@openwrt.org>
---
drivers/net/phy/Kconfig | 5 ++
drivers/net/phy/Makefile | 1 +
drivers/net/phy/lantiq.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 184 insertions(+)
create mode 100644 drivers/net/phy/lantiq.c
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 961f0b2..41a2992 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -107,6 +107,11 @@ config MICREL_PHY
---help---
Supports the KSZ9021, VSC8201, KS8001 PHYs.
+config LANTIQ_PHY
+ tristate "Driver for Lantiq PHYs"
+ ---help---
+ Supports the 11G and 22E PHYs.
+
config FIXED_PHY
bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
depends on PHYLIB=y
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 9645e38..e2eeee3 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_NATIONAL_PHY) += national.o
obj-$(CONFIG_DP83640_PHY) += dp83640.o
obj-$(CONFIG_STE10XP) += ste10Xp.o
obj-$(CONFIG_MICREL_PHY) += micrel.o
+obj-$(CONFIG_LANTIQ_PHY) += lantiq.o
obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o
obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o
obj-$(CONFIG_AT803X_PHY) += at803x.o
diff --git a/drivers/net/phy/lantiq.c b/drivers/net/phy/lantiq.c
new file mode 100644
index 0000000..ba4d7b7
--- /dev/null
+++ b/drivers/net/phy/lantiq.c
@@ -0,0 +1,178 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) 2012 Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
+ */
+
+#include <linux/module.h>
+#include <linux/phy.h>
+
+#define MII_MMDCTRL 0x0d
+#define MII_MMDDATA 0x0e
+
+#define MII_VR9_11G_IMASK 0x19 /* interrupt mask */
+#define MII_VR9_11G_ISTAT 0x1a /* interrupt status */
+
+#define INT_VR9_11G_WOL BIT(15) /* Wake-On-LAN */
+#define INT_VR9_11G_ANE BIT(11) /* Auto-Neg error */
+#define INT_VR9_11G_ANC BIT(10) /* Auto-Neg complete */
+#define INT_VR9_11G_ADSC BIT(5) /* Link auto-downspeed detect */
+#define INT_VR9_11G_DXMC BIT(2) /* Duplex mode change */
+#define INT_VR9_11G_LSPC BIT(1) /* Link speed change */
+#define INT_VR9_11G_LSTC BIT(0) /* Link state change */
+#define INT_VR9_11G_MASK (INT_VR9_11G_LSTC | INT_VR9_11G_ADSC)
+
+#define ADVERTISED_MPD BIT(10) /* Multi-port device */
+
+#define MMD_DEVAD 0x1f
+#define MMD_ACTYPE_SHIFT 14
+#define MMD_ACTYPE_ADDRESS (0 << MMD_ACTYPE_SHIFT)
+#define MMD_ACTYPE_DATA (1 << MMD_ACTYPE_SHIFT)
+#define MMD_ACTYPE_DATA_PI (2 << MMD_ACTYPE_SHIFT)
+#define MMD_ACTYPE_DATA_PIWR (3 << MMD_ACTYPE_SHIFT)
+
+static __maybe_unused int vr9_gphy_mmd_read(struct phy_device *phydev,
+ u16 regnum)
+{
+ phy_write(phydev, MII_MMDCTRL, MMD_ACTYPE_ADDRESS | MMD_DEVAD);
+ phy_write(phydev, MII_MMDDATA, regnum);
+ phy_write(phydev, MII_MMDCTRL, MMD_ACTYPE_DATA | MMD_DEVAD);
+
+ return phy_read(phydev, MII_MMDDATA);
+}
+
+static __maybe_unused int vr9_gphy_mmd_write(struct phy_device *phydev,
+ u16 regnum, u16 val)
+{
+ phy_write(phydev, MII_MMDCTRL, MMD_ACTYPE_ADDRESS | MMD_DEVAD);
+ phy_write(phydev, MII_MMDDATA, regnum);
+ phy_write(phydev, MII_MMDCTRL, MMD_ACTYPE_DATA | MMD_DEVAD);
+ phy_write(phydev, MII_MMDDATA, val);
+
+ return 0;
+}
+
+static int vr9_gphy_config_init(struct phy_device *phydev)
+{
+ int err;
+
+ dev_dbg(&phydev->dev, "%s\n", __func__);
+
+ /* Mask all interrupts */
+ err = phy_write(phydev, MII_VR9_11G_IMASK, 0);
+ if (err)
+ return err;
+
+ /* Clear all pending interrupts */
+ phy_read(phydev, MII_VR9_11G_ISTAT);
+
+ return 0;
+}
+
+static int vr9_gphy_config_aneg(struct phy_device *phydev)
+{
+ int reg, err;
+
+ /* Advertise as multi-port device */
+ reg = phy_read(phydev, MII_CTRL1000);
+ reg |= ADVERTISED_MPD;
+ err = phy_write(phydev, MII_CTRL1000, reg);
+ if (err)
+ return err;
+
+ return genphy_config_aneg(phydev);
+}
+
+static int vr9_gphy_ack_interrupt(struct phy_device *phydev)
+{
+ int reg;
+
+ /*
+ * Possible IRQ numbers:
+ * - IM3_IRL18 for GPHY0
+ * - IM3_IRL17 for GPHY1
+ *
+ * Due to a silicon bug IRQ lines are not really independent from
+ * each other. Sometimes the two lines are driven at the same time
+ * if only one GPHY core raises the interrupt.
+ */
+
+ reg = phy_read(phydev, MII_VR9_11G_ISTAT);
+
+ return (reg < 0) ? reg : 0;
+}
+
+static int vr9_gphy_did_interrupt(struct phy_device *phydev)
+{
+ int reg;
+
+ reg = phy_read(phydev, MII_VR9_11G_ISTAT);
+
+ return reg > 0;
+}
+
+static int vr9_gphy_config_intr(struct phy_device *phydev)
+{
+ int err;
+
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ err = phy_write(phydev, MII_VR9_11G_IMASK, INT_VR9_11G_MASK);
+ else
+ err = phy_write(phydev, MII_VR9_11G_IMASK, 0);
+
+ return err;
+}
+
+/* TODO: add vr9_gphy_22f_driver and drivers for external Lantiq PEF7071 PHYs */
+static struct phy_driver vr9_gphy_11g_driver = {
+ .phy_id = 0xd565a408,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Lantiq XWAY VR9 GPHY 11G",
+ .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause),
+ .flags = 0, /*PHY_HAS_INTERRUPT,*/
+ .config_init = vr9_gphy_config_init,
+ .config_aneg = vr9_gphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = vr9_gphy_ack_interrupt,
+ .did_interrupt = vr9_gphy_did_interrupt,
+ .config_intr = vr9_gphy_config_intr,
+ .driver = { .owner = THIS_MODULE },
+};
+
+static int __init ltq_phy_init(void)
+{
+ int err;
+
+ err = phy_driver_register(&vr9_gphy_11g_driver);
+ if (err)
+ goto err_out;
+
+ return 0;
+
+err_out:
+ return err;
+}
+
+static void __exit ltq_phy_exit(void)
+{
+ phy_driver_unregister(&vr9_gphy_11g_driver);
+}
+
+module_init(ltq_phy_init);
+module_exit(ltq_phy_exit);
+
+MODULE_DESCRIPTION("Lantiq PHY drivers");
+MODULE_AUTHOR("Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>");
+MODULE_LICENSE("GPL");
--
1.7.10.4

View file

@ -0,0 +1,807 @@
From c7b0e371e1c5e2f6258decfeb948e0dda7109afc Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Wed, 24 Oct 2012 19:50:30 +0200
Subject: [PATCH 116/123] NET: MIPS: lantiq: update etop driver for devicetree
---
drivers/net/ethernet/lantiq_etop.c | 470 +++++++++++++++++++++++++-----------
1 file changed, 333 insertions(+), 137 deletions(-)
diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
index 003c5bc..dc5457a 100644
--- a/drivers/net/ethernet/lantiq_etop.c
+++ b/drivers/net/ethernet/lantiq_etop.c
@@ -12,7 +12,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
- * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2011-12 John Crispin <blogic@openwrt.org>
*/
#include <linux/kernel.h>
@@ -36,6 +36,10 @@
#include <linux/io.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/of_net.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
#include <asm/checksum.h>
@@ -71,25 +75,56 @@
#define ETOP_MII_REVERSE 0xe
#define ETOP_PLEN_UNDER 0x40
#define ETOP_CGEN 0x800
-
-/* use 2 static channels for TX/RX */
-#define LTQ_ETOP_TX_CHANNEL 1
-#define LTQ_ETOP_RX_CHANNEL 6
-#define IS_TX(x) (x == LTQ_ETOP_TX_CHANNEL)
-#define IS_RX(x) (x == LTQ_ETOP_RX_CHANNEL)
-
+#define ETOP_CFG_MII0 0x01
+
+#define LTQ_GBIT_MDIO_CTL 0xCC
+#define LTQ_GBIT_MDIO_DATA 0xd0
+#define LTQ_GBIT_GCTL0 0x68
+#define LTQ_GBIT_PMAC_HD_CTL 0x8c
+#define LTQ_GBIT_P0_CTL 0x4
+#define LTQ_GBIT_PMAC_RX_IPG 0xa8
+
+#define PMAC_HD_CTL_AS (1 << 19)
+#define PMAC_HD_CTL_RXSH (1 << 22)
+
+/* Switch Enable (0=disable, 1=enable) */
+#define GCTL0_SE 0x80000000
+/* Disable MDIO auto polling (0=disable, 1=enable) */
+#define PX_CTL_DMDIO 0x00400000
+
+/* register information for the gbit's MDIO bus */
+#define MDIO_XR9_REQUEST 0x00008000
+#define MDIO_XR9_READ 0x00000800
+#define MDIO_XR9_WRITE 0x00000400
+#define MDIO_XR9_REG_MASK 0x1f
+#define MDIO_XR9_ADDR_MASK 0x1f
+#define MDIO_XR9_RD_MASK 0xffff
+#define MDIO_XR9_REG_OFFSET 0
+#define MDIO_XR9_ADDR_OFFSET 5
+#define MDIO_XR9_WR_OFFSET 16
+
+#define LTQ_DMA_ETOP ((of_machine_is_compatible("lantiq,ase")) ? \
+ (INT_NUM_IM3_IRL0) : (INT_NUM_IM2_IRL0))
+
+/* the newer xway socks have a embedded 3/7 port gbit multiplexer */
#define ltq_etop_r32(x) ltq_r32(ltq_etop_membase + (x))
#define ltq_etop_w32(x, y) ltq_w32(x, ltq_etop_membase + (y))
#define ltq_etop_w32_mask(x, y, z) \
ltq_w32_mask(x, y, ltq_etop_membase + (z))
-#define DRV_VERSION "1.0"
+#define ltq_gbit_r32(x) ltq_r32(ltq_gbit_membase + (x))
+#define ltq_gbit_w32(x, y) ltq_w32(x, ltq_gbit_membase + (y))
+#define ltq_gbit_w32_mask(x, y, z) \
+ ltq_w32_mask(x, y, ltq_gbit_membase + (z))
+
+#define DRV_VERSION "1.2"
static void __iomem *ltq_etop_membase;
+static void __iomem *ltq_gbit_membase;
struct ltq_etop_chan {
- int idx;
int tx_free;
+ int irq;
struct net_device *netdev;
struct napi_struct napi;
struct ltq_dma_channel dma;
@@ -99,22 +134,35 @@ struct ltq_etop_chan {
struct ltq_etop_priv {
struct net_device *netdev;
struct platform_device *pdev;
- struct ltq_eth_data *pldata;
struct resource *res;
struct mii_bus *mii_bus;
struct phy_device *phydev;
- struct ltq_etop_chan ch[MAX_DMA_CHAN];
- int tx_free[MAX_DMA_CHAN >> 1];
+ struct ltq_etop_chan txch;
+ struct ltq_etop_chan rxch;
+
+ int tx_irq;
+ int rx_irq;
+
+ const void *mac;
+ int mii_mode;
spinlock_t lock;
+
+ struct clk *clk_ppe;
+ struct clk *clk_switch;
+ struct clk *clk_ephy;
+ struct clk *clk_ephycgu;
};
+static int ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr,
+ int phy_reg, u16 phy_data);
+
static int
ltq_etop_alloc_skb(struct ltq_etop_chan *ch)
{
- ch->skb[ch->dma.desc] = netdev_alloc_skb(ch->netdev, MAX_DMA_DATA_LEN);
+ ch->skb[ch->dma.desc] = dev_alloc_skb(MAX_DMA_DATA_LEN);
if (!ch->skb[ch->dma.desc])
return -ENOMEM;
ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(NULL,
@@ -149,8 +197,11 @@ ltq_etop_hw_receive(struct ltq_etop_chan *ch)
spin_unlock_irqrestore(&priv->lock, flags);
skb_put(skb, len);
+ skb->dev = ch->netdev;
skb->protocol = eth_type_trans(skb, ch->netdev);
netif_receive_skb(skb);
+ ch->netdev->stats.rx_packets++;
+ ch->netdev->stats.rx_bytes += len;
}
static int
@@ -158,8 +209,10 @@ ltq_etop_poll_rx(struct napi_struct *napi, int budget)
{
struct ltq_etop_chan *ch = container_of(napi,
struct ltq_etop_chan, napi);
+ struct ltq_etop_priv *priv = netdev_priv(ch->netdev);
int rx = 0;
int complete = 0;
+ unsigned long flags;
while ((rx < budget) && !complete) {
struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
@@ -173,7 +226,9 @@ ltq_etop_poll_rx(struct napi_struct *napi, int budget)
}
if (complete || !rx) {
napi_complete(&ch->napi);
+ spin_lock_irqsave(&priv->lock, flags);
ltq_dma_ack_irq(&ch->dma);
+ spin_unlock_irqrestore(&priv->lock, flags);
}
return rx;
}
@@ -185,12 +240,14 @@ ltq_etop_poll_tx(struct napi_struct *napi, int budget)
container_of(napi, struct ltq_etop_chan, napi);
struct ltq_etop_priv *priv = netdev_priv(ch->netdev);
struct netdev_queue *txq =
- netdev_get_tx_queue(ch->netdev, ch->idx >> 1);
+ netdev_get_tx_queue(ch->netdev, ch->dma.nr >> 1);
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
while ((ch->dma.desc_base[ch->tx_free].ctl &
(LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) {
+ ch->netdev->stats.tx_packets++;
+ ch->netdev->stats.tx_bytes += ch->skb[ch->tx_free]->len;
dev_kfree_skb_any(ch->skb[ch->tx_free]);
ch->skb[ch->tx_free] = NULL;
memset(&ch->dma.desc_base[ch->tx_free], 0,
@@ -203,7 +260,9 @@ ltq_etop_poll_tx(struct napi_struct *napi, int budget)
if (netif_tx_queue_stopped(txq))
netif_tx_start_queue(txq);
napi_complete(&ch->napi);
+ spin_lock_irqsave(&priv->lock, flags);
ltq_dma_ack_irq(&ch->dma);
+ spin_unlock_irqrestore(&priv->lock, flags);
return 1;
}
@@ -211,9 +270,10 @@ static irqreturn_t
ltq_etop_dma_irq(int irq, void *_priv)
{
struct ltq_etop_priv *priv = _priv;
- int ch = irq - LTQ_DMA_CH0_INT;
-
- napi_schedule(&priv->ch[ch].napi);
+ if (irq == priv->txch.dma.irq)
+ napi_schedule(&priv->txch.napi);
+ else
+ napi_schedule(&priv->rxch.napi);
return IRQ_HANDLED;
}
@@ -225,7 +285,7 @@ ltq_etop_free_channel(struct net_device *dev, struct ltq_etop_chan *ch)
ltq_dma_free(&ch->dma);
if (ch->dma.irq)
free_irq(ch->dma.irq, priv);
- if (IS_RX(ch->idx)) {
+ if (ch == &priv->txch) {
int desc;
for (desc = 0; desc < LTQ_DESC_NUM; desc++)
dev_kfree_skb_any(ch->skb[ch->dma.desc]);
@@ -236,23 +296,55 @@ static void
ltq_etop_hw_exit(struct net_device *dev)
{
struct ltq_etop_priv *priv = netdev_priv(dev);
- int i;
- ltq_pmu_disable(PMU_PPE);
- for (i = 0; i < MAX_DMA_CHAN; i++)
- if (IS_TX(i) || IS_RX(i))
- ltq_etop_free_channel(dev, &priv->ch[i]);
+ clk_disable(priv->clk_ppe);
+
+ if (of_machine_is_compatible("lantiq,ar9"))
+ clk_disable(priv->clk_switch);
+
+ if (of_machine_is_compatible("lantiq,ase")) {
+ clk_disable(priv->clk_ephy);
+ clk_disable(priv->clk_ephycgu);
+ }
+
+ ltq_etop_free_channel(dev, &priv->txch);
+ ltq_etop_free_channel(dev, &priv->rxch);
+}
+
+static void
+ltq_etop_gbit_init(struct net_device *dev)
+{
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+
+ clk_enable(priv->clk_switch);
+
+ ltq_gbit_w32_mask(0, GCTL0_SE, LTQ_GBIT_GCTL0);
+ /** Disable MDIO auto polling mode */
+ ltq_gbit_w32_mask(0, PX_CTL_DMDIO, LTQ_GBIT_P0_CTL);
+ /* set 1522 packet size */
+ ltq_gbit_w32_mask(0x300, 0, LTQ_GBIT_GCTL0);
+ /* disable pmac & dmac headers */
+ ltq_gbit_w32_mask(PMAC_HD_CTL_AS | PMAC_HD_CTL_RXSH, 0,
+ LTQ_GBIT_PMAC_HD_CTL);
+ /* Due to traffic halt when burst length 8,
+ replace default IPG value with 0x3B */
+ ltq_gbit_w32(0x3B, LTQ_GBIT_PMAC_RX_IPG);
}
static int
ltq_etop_hw_init(struct net_device *dev)
{
struct ltq_etop_priv *priv = netdev_priv(dev);
- int i;
- ltq_pmu_enable(PMU_PPE);
+ clk_enable(priv->clk_ppe);
- switch (priv->pldata->mii_mode) {
+ if (of_machine_is_compatible("lantiq,ar9")) {
+ ltq_etop_gbit_init(dev);
+ /* force the etops link to the gbit to MII */
+ priv->mii_mode = PHY_INTERFACE_MODE_MII;
+ }
+
+ switch (priv->mii_mode) {
case PHY_INTERFACE_MODE_RMII:
ltq_etop_w32_mask(ETOP_MII_MASK,
ETOP_MII_REVERSE, LTQ_ETOP_CFG);
@@ -264,39 +356,68 @@ ltq_etop_hw_init(struct net_device *dev)
break;
default:
+ if (of_machine_is_compatible("lantiq,ase")) {
+ clk_enable(priv->clk_ephy);
+ /* disable external MII */
+ ltq_etop_w32_mask(0, ETOP_CFG_MII0, LTQ_ETOP_CFG);
+ /* enable clock for internal PHY */
+ clk_enable(priv->clk_ephycgu);
+ /* we need to write this magic to the internal phy to
+ make it work */
+ ltq_etop_mdio_wr(NULL, 0x8, 0x12, 0xC020);
+ pr_info("Selected EPHY mode\n");
+ break;
+ }
netdev_err(dev, "unknown mii mode %d\n",
- priv->pldata->mii_mode);
+ priv->mii_mode);
return -ENOTSUPP;
}
/* enable crc generation */
ltq_etop_w32(PPE32_CGEN, LQ_PPE32_ENET_MAC_CFG);
+ return 0;
+}
+
+static int
+ltq_etop_dma_init(struct net_device *dev)
+{
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+ int tx = priv->tx_irq - LTQ_DMA_ETOP;
+ int rx = priv->rx_irq - LTQ_DMA_ETOP;
+ int err;
+
ltq_dma_init_port(DMA_PORT_ETOP);
- for (i = 0; i < MAX_DMA_CHAN; i++) {
- int irq = LTQ_DMA_CH0_INT + i;
- struct ltq_etop_chan *ch = &priv->ch[i];
-
- ch->idx = ch->dma.nr = i;
-
- if (IS_TX(i)) {
- ltq_dma_alloc_tx(&ch->dma);
- request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED,
- "etop_tx", priv);
- } else if (IS_RX(i)) {
- ltq_dma_alloc_rx(&ch->dma);
- for (ch->dma.desc = 0; ch->dma.desc < LTQ_DESC_NUM;
- ch->dma.desc++)
- if (ltq_etop_alloc_skb(ch))
- return -ENOMEM;
- ch->dma.desc = 0;
- request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED,
- "etop_rx", priv);
+ priv->txch.dma.nr = tx;
+ ltq_dma_alloc_tx(&priv->txch.dma);
+ err = request_irq(priv->tx_irq, ltq_etop_dma_irq, IRQF_DISABLED,
+ "eth_tx", priv);
+ if (err) {
+ netdev_err(dev, "failed to allocate tx irq\n");
+ goto err_out;
+ }
+ priv->txch.dma.irq = priv->tx_irq;
+
+ priv->rxch.dma.nr = rx;
+ ltq_dma_alloc_rx(&priv->rxch.dma);
+ for (priv->rxch.dma.desc = 0; priv->rxch.dma.desc < LTQ_DESC_NUM;
+ priv->rxch.dma.desc++) {
+ if (ltq_etop_alloc_skb(&priv->rxch)) {
+ netdev_err(dev, "failed to allocate skbs\n");
+ err = -ENOMEM;
+ goto err_out;
}
- ch->dma.irq = irq;
}
- return 0;
+ priv->rxch.dma.desc = 0;
+ err = request_irq(priv->rx_irq, ltq_etop_dma_irq, IRQF_DISABLED,
+ "eth_rx", priv);
+ if (err)
+ netdev_err(dev, "failed to allocate rx irq\n");
+ else
+ priv->rxch.dma.irq = priv->rx_irq;
+err_out:
+ return err;
}
static void
@@ -312,7 +433,10 @@ ltq_etop_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct ltq_etop_priv *priv = netdev_priv(dev);
- return phy_ethtool_gset(priv->phydev, cmd);
+ if (priv->phydev)
+ return phy_ethtool_gset(priv->phydev, cmd);
+ else
+ return 0;
}
static int
@@ -320,7 +444,10 @@ ltq_etop_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct ltq_etop_priv *priv = netdev_priv(dev);
- return phy_ethtool_sset(priv->phydev, cmd);
+ if (priv->phydev)
+ return phy_ethtool_sset(priv->phydev, cmd);
+ else
+ return 0;
}
static int
@@ -328,7 +455,10 @@ ltq_etop_nway_reset(struct net_device *dev)
{
struct ltq_etop_priv *priv = netdev_priv(dev);
- return phy_start_aneg(priv->phydev);
+ if (priv->phydev)
+ return phy_start_aneg(priv->phydev);
+ else
+ return 0;
}
static const struct ethtool_ops ltq_etop_ethtool_ops = {
@@ -339,6 +469,39 @@ static const struct ethtool_ops ltq_etop_ethtool_ops = {
};
static int
+ltq_etop_mdio_wr_xr9(struct mii_bus *bus, int phy_addr,
+ int phy_reg, u16 phy_data)
+{
+ u32 val = MDIO_XR9_REQUEST | MDIO_XR9_WRITE |
+ (phy_data << MDIO_XR9_WR_OFFSET) |
+ ((phy_addr & MDIO_XR9_ADDR_MASK) << MDIO_XR9_ADDR_OFFSET) |
+ ((phy_reg & MDIO_XR9_REG_MASK) << MDIO_XR9_REG_OFFSET);
+
+ while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST)
+ ;
+ ltq_gbit_w32(val, LTQ_GBIT_MDIO_CTL);
+ while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST)
+ ;
+ return 0;
+}
+
+static int
+ltq_etop_mdio_rd_xr9(struct mii_bus *bus, int phy_addr, int phy_reg)
+{
+ u32 val = MDIO_XR9_REQUEST | MDIO_XR9_READ |
+ ((phy_addr & MDIO_XR9_ADDR_MASK) << MDIO_XR9_ADDR_OFFSET) |
+ ((phy_reg & MDIO_XR9_REG_MASK) << MDIO_XR9_REG_OFFSET);
+
+ while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST)
+ ;
+ ltq_gbit_w32(val, LTQ_GBIT_MDIO_CTL);
+ while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST)
+ ;
+ val = ltq_gbit_r32(LTQ_GBIT_MDIO_DATA) & MDIO_XR9_RD_MASK;
+ return val;
+}
+
+static int
ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr, int phy_reg, u16 phy_data)
{
u32 val = MDIO_REQUEST |
@@ -379,14 +542,11 @@ ltq_etop_mdio_probe(struct net_device *dev)
{
struct ltq_etop_priv *priv = netdev_priv(dev);
struct phy_device *phydev = NULL;
- int phy_addr;
- for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
- if (priv->mii_bus->phy_map[phy_addr]) {
- phydev = priv->mii_bus->phy_map[phy_addr];
- break;
- }
- }
+ if (of_machine_is_compatible("lantiq,ase"))
+ phydev = priv->mii_bus->phy_map[8];
+ else
+ phydev = priv->mii_bus->phy_map[0];
if (!phydev) {
netdev_err(dev, "no PHY found\n");
@@ -394,7 +554,7 @@ ltq_etop_mdio_probe(struct net_device *dev)
}
phydev = phy_connect(dev, dev_name(&phydev->dev), &ltq_etop_mdio_link,
- 0, priv->pldata->mii_mode);
+ 0, priv->mii_mode);
if (IS_ERR(phydev)) {
netdev_err(dev, "Could not attach to PHY\n");
@@ -408,6 +568,9 @@ ltq_etop_mdio_probe(struct net_device *dev)
| SUPPORTED_Autoneg
| SUPPORTED_MII
| SUPPORTED_TP);
+ if (of_machine_is_compatible("lantiq,ar9"))
+ phydev->supported &= SUPPORTED_1000baseT_Half
+ | SUPPORTED_1000baseT_Full;
phydev->advertising = phydev->supported;
priv->phydev = phydev;
@@ -433,8 +596,13 @@ ltq_etop_mdio_init(struct net_device *dev)
}
priv->mii_bus->priv = dev;
- priv->mii_bus->read = ltq_etop_mdio_rd;
- priv->mii_bus->write = ltq_etop_mdio_wr;
+ if (of_machine_is_compatible("lantiq,ar9")) {
+ priv->mii_bus->read = ltq_etop_mdio_rd_xr9;
+ priv->mii_bus->write = ltq_etop_mdio_wr_xr9;
+ } else {
+ priv->mii_bus->read = ltq_etop_mdio_rd;
+ priv->mii_bus->write = ltq_etop_mdio_wr;
+ }
priv->mii_bus->name = "ltq_mii";
snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
priv->pdev->name, priv->pdev->id);
@@ -483,17 +651,19 @@ static int
ltq_etop_open(struct net_device *dev)
{
struct ltq_etop_priv *priv = netdev_priv(dev);
- int i;
+ unsigned long flags;
- for (i = 0; i < MAX_DMA_CHAN; i++) {
- struct ltq_etop_chan *ch = &priv->ch[i];
+ napi_enable(&priv->txch.napi);
+ napi_enable(&priv->rxch.napi);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ ltq_dma_open(&priv->txch.dma);
+ ltq_dma_open(&priv->rxch.dma);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ if (priv->phydev)
+ phy_start(priv->phydev);
- if (!IS_TX(i) && (!IS_RX(i)))
- continue;
- ltq_dma_open(&ch->dma);
- napi_enable(&ch->napi);
- }
- phy_start(priv->phydev);
netif_tx_start_all_queues(dev);
return 0;
}
@@ -502,18 +672,19 @@ static int
ltq_etop_stop(struct net_device *dev)
{
struct ltq_etop_priv *priv = netdev_priv(dev);
- int i;
+ unsigned long flags;
netif_tx_stop_all_queues(dev);
- phy_stop(priv->phydev);
- for (i = 0; i < MAX_DMA_CHAN; i++) {
- struct ltq_etop_chan *ch = &priv->ch[i];
+ if (priv->phydev)
+ phy_stop(priv->phydev);
+ napi_disable(&priv->txch.napi);
+ napi_disable(&priv->rxch.napi);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ ltq_dma_close(&priv->txch.dma);
+ ltq_dma_close(&priv->rxch.dma);
+ spin_unlock_irqrestore(&priv->lock, flags);
- if (!IS_RX(i) && !IS_TX(i))
- continue;
- napi_disable(&ch->napi);
- ltq_dma_close(&ch->dma);
- }
return 0;
}
@@ -523,16 +694,16 @@ ltq_etop_tx(struct sk_buff *skb, struct net_device *dev)
int queue = skb_get_queue_mapping(skb);
struct netdev_queue *txq = netdev_get_tx_queue(dev, queue);
struct ltq_etop_priv *priv = netdev_priv(dev);
- struct ltq_etop_chan *ch = &priv->ch[(queue << 1) | 1];
- struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
- int len;
+ struct ltq_dma_desc *desc =
+ &priv->txch.dma.desc_base[priv->txch.dma.desc];
unsigned long flags;
u32 byte_offset;
+ int len;
len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
- if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) || ch->skb[ch->dma.desc]) {
- dev_kfree_skb_any(skb);
+ if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) ||
+ priv->txch.skb[priv->txch.dma.desc]) {
netdev_err(dev, "tx ring full\n");
netif_tx_stop_queue(txq);
return NETDEV_TX_BUSY;
@@ -540,7 +711,7 @@ ltq_etop_tx(struct sk_buff *skb, struct net_device *dev)
/* dma needs to start on a 16 byte aligned address */
byte_offset = CPHYSADDR(skb->data) % 16;
- ch->skb[ch->dma.desc] = skb;
+ priv->txch.skb[priv->txch.dma.desc] = skb;
dev->trans_start = jiffies;
@@ -550,11 +721,11 @@ ltq_etop_tx(struct sk_buff *skb, struct net_device *dev)
wmb();
desc->ctl = LTQ_DMA_OWN | LTQ_DMA_SOP | LTQ_DMA_EOP |
LTQ_DMA_TX_OFFSET(byte_offset) | (len & LTQ_DMA_SIZE_MASK);
- ch->dma.desc++;
- ch->dma.desc %= LTQ_DESC_NUM;
+ priv->txch.dma.desc++;
+ priv->txch.dma.desc %= LTQ_DESC_NUM;
spin_unlock_irqrestore(&priv->lock, flags);
- if (ch->dma.desc_base[ch->dma.desc].ctl & LTQ_DMA_OWN)
+ if (priv->txch.dma.desc_base[priv->txch.dma.desc].ctl & LTQ_DMA_OWN)
netif_tx_stop_queue(txq);
return NETDEV_TX_OK;
@@ -633,34 +804,32 @@ ltq_etop_init(struct net_device *dev)
struct ltq_etop_priv *priv = netdev_priv(dev);
struct sockaddr mac;
int err;
- bool random_mac = false;
ether_setup(dev);
dev->watchdog_timeo = 10 * HZ;
err = ltq_etop_hw_init(dev);
if (err)
goto err_hw;
+ err = ltq_etop_dma_init(dev);
+ if (err)
+ goto err_hw;
+
ltq_etop_change_mtu(dev, 1500);
- memcpy(&mac, &priv->pldata->mac, sizeof(struct sockaddr));
+ memcpy(&mac.sa_data, priv->mac, ETH_ALEN);
if (!is_valid_ether_addr(mac.sa_data)) {
pr_warn("etop: invalid MAC, using random\n");
- eth_random_addr(mac.sa_data);
- random_mac = true;
+ random_ether_addr(mac.sa_data);
}
err = ltq_etop_set_mac_address(dev, &mac);
if (err)
goto err_netdev;
-
- /* Set addr_assign_type here, ltq_etop_set_mac_address would reset it. */
- if (random_mac)
- dev->addr_assign_type |= NET_ADDR_RANDOM;
-
ltq_etop_set_multicast_list(dev);
- err = ltq_etop_mdio_init(dev);
- if (err)
- goto err_netdev;
+ if (!ltq_etop_mdio_init(dev))
+ dev->ethtool_ops = &ltq_etop_ethtool_ops;
+ else
+ pr_warn("etop: mdio probe failed\n");;
return 0;
err_netdev:
@@ -680,6 +849,9 @@ ltq_etop_tx_timeout(struct net_device *dev)
err = ltq_etop_hw_init(dev);
if (err)
goto err_hw;
+ err = ltq_etop_dma_init(dev);
+ if (err)
+ goto err_hw;
dev->trans_start = jiffies;
netif_wake_queue(dev);
return;
@@ -703,14 +875,19 @@ static const struct net_device_ops ltq_eth_netdev_ops = {
.ndo_tx_timeout = ltq_etop_tx_timeout,
};
-static int __init
+static int __devinit
ltq_etop_probe(struct platform_device *pdev)
{
struct net_device *dev;
struct ltq_etop_priv *priv;
- struct resource *res;
+ struct resource *res, *gbit_res, irqres[2];
int err;
- int i;
+
+ err = of_irq_to_resource_table(pdev->dev.of_node, irqres, 2);
+ if (err != 2) {
+ dev_err(&pdev->dev, "failed to get etop irqs\n");
+ return -EINVAL;
+ }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
@@ -736,30 +913,58 @@ ltq_etop_probe(struct platform_device *pdev)
goto err_out;
}
- dev = alloc_etherdev_mq(sizeof(struct ltq_etop_priv), 4);
- if (!dev) {
- err = -ENOMEM;
- goto err_out;
+ if (of_machine_is_compatible("lantiq,ar9")) {
+ gbit_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!gbit_res) {
+ dev_err(&pdev->dev, "failed to get gbit resource\n");
+ err = -ENOENT;
+ goto err_out;
+ }
+ ltq_gbit_membase = devm_ioremap_nocache(&pdev->dev,
+ gbit_res->start, resource_size(gbit_res));
+ if (!ltq_gbit_membase) {
+ dev_err(&pdev->dev, "failed to remap gigabit switch %d\n",
+ pdev->id);
+ err = -ENOMEM;
+ goto err_out;
+ }
}
+
+ dev = alloc_etherdev_mq(sizeof(struct ltq_etop_priv), 4);
strcpy(dev->name, "eth%d");
dev->netdev_ops = &ltq_eth_netdev_ops;
- dev->ethtool_ops = &ltq_etop_ethtool_ops;
priv = netdev_priv(dev);
priv->res = res;
priv->pdev = pdev;
- priv->pldata = dev_get_platdata(&pdev->dev);
priv->netdev = dev;
+ priv->tx_irq = irqres[0].start;
+ priv->rx_irq = irqres[1].start;
+ priv->mii_mode = of_get_phy_mode(pdev->dev.of_node);
+ priv->mac = of_get_mac_address(pdev->dev.of_node);
+
+ priv->clk_ppe = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(priv->clk_ppe))
+ return PTR_ERR(priv->clk_ppe);
+ if (of_machine_is_compatible("lantiq,ar9")) {
+ priv->clk_switch = clk_get(&pdev->dev, "switch");
+ if (IS_ERR(priv->clk_switch))
+ return PTR_ERR(priv->clk_switch);
+ }
+ if (of_machine_is_compatible("lantiq,ase")) {
+ priv->clk_ephy = clk_get(&pdev->dev, "ephy");
+ if (IS_ERR(priv->clk_ephy))
+ return PTR_ERR(priv->clk_ephy);
+ priv->clk_ephycgu = clk_get(&pdev->dev, "ephycgu");
+ if (IS_ERR(priv->clk_ephycgu))
+ return PTR_ERR(priv->clk_ephycgu);
+ }
+
spin_lock_init(&priv->lock);
- for (i = 0; i < MAX_DMA_CHAN; i++) {
- if (IS_TX(i))
- netif_napi_add(dev, &priv->ch[i].napi,
- ltq_etop_poll_tx, 8);
- else if (IS_RX(i))
- netif_napi_add(dev, &priv->ch[i].napi,
- ltq_etop_poll_rx, 32);
- priv->ch[i].netdev = dev;
- }
+ netif_napi_add(dev, &priv->txch.napi, ltq_etop_poll_tx, 8);
+ netif_napi_add(dev, &priv->rxch.napi, ltq_etop_poll_rx, 32);
+ priv->txch.netdev = dev;
+ priv->rxch.netdev = dev;
err = register_netdev(dev);
if (err)
@@ -788,32 +993,23 @@ ltq_etop_remove(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id ltq_etop_match[] = {
+ { .compatible = "lantiq,etop-xway" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ltq_etop_match);
+
static struct platform_driver ltq_mii_driver = {
+ .probe = ltq_etop_probe,
.remove = __devexit_p(ltq_etop_remove),
.driver = {
.name = "ltq_etop",
.owner = THIS_MODULE,
+ .of_match_table = ltq_etop_match,
},
};
-int __init
-init_ltq_etop(void)
-{
- int ret = platform_driver_probe(&ltq_mii_driver, ltq_etop_probe);
-
- if (ret)
- pr_err("ltq_etop: Error registering platform driver!");
- return ret;
-}
-
-static void __exit
-exit_ltq_etop(void)
-{
- platform_driver_unregister(&ltq_mii_driver);
-}
-
-module_init(init_ltq_etop);
-module_exit(exit_ltq_etop);
+module_platform_driver(ltq_mii_driver);
MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
MODULE_DESCRIPTION("Lantiq SoC ETOP");
--
1.7.10.4

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,508 @@
From 8d2a7d1fb561c9cb098c2b13ded34fe0f49dcca5 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 3 Aug 2012 10:27:25 +0200
Subject: [PATCH 20/25] owrt atm
---
arch/mips/lantiq/irq.c | 2 ++
arch/mips/mm/cache.c | 2 ++
net/atm/common.c | 6 ++++++
net/atm/proc.c | 2 +-
4 files changed, 11 insertions(+), 1 deletions(-)
Index: linux-3.7-rc6/arch/mips/lantiq/irq.c
===================================================================
--- linux-3.7-rc6.orig/arch/mips/lantiq/irq.c 2012-12-06 21:02:42.000000000 +0100
+++ linux-3.7-rc6/arch/mips/lantiq/irq.c 2012-12-06 21:03:13.850060387 +0100
@@ -14,6 +14,7 @@
#include <linux/of_platform.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
+#include <linux/module.h>
#include <asm/bootinfo.h>
#include <asm/irq_cpu.h>
@@ -99,6 +100,7 @@
ltq_icu_w32(im, ltq_icu_r32(im, ier) & ~BIT(offset), ier);
ltq_icu_w32(im, BIT(offset), isr);
}
+EXPORT_SYMBOL(ltq_mask_and_ack_irq);
static void ltq_ack_irq(struct irq_data *d)
{
Index: linux-3.7-rc6/arch/mips/mm/cache.c
===================================================================
--- linux-3.7-rc6.orig/arch/mips/mm/cache.c 2012-12-06 21:02:40.000000000 +0100
+++ linux-3.7-rc6/arch/mips/mm/cache.c 2012-12-06 21:03:13.850060387 +0100
@@ -58,6 +58,8 @@
void (*_dma_cache_inv)(unsigned long start, unsigned long size);
EXPORT_SYMBOL(_dma_cache_wback_inv);
+EXPORT_SYMBOL(_dma_cache_wback);
+EXPORT_SYMBOL(_dma_cache_inv);
#endif /* CONFIG_DMA_NONCOHERENT */
Index: linux-3.7-rc6/net/atm/common.c
===================================================================
--- linux-3.7-rc6.orig/net/atm/common.c 2012-11-17 02:42:40.000000000 +0100
+++ linux-3.7-rc6/net/atm/common.c 2012-12-06 21:03:13.850060387 +0100
@@ -62,11 +62,17 @@
write_unlock_irq(&vcc_sklist_lock);
}
+struct sk_buff* (*ifx_atm_alloc_tx)(struct atm_vcc *, unsigned int) = NULL;
+EXPORT_SYMBOL(ifx_atm_alloc_tx);
+
static struct sk_buff *alloc_tx(struct atm_vcc *vcc, unsigned int size)
{
struct sk_buff *skb;
struct sock *sk = sk_atm(vcc);
+ if (ifx_atm_alloc_tx != NULL)
+ return ifx_atm_alloc_tx(vcc, size);
+
if (sk_wmem_alloc_get(sk) && !atm_may_send(vcc, size)) {
pr_debug("Sorry: wmem_alloc = %d, size = %d, sndbuf = %d\n",
sk_wmem_alloc_get(sk), size, sk->sk_sndbuf);
Index: linux-3.7-rc6/net/atm/proc.c
===================================================================
--- linux-3.7-rc6.orig/net/atm/proc.c 2012-11-17 02:42:40.000000000 +0100
+++ linux-3.7-rc6/net/atm/proc.c 2012-12-06 21:03:13.850060387 +0100
@@ -154,7 +154,7 @@
static void pvc_info(struct seq_file *seq, struct atm_vcc *vcc)
{
static const char *const class_name[] = {
- "off", "UBR", "CBR", "VBR", "ABR"};
+ "off","UBR","CBR","NTR-VBR","ABR","ANY","RT-VBR","UBR+","GFR"};
static const char *const aal_name[] = {
"---", "1", "2", "3/4", /* 0- 3 */
"???", "5", "???", "???", /* 4- 7 */
Index: linux-3.7-rc6/arch/mips/include/asm/mach-lantiq/lantiq_atm.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-3.7-rc6/arch/mips/include/asm/mach-lantiq/lantiq_atm.h 2012-12-06 21:03:13.850060387 +0100
@@ -0,0 +1,196 @@
+/******************************************************************************
+**
+** FILE NAME : ifx_atm.h
+** PROJECT : UEIP
+** MODULES : ATM
+**
+** DATE : 17 Jun 2009
+** AUTHOR : Xu Liang
+** DESCRIPTION : Global ATM driver header file
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 07 JUL 2009 Xu Liang Init Version
+*******************************************************************************/
+
+#ifndef IFX_ATM_H
+#define IFX_ATM_H
+
+
+
+/*!
+ \defgroup IFX_ATM UEIP Project - ATM driver module
+ \brief UEIP Project - ATM driver module, support Danube, Amazon-SE, AR9, VR9.
+ */
+
+/*!
+ \defgroup IFX_ATM_IOCTL IOCTL Commands
+ \ingroup IFX_ATM
+ \brief IOCTL Commands used by user application.
+ */
+
+/*!
+ \defgroup IFX_ATM_STRUCT Structures
+ \ingroup IFX_ATM
+ \brief Structures used by user application.
+ */
+
+/*!
+ \file ifx_atm.h
+ \ingroup IFX_ATM
+ \brief ATM driver header file
+ */
+
+
+
+/*
+ * ####################################
+ * Definition
+ * ####################################
+ */
+
+/*!
+ \addtogroup IFX_ATM_STRUCT
+ */
+/*@{*/
+
+/*
+ * ATM MIB
+ */
+
+/*!
+ \struct atm_cell_ifEntry_t
+ \brief Structure used for Cell Level MIB Counters.
+
+ User application use this structure to call IOCTL command "PPE_ATM_MIB_CELL".
+ */
+typedef struct {
+ __u32 ifHCInOctets_h; /*!< byte counter of ingress cells (upper 32 bits, total 64 bits) */
+ __u32 ifHCInOctets_l; /*!< byte counter of ingress cells (lower 32 bits, total 64 bits) */
+ __u32 ifHCOutOctets_h; /*!< byte counter of egress cells (upper 32 bits, total 64 bits) */
+ __u32 ifHCOutOctets_l; /*!< byte counter of egress cells (lower 32 bits, total 64 bits) */
+ __u32 ifInErrors; /*!< counter of error ingress cells */
+ __u32 ifInUnknownProtos; /*!< counter of unknown ingress cells */
+ __u32 ifOutErrors; /*!< counter of error egress cells */
+} atm_cell_ifEntry_t;
+
+/*!
+ \struct atm_aal5_ifEntry_t
+ \brief Structure used for AAL5 Frame Level MIB Counters.
+
+ User application use this structure to call IOCTL command "PPE_ATM_MIB_AAL5".
+ */
+typedef struct {
+ __u32 ifHCInOctets_h; /*!< byte counter of ingress packets (upper 32 bits, total 64 bits) */
+ __u32 ifHCInOctets_l; /*!< byte counter of ingress packets (lower 32 bits, total 64 bits) */
+ __u32 ifHCOutOctets_h; /*!< byte counter of egress packets (upper 32 bits, total 64 bits) */
+ __u32 ifHCOutOctets_l; /*!< byte counter of egress packets (lower 32 bits, total 64 bits) */
+ __u32 ifInUcastPkts; /*!< counter of ingress packets */
+ __u32 ifOutUcastPkts; /*!< counter of egress packets */
+ __u32 ifInErrors; /*!< counter of error ingress packets */
+ __u32 ifInDiscards; /*!< counter of dropped ingress packets */
+ __u32 ifOutErros; /*!< counter of error egress packets */
+ __u32 ifOutDiscards; /*!< counter of dropped egress packets */
+} atm_aal5_ifEntry_t;
+
+/*!
+ \struct atm_aal5_vcc_t
+ \brief Structure used for per PVC AAL5 Frame Level MIB Counters.
+
+ This structure is a part of structure "atm_aal5_vcc_x_t".
+ */
+typedef struct {
+ __u32 aal5VccCrcErrors; /*!< counter of ingress packets with CRC error */
+ __u32 aal5VccSarTimeOuts; /*!< counter of ingress packets with Re-assemble timeout */ //no timer support yet
+ __u32 aal5VccOverSizedSDUs; /*!< counter of oversized ingress packets */
+} atm_aal5_vcc_t;
+
+/*!
+ \struct atm_aal5_vcc_x_t
+ \brief Structure used for per PVC AAL5 Frame Level MIB Counters.
+
+ User application use this structure to call IOCTL command "PPE_ATM_MIB_VCC".
+ */
+typedef struct {
+ int vpi; /*!< VPI of the VCC to get MIB counters */
+ int vci; /*!< VCI of the VCC to get MIB counters */
+ atm_aal5_vcc_t mib_vcc; /*!< structure to get MIB counters */
+} atm_aal5_vcc_x_t;
+
+/*@}*/
+
+
+
+/*
+ * ####################################
+ * IOCTL
+ * ####################################
+ */
+
+/*!
+ \addtogroup IFX_ATM_IOCTL
+ */
+/*@{*/
+
+/*
+ * ioctl Command
+ */
+/*!
+ \brief ATM IOCTL Magic Number
+ */
+#define PPE_ATM_IOC_MAGIC 'o'
+/*!
+ \brief ATM IOCTL Command - Get Cell Level MIB Counters
+
+ This command is obsolete. User can get cell level MIB from DSL API.
+ This command uses structure "atm_cell_ifEntry_t" as parameter for output of MIB counters.
+ */
+#define PPE_ATM_MIB_CELL _IOW(PPE_ATM_IOC_MAGIC, 0, atm_cell_ifEntry_t)
+/*!
+ \brief ATM IOCTL Command - Get AAL5 Level MIB Counters
+
+ Get AAL5 packet counters.
+ This command uses structure "atm_aal5_ifEntry_t" as parameter for output of MIB counters.
+ */
+#define PPE_ATM_MIB_AAL5 _IOW(PPE_ATM_IOC_MAGIC, 1, atm_aal5_ifEntry_t)
+/*!
+ \brief ATM IOCTL Command - Get Per PVC MIB Counters
+
+ Get AAL5 packet counters for each PVC.
+ This command uses structure "atm_aal5_vcc_x_t" as parameter for input of VPI/VCI information and output of MIB counters.
+ */
+#define PPE_ATM_MIB_VCC _IOWR(PPE_ATM_IOC_MAGIC, 2, atm_aal5_vcc_x_t)
+/*!
+ \brief Total Number of ATM IOCTL Commands
+ */
+#define PPE_ATM_IOC_MAXNR 3
+
+/*@}*/
+
+
+
+/*
+ * ####################################
+ * API
+ * ####################################
+ */
+
+#ifdef __KERNEL__
+struct port_cell_info {
+ unsigned int port_num;
+ unsigned int tx_link_rate[2];
+};
+#endif
+
+
+
+#endif // IFX_ATM_H
+
Index: linux-3.7-rc6/arch/mips/include/asm/mach-lantiq/lantiq_ptm.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-3.7-rc6/arch/mips/include/asm/mach-lantiq/lantiq_ptm.h 2012-12-06 21:03:13.854060387 +0100
@@ -0,0 +1,203 @@
+/******************************************************************************
+**
+** FILE NAME : ifx_ptm.h
+** PROJECT : UEIP
+** MODULES : PTM
+**
+** DATE : 17 Jun 2009
+** AUTHOR : Xu Liang
+** DESCRIPTION : Global PTM driver header file
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 07 JUL 2009 Xu Liang Init Version
+*******************************************************************************/
+
+#ifndef IFX_PTM_H
+#define IFX_PTM_H
+
+
+
+/*!
+ \defgroup IFX_PTM UEIP Project - PTM driver module
+ \brief UEIP Project - PTM driver module, support Danube, Amazon-SE, AR9, VR9.
+ */
+
+/*!
+ \defgroup IFX_PTM_IOCTL IOCTL Commands
+ \ingroup IFX_PTM
+ \brief IOCTL Commands used by user application.
+ */
+
+/*!
+ \defgroup IFX_PTM_STRUCT Structures
+ \ingroup IFX_PTM
+ \brief Structures used by user application.
+ */
+
+/*!
+ \file ifx_ptm.h
+ \ingroup IFX_PTM
+ \brief PTM driver header file
+ */
+
+
+
+/*
+ * ####################################
+ * Definition
+ * ####################################
+ */
+
+
+
+/*
+ * ####################################
+ * IOCTL
+ * ####################################
+ */
+
+/*!
+ \addtogroup IFX_PTM_IOCTL
+ */
+/*@{*/
+
+/*
+ * ioctl Command
+ */
+/*!
+ \brief PTM IOCTL Command - Get codeword MIB counters.
+
+ This command uses structure "PTM_CW_IF_ENTRY_T" to get codeword level MIB counters.
+ */
+#define IFX_PTM_MIB_CW_GET SIOCDEVPRIVATE + 1
+/*!
+ \brief PTM IOCTL Command - Get packet MIB counters.
+
+ This command uses structure "PTM_FRAME_MIB_T" to get packet level MIB counters.
+ */
+#define IFX_PTM_MIB_FRAME_GET SIOCDEVPRIVATE + 2
+/*!
+ \brief PTM IOCTL Command - Get firmware configuration (CRC).
+
+ This command uses structure "IFX_PTM_CFG_T" to get firmware configuration (CRC).
+ */
+#define IFX_PTM_CFG_GET SIOCDEVPRIVATE + 3
+/*!
+ \brief PTM IOCTL Command - Set firmware configuration (CRC).
+
+ This command uses structure "IFX_PTM_CFG_T" to set firmware configuration (CRC).
+ */
+#define IFX_PTM_CFG_SET SIOCDEVPRIVATE + 4
+/*!
+ \brief PTM IOCTL Command - Program priority value to TX queue mapping.
+
+ This command uses structure "IFX_PTM_PRIO_Q_MAP_T" to program priority value to TX queue mapping.
+ */
+#define IFX_PTM_MAP_PKT_PRIO_TO_Q SIOCDEVPRIVATE + 14
+
+/*@}*/
+
+
+/*!
+ \addtogroup IFX_PTM_STRUCT
+ */
+/*@{*/
+
+/*
+ * ioctl Data Type
+ */
+
+/*!
+ \typedef PTM_CW_IF_ENTRY_T
+ \brief Wrapping of structure "ptm_cw_ifEntry_t".
+ */
+/*!
+ \struct ptm_cw_ifEntry_t
+ \brief Structure used for CodeWord level MIB counters.
+ */
+typedef struct ptm_cw_ifEntry_t {
+ uint32_t ifRxNoIdleCodewords; /*!< output, number of ingress user codeword */
+ uint32_t ifRxIdleCodewords; /*!< output, number of ingress idle codeword */
+ uint32_t ifRxCodingViolation; /*!< output, number of error ingress codeword */
+ uint32_t ifTxNoIdleCodewords; /*!< output, number of egress user codeword */
+ uint32_t ifTxIdleCodewords; /*!< output, number of egress idle codeword */
+} PTM_CW_IF_ENTRY_T;
+
+/*!
+ \typedef PTM_FRAME_MIB_T
+ \brief Wrapping of structure "ptm_frame_mib_t".
+ */
+/*!
+ \struct ptm_frame_mib_t
+ \brief Structure used for packet level MIB counters.
+ */
+typedef struct ptm_frame_mib_t {
+ uint32_t RxCorrect; /*!< output, number of ingress packet */
+ uint32_t TC_CrcError; /*!< output, number of egress packet with CRC error */
+ uint32_t RxDropped; /*!< output, number of dropped ingress packet */
+ uint32_t TxSend; /*!< output, number of egress packet */
+} PTM_FRAME_MIB_T;
+
+/*!
+ \typedef IFX_PTM_CFG_T
+ \brief Wrapping of structure "ptm_cfg_t".
+ */
+/*!
+ \struct ptm_cfg_t
+ \brief Structure used for ETH/TC CRC configuration.
+ */
+typedef struct ptm_cfg_t {
+ uint32_t RxEthCrcPresent; /*!< input/output, ingress packet has ETH CRC */
+ uint32_t RxEthCrcCheck; /*!< input/output, check ETH CRC of ingress packet */
+ uint32_t RxTcCrcCheck; /*!< input/output, check TC CRC of ingress codeword */
+ uint32_t RxTcCrcLen; /*!< input/output, length of TC CRC of ingress codeword */
+ uint32_t TxEthCrcGen; /*!< input/output, generate ETH CRC for egress packet */
+ uint32_t TxTcCrcGen; /*!< input/output, generate TC CRC for egress codeword */
+ uint32_t TxTcCrcLen; /*!< input/output, length of TC CRC of egress codeword */
+} IFX_PTM_CFG_T;
+
+/*!
+ \typedef IFX_PTM_PRIO_Q_MAP_T
+ \brief Wrapping of structure "ppe_prio_q_map".
+ */
+/*!
+ \struct ppe_prio_q_map
+ \brief Structure used for Priority Value to TX Queue mapping.
+ */
+typedef struct ppe_prio_q_map {
+ int pkt_prio;
+ int qid;
+ int vpi; // ignored in eth interface
+ int vci; // ignored in eth interface
+} IFX_PTM_PRIO_Q_MAP_T;
+
+/*@}*/
+
+
+
+/*
+ * ####################################
+ * API
+ * ####################################
+ */
+
+#ifdef __KERNEL__
+struct port_cell_info {
+ unsigned int port_num;
+ unsigned int tx_link_rate[2];
+};
+#endif
+
+
+
+#endif // IFX_PTM_H
+
Index: linux-3.7-rc6/include/uapi/linux/atm.h
===================================================================
--- linux-3.7-rc6.orig/include/uapi/linux/atm.h 2012-12-06 21:02:41.458059575 +0100
+++ linux-3.7-rc6/include/uapi/linux/atm.h 2012-12-06 21:04:21.282062078 +0100
@@ -130,8 +130,14 @@
#define ATM_ABR 4
#define ATM_ANYCLASS 5 /* compatible with everything */
+#define ATM_VBR_NRT ATM_VBR
+#define ATM_VBR_RT 6
+#define ATM_UBR_PLUS 7
+#define ATM_GFR 8
+
#define ATM_MAX_PCR -1 /* maximum available PCR */
+
struct atm_trafprm {
unsigned char traffic_class; /* traffic class (ATM_UBR, ...) */
int max_pcr; /* maximum PCR in cells per second */

View file

@ -0,0 +1,26 @@
From ac676d9516d9d14b98eef3dec05badae1d1a331a Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 2 Nov 2012 15:40:08 +0100
Subject: [PATCH 120/123] owrt: generic dtb image hack
---
arch/mips/kernel/head.S | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index ea695d9..be87456 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -141,6 +141,9 @@ FEXPORT(__kernel_entry)
j kernel_entry
#endif
+ .ascii "OWRTDTB:"
+ EXPORT(__image_dtb)
+ .fill 0x4000
__REF
NESTED(kernel_entry, 16, sp) # kernel entry point
--
1.7.10.4

View file

@ -0,0 +1,44 @@
From d8f83a608bc854dbbe6b2ea5436e9b34516af8e4 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 6 Dec 2012 16:09:08 +0100
Subject: [PATCH 121/123] owrt: lantiq dtb image hack
---
arch/mips/lantiq/prom.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
Index: linux-3.7-rc8/arch/mips/lantiq/prom.c
===================================================================
--- linux-3.7-rc8.orig/arch/mips/lantiq/prom.c 2012-12-14 23:08:36.451576994 +0100
+++ linux-3.7-rc8/arch/mips/lantiq/prom.c 2012-12-14 23:08:36.607576999 +0100
@@ -72,6 +72,8 @@
return 0;
}
+extern struct boot_param_header __image_dtb;
+
void __init plat_mem_setup(void)
{
ioport_resource.start = IOPORT_RESOURCE_START;
@@ -85,7 +87,7 @@
* Load the builtin devicetree. This causes the chosen node to be
* parsed resulting in our memory appearing
*/
- __dt_setup_arch(&__dtb_start);
+ __dt_setup_arch(&__image_dtb);
of_scan_flat_dt(early_init_dt_scan_model, NULL);
}
Index: linux-3.7-rc8/arch/mips/lantiq/Makefile
===================================================================
--- linux-3.7-rc8.orig/arch/mips/lantiq/Makefile 2012-12-14 23:08:36.459576996 +0100
+++ linux-3.7-rc8/arch/mips/lantiq/Makefile 2012-12-15 01:40:16.519805129 +0100
@@ -6,8 +6,6 @@
obj-y := irq.o clk.o prom.o
-obj-y += dts/
-
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_SOC_TYPE_XWAY) += xway/

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,34 @@
From 1b6941ae603f2885e6cf729119ef753deb7eb835 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 6 Dec 2012 19:59:53 +0100
Subject: [PATCH 123/123] USB: fix roothub for IFXHCD
---
drivers/usb/core/hub.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Index: linux-3.7-rc8/drivers/usb/core/hub.c
===================================================================
--- linux-3.7-rc8.orig/drivers/usb/core/hub.c 2012-12-03 20:22:37.000000000 +0100
+++ linux-3.7-rc8/drivers/usb/core/hub.c 2012-12-10 23:37:16.658956109 +0100
@@ -3839,7 +3839,7 @@
udev->ttport = hdev->ttport;
} else if (udev->speed != USB_SPEED_HIGH
&& hdev->speed == USB_SPEED_HIGH) {
- if (!hub->tt.hub) {
+ if (hdev->parent && !hub->tt.hub) {
dev_err(&udev->dev, "parent hub has no TT\n");
retval = -EINVAL;
goto fail;
Index: linux-3.7-rc8/arch/mips/lantiq/Kconfig
===================================================================
--- linux-3.7-rc8.orig/arch/mips/lantiq/Kconfig 2012-12-10 23:37:16.622956108 +0100
+++ linux-3.7-rc8/arch/mips/lantiq/Kconfig 2012-12-11 13:58:10.816251053 +0100
@@ -3,6 +3,7 @@
config SOC_TYPE_XWAY
bool
select PINCTRL_XWAY
+ select USB_ARCH_HAS_HCD
default n
choice

View file

@ -0,0 +1,22 @@
Index: linux-3.7-rc8/arch/mips/pci/pci-lantiq.c
===================================================================
--- linux-3.7-rc8.orig/arch/mips/pci/pci-lantiq.c 2012-12-03 20:22:37.000000000 +0100
+++ linux-3.7-rc8/arch/mips/pci/pci-lantiq.c 2012-12-14 23:28:24.355606776 +0100
@@ -129,8 +129,15 @@
/* setup reset gpio used by pci */
reset_gpio = of_get_named_gpio(node, "gpio-reset", 0);
- if (gpio_is_valid(reset_gpio))
- devm_gpio_request(&pdev->dev, reset_gpio, "pci-reset");
+ if (gpio_is_valid(reset_gpio)) {
+ int ret = devm_gpio_request(&pdev->dev, reset_gpio, "pci-reset");
+ if (ret) {
+ dev_err(&pdev->dev,
+ "failed to request gpio %d\n", reset_gpio);
+ return ret;
+ }
+ gpio_direction_output(reset_gpio, 1);
+ }
/* enable auto-switching between PCI and EBU */
ltq_pci_w32(0xa, PCI_CR_CLK_CTRL);

View file

@ -0,0 +1,230 @@
From 2a295753a10823a47542c779a25bbb1f52c71281 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 3 Aug 2012 10:27:13 +0200
Subject: [PATCH 19/25] owrt mtd split
---
.../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 1 +
arch/mips/lantiq/setup.c | 7 +
drivers/mtd/Kconfig | 4 +
drivers/mtd/mtdpart.c | 173 +++++++++++++++++++-
4 files changed, 184 insertions(+), 1 deletions(-)
diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
index 1ec8f2a..1ff93cc 100644
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 982a98b..e2f3f3e 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -31,6 +31,10 @@ config MTD_ROOTFS_SPLIT
bool "Automatically split 'rootfs' partition for squashfs"
default y
+config MTD_UIMAGE_SPLIT
+ bool "Automatically split 'linux' partition into 'kernel' and 'rootfs'"
+ default y
+
config MTD_REDBOOT_PARTS
tristate "RedBoot partition table parsing"
---help---
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 855b70b..93711e2 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -867,6 +867,168 @@ static int refresh_rootfs_split(struct mtd_info *mtd)
}
#endif /* CONFIG_MTD_ROOTFS_SPLIT */
+#ifdef CONFIG_MTD_UIMAGE_SPLIT
+static unsigned long find_uimage_size(struct mtd_info *mtd,
+ unsigned long offset)
+{
+#define UBOOT_MAGIC 0x56190527
+ unsigned long magic = 0;
+ unsigned long temp;
+ size_t len;
+ int ret;
+
+ ret = mtd_read(mtd, offset, 4, &len, (void *)&magic);
+ if (ret || len != sizeof(magic))
+ return 0;
+
+ if (le32_to_cpu(magic) != UBOOT_MAGIC)
+ return 0;
+
+ ret = mtd_read(mtd, offset + 12, 4, &len, (void *)&temp);
+ if (ret || len != sizeof(temp))
+ return 0;
+
+ return temp + 0x40;
+}
+
+static unsigned long find_eva_size(struct mtd_info *mtd,
+ unsigned long offset)
+{
+#define EVA_MAGIC 0xfeed1281
+ unsigned long magic = 0;
+ unsigned long temp;
+ size_t len;
+ int ret;
+
+ ret = mtd_read(mtd, offset, 4, &len, (void *)&magic);
+ if (ret || len != sizeof(magic))
+ return 0;
+
+ if (le32_to_cpu(magic) != EVA_MAGIC)
+ return 0;
+
+ ret = mtd_read(mtd, offset + 4, 4, &len, (void *)&temp);
+ if (ret || len != sizeof(temp))
+ return 0;
+
+ /* add eva header size */
+ temp = le32_to_cpu(temp) + 0x18;
+
+ temp &= ~0xffff;
+ temp += 0x10000;
+ return temp;
+}
+
+static int detect_squashfs_partition(struct mtd_info *mtd, unsigned long offset)
+{
+ unsigned long temp;
+ size_t len;
+ int ret;
+
+ ret = mtd_read(mtd, offset, 4, &len, (void *)&temp);
+ if (ret || len != sizeof(temp))
+ return 0;
+
+
+ return le32_to_cpu(temp) == SQUASHFS_MAGIC;
+}
+
+static int detect_eva_squashfs_partition(struct mtd_info *mtd, unsigned long offset)
+{
+ unsigned long temp;
+ size_t len;
+ int ret;
+
+ ret = mtd_read(mtd, offset, 4, &len, (void *)&temp);
+ if (ret || len != sizeof(temp))
+ return 0;
+
+ return be32_to_cpu(temp) == SQUASHFS_MAGIC;
+}
+
+static unsigned long find_brnimage_size(struct mtd_info *mtd,
+ unsigned long offset)
+{
+ unsigned long buf[4];
+ // Assume at most 2MB of kernel image
+ unsigned long end = offset + (2 << 20);
+ unsigned long ptr = offset + 0x400 - 12;
+ size_t len;
+ int ret;
+
+ while (ptr < end) {
+ long size_min = ptr - 0x400 - 12 - offset;
+ long size_max = ptr + 12 - offset;
+ ret = mtd_read(mtd, ptr, 16, &len, (void *)buf);
+ if (ret || len != 16)
+ return 0;
+
+ if (le32_to_cpu(buf[0]) < size_min ||
+ le32_to_cpu(buf[0]) > size_max) {
+ ptr += 0x400;
+ continue;
+ }
+
+ if (le32_to_cpu(buf[3]) == SQUASHFS_MAGIC)
+ return ptr + 12 - offset;
+
+ ptr += 0x400;
+ }
+
+ return 0;
+}
+
+static int split_uimage(struct mtd_info *mtd,
+ const struct mtd_partition *part)
+{
+ static struct mtd_partition split_partitions[] = {
+ {
+ .name = "kernel",
+ .offset = 0x0,
+ .size = 0x0,
+ }, {
+ .name = "rootfs",
+ .offset = 0x0,
+ .size = 0x0,
+ },
+ };
+
+ split_partitions[0].size = find_uimage_size(mtd, part->offset);
+ if (!split_partitions[0].size) {
+ split_partitions[0].size = find_eva_size(mtd, part->offset);
+ if (!split_partitions[0].size) {
+ split_partitions[0].size = find_brnimage_size(mtd, part->offset);
+ if (!split_partitions[0].size) {
+ printk(KERN_NOTICE "no uImage or brnImage or eva found in linux partition\n");
+ return -1;
+ }
+ }
+ }
+
+ if (detect_eva_squashfs_partition(mtd,
+ part->offset
+ + split_partitions[0].size)) {
+ split_partitions[0].size += 0x100;
+ pr_info("found eva dummy squashfs behind kernel\n");
+ } else if (!detect_squashfs_partition(mtd,
+ part->offset
+ + split_partitions[0].size)) {
+ split_partitions[0].size &= ~(mtd->erasesize - 1);
+ split_partitions[0].size += mtd->erasesize;
+ } else {
+ pr_info("found squashfs behind kernel\n");
+ }
+
+ split_partitions[0].offset = part->offset;
+ split_partitions[1].offset = part->offset + split_partitions[0].size;
+ split_partitions[1].size = part->size - split_partitions[0].size;
+
+ add_mtd_partitions(mtd, split_partitions, 2);
+
+ return 0;
+}
+#endif
+
/*
* This function, given a master MTD object and a partition table, creates
* and registers slave MTD objects which are bound to the master according to
@@ -883,7 +1045,7 @@ int add_mtd_partitions(struct mtd_info *master,
struct mtd_part *slave;
uint64_t cur_offset = 0;
int i;
-#ifdef CONFIG_MTD_ROOTFS_SPLIT
+#if defined(CONFIG_MTD_ROOTFS_SPLIT) || defined(CONFIG_MTD_UIMAGE_SPLIT)
int ret;
#endif
@@ -900,6 +1062,15 @@ int add_mtd_partitions(struct mtd_info *master,
add_mtd_device(&slave->mtd);
+#ifdef CONFIG_MTD_UIMAGE_SPLIT
+ if (!strcmp(parts[i].name, "linux")) {
+ ret = split_uimage(master, &parts[i]);
+
+ if (ret)
+ printk(KERN_WARNING "Can't split linux partition\n");
+ }
+#endif
+
if (!strcmp(parts[i].name, "rootfs")) {
#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
if (ROOT_DEV == 0) {
--
1.7.9.1

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,319 @@
Index: linux-3.7-rc8/arch/mips/lantiq/xway/Makefile
===================================================================
--- linux-3.7-rc8.orig/arch/mips/lantiq/xway/Makefile 2012-12-13 10:59:54.176314899 +0100
+++ linux-3.7-rc8/arch/mips/lantiq/xway/Makefile 2012-12-13 13:58:51.696584083 +0100
@@ -1,3 +1,5 @@
obj-y := prom.o sysctrl.o clk.o reset.o dma.o timer.o dcdc.o
+obj-y += ath_eep.o rt_eep.o eth_mac.o
+
obj-$(CONFIG_XRX200_PHY_FW) += xrx200_phy_fw.o
Index: linux-3.7-rc8/arch/mips/lantiq/xway/ath_eep.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-3.7-rc8/arch/mips/lantiq/xway/ath_eep.c 2012-12-13 13:49:12.472569552 +0100
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2011 Andrej Vlašić <andrej.vlasic0@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/etherdevice.h>
+#include <linux/ath5k_platform.h>
+#include <linux/ath9k_platform.h>
+#include <linux/pci.h>
+
+extern int (*ltq_pci_plat_dev_init)(struct pci_dev *dev);
+struct ath5k_platform_data ath5k_pdata;
+/*struct ath9k_platform_data ath9k_pdata = {
+ .led_pin = -1,
+ .endian_check = true,
+};*/
+static u16 ath5k_eeprom_data[ATH5K_PLAT_EEP_MAX_WORDS];
+//static u16 ath9k_eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS];
+static u8 athxk_eeprom_mac[6];
+
+/*static int
+ath9k_pci_plat_dev_init(struct pci_dev *dev)
+{
+ dev->dev.platform_data = &ath9k_pdata;
+ return 0;
+}
+
+void __init
+ltq_register_ath9k(u16 *eeprom_data, u8 *macaddr)
+{
+ memcpy(ath9k_pdata.eeprom_data, eeprom_data, sizeof(ath9k_pdata.eeprom_data));
+ ath9k_pdata.macaddr = macaddr;
+ ltq_pci_plat_dev_init = ath9k_pci_plat_dev_init;
+}
+*/
+static int ath5k_pci_plat_dev_init(struct pci_dev *dev)
+{
+ dev->dev.platform_data = &ath5k_pdata;
+ return 0;
+}
+
+int __init of_ath5k_eeprom_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct resource *eep_res, *mac_res;
+ void __iomem *eep, *mac;
+ int mac_offset;
+ u32 mac_inc = 0;
+ int i;
+
+ eep_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ mac_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+
+ if (!eep_res) {
+ dev_err(&pdev->dev, "failed to load eeprom address\n");
+ return -ENODEV;
+ }
+ if (resource_size(eep_res) != ATH5K_PLAT_EEP_MAX_WORDS) {
+ dev_err(&pdev->dev, "eeprom has an invalid size\n");
+ return -EINVAL;
+ }
+
+ eep = ioremap(eep_res->start, resource_size(eep_res));
+ memcpy_fromio(ath5k_eeprom_data, eep, ATH5K_PLAT_EEP_MAX_WORDS);
+
+ if (of_find_property(np, "ath,eep-swap", NULL))
+ for (i = 0; i < (ATH5K_PLAT_EEP_MAX_WORDS >> 1); i++)
+ ath5k_eeprom_data[i] = swab16(ath5k_eeprom_data[i]);
+
+ if (!of_property_read_u32(np, "ath,mac-offset", &mac_offset)) {
+ memcpy_fromio(athxk_eeprom_mac, (void*) ath5k_eeprom_data, 6);
+ } else if (mac_res) {
+ if (resource_size(mac_res) != 6) {
+ dev_err(&pdev->dev, "mac has an invalid size\n");
+ return -EINVAL;
+ }
+ mac = ioremap(mac_res->start, resource_size(mac_res));
+ memcpy_fromio(athxk_eeprom_mac, mac, 6);
+ } else {
+ dev_warn(&pdev->dev, "using random mac\n");
+ random_ether_addr(athxk_eeprom_mac);
+ }
+
+ if (!of_property_read_u32(np, "ath,mac-increment", &mac_inc))
+ athxk_eeprom_mac[5] += mac_inc;
+
+ ath5k_pdata.eeprom_data = ath5k_eeprom_data;
+ ath5k_pdata.macaddr = athxk_eeprom_mac;
+ ltq_pci_plat_dev_init = ath5k_pci_plat_dev_init;
+
+ dev_info(&pdev->dev, "loaded ath5k eeprom\n");
+
+ return 0;
+}
+
+static struct of_device_id ath5k_eeprom_ids[] = {
+ { .compatible = "ath5k,eeprom" },
+ { }
+};
+
+static struct platform_driver ath5k_eeprom_driver = {
+ .driver = {
+ .name = "ath5k,eeprom",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(ath5k_eeprom_ids),
+ },
+};
+
+static int __init of_ath5k_eeprom_init(void)
+{
+ return platform_driver_probe(&ath5k_eeprom_driver, of_ath5k_eeprom_probe);
+}
+device_initcall(of_ath5k_eeprom_init);
Index: linux-3.7-rc8/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
===================================================================
--- linux-3.7-rc8.orig/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h 2012-12-13 10:59:57.300314976 +0100
+++ linux-3.7-rc8/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h 2012-12-13 10:59:57.308314977 +0100
@@ -93,5 +93,8 @@
/* allow tapi driver to read the gptu value */
long gptu_get_count(struct clk *clk);
+/* allow the ethernet driver to load a flash mapped mac addr */
+const u8* ltq_get_eth_mac(void);
+
#endif /* CONFIG_SOC_TYPE_XWAY */
#endif /* _LTQ_XWAY_H__ */
Index: linux-3.7-rc8/arch/mips/lantiq/xway/eth_mac.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-3.7-rc8/arch/mips/lantiq/xway/eth_mac.c 2012-12-13 10:59:57.308314977 +0100
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/if_ether.h>
+
+static u8 eth_mac[6];
+static int eth_mac_set;
+
+const u8* ltq_get_eth_mac(void)
+{
+ return eth_mac;
+}
+
+static int __init setup_ethaddr(char *str)
+{
+ eth_mac_set = mac_pton(str, eth_mac);
+ return !eth_mac_set;
+}
+__setup("ethaddr=", setup_ethaddr);
+
+int __init of_eth_mac_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct resource *mac_res;
+ void __iomem *mac;
+ u32 mac_inc = 0;
+
+ if (eth_mac_set) {
+ dev_err(&pdev->dev, "mac was already set by bootloader\n");
+ return -EINVAL;
+ }
+ mac_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (!mac_res) {
+ dev_err(&pdev->dev, "failed to load mac\n");
+ return -EINVAL;
+ }
+ if (resource_size(mac_res) != 6) {
+ dev_err(&pdev->dev, "mac has an invalid size\n");
+ return -EINVAL;
+ }
+ mac = ioremap(mac_res->start, resource_size(mac_res));
+ memcpy_fromio(eth_mac, mac, 6);
+
+ if (!of_property_read_u32(np, "mac-increment", &mac_inc))
+ eth_mac[5] += mac_inc;
+
+ return 0;
+}
+
+static struct of_device_id eth_mac_ids[] = {
+ { .compatible = "lantiq,eth-mac" },
+ { /* sentinel */ }
+};
+
+static struct platform_driver eth_mac_driver = {
+ .driver = {
+ .name = "lantiq,eth-mac",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(eth_mac_ids),
+ },
+};
+
+static int __init of_eth_mac_init(void)
+{
+ return platform_driver_probe(&eth_mac_driver, of_eth_mac_probe);
+}
+device_initcall(of_eth_mac_init);
Index: linux-3.7-rc8/drivers/net/ethernet/lantiq_etop.c
===================================================================
--- linux-3.7-rc8.orig/drivers/net/ethernet/lantiq_etop.c 2012-12-13 10:59:54.176314899 +0100
+++ linux-3.7-rc8/drivers/net/ethernet/lantiq_etop.c 2012-12-13 10:59:57.308314977 +0100
@@ -816,7 +816,8 @@
ltq_etop_change_mtu(dev, 1500);
- memcpy(&mac.sa_data, priv->mac, ETH_ALEN);
+ if (priv->mac)
+ memcpy(&mac.sa_data, priv->mac, ETH_ALEN);
if (!is_valid_ether_addr(mac.sa_data)) {
pr_warn("etop: invalid MAC, using random\n");
random_ether_addr(mac.sa_data);
@@ -940,7 +941,9 @@
priv->tx_irq = irqres[0].start;
priv->rx_irq = irqres[1].start;
priv->mii_mode = of_get_phy_mode(pdev->dev.of_node);
- priv->mac = of_get_mac_address(pdev->dev.of_node);
+ priv->mac = ltq_get_eth_mac();
+ if (!priv->mac)
+ priv->mac = of_get_mac_address(pdev->dev.of_node);
priv->clk_ppe = clk_get(&pdev->dev, NULL);
if (IS_ERR(priv->clk_ppe))
Index: linux-3.7-rc8/arch/mips/lantiq/xway/rt_eep.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-3.7-rc8/arch/mips/lantiq/xway/rt_eep.c 2012-12-13 13:55:43.132579350 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/rt2x00_platform.h>
+
+extern int (*ltq_pci_plat_dev_init)(struct pci_dev *dev);
+static struct rt2x00_platform_data rt2x00_pdata;
+
+static int rt2x00_pci_plat_dev_init(struct pci_dev *dev)
+{
+ dev->dev.platform_data = &rt2x00_pdata;
+ return 0;
+}
+
+int __init of_ralink_eeprom_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ const char *eeprom;
+
+ if (of_property_read_string(np, "ralink,eeprom", &eeprom)) {
+ dev_err(&pdev->dev, "failed to load eeprom filename\n");
+ return 0;
+ }
+
+ rt2x00_pdata.eeprom_file_name = kstrdup(eeprom, GFP_KERNEL);
+// rt2x00_pdata.mac_address = mac;
+ ltq_pci_plat_dev_init = rt2x00_pci_plat_dev_init;
+
+ dev_info(&pdev->dev, "using %s as eeprom\n", eeprom);
+
+ return 0;
+}
+
+static struct of_device_id ralink_eeprom_ids[] = {
+ { .compatible = "ralink,eeprom" },
+ { }
+};
+
+static struct platform_driver ralink_eeprom_driver = {
+ .driver = {
+ .name = "ralink,eeprom",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(ralink_eeprom_ids),
+ },
+};
+
+static int __init of_ralink_eeprom_init(void)
+{
+ return platform_driver_probe(&ralink_eeprom_driver, of_ralink_eeprom_probe);
+}
+device_initcall(of_ralink_eeprom_init);

View file

@ -0,0 +1,79 @@
Index: linux-3.7-rc8/arch/mips/lantiq/xway/Makefile
===================================================================
--- linux-3.7-rc8.orig/arch/mips/lantiq/xway/Makefile 2012-12-13 13:40:23.000000000 +0100
+++ linux-3.7-rc8/arch/mips/lantiq/xway/Makefile 2012-12-13 13:40:49.788556963 +0100
@@ -1,5 +1,5 @@
obj-y := prom.o sysctrl.o clk.o reset.o dma.o timer.o dcdc.o
-obj-y += ath_eep.o rt_eep.o eth_mac.o
+obj-y += ath_eep.o rt_eep.o eth_mac.o vmmc.o
obj-$(CONFIG_XRX200_PHY_FW) += xrx200_phy_fw.o
Index: linux-3.7-rc8/arch/mips/lantiq/xway/vmmc.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-3.7-rc8/arch/mips/lantiq/xway/vmmc.c 2012-12-13 13:40:30.520556476 +0100
@@ -0,0 +1,63 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/dma-mapping.h>
+
+#include <lantiq_soc.h>
+
+static unsigned int *cp1_base = 0;
+unsigned int* ltq_get_cp1_base(void)
+{
+ if (!cp1_base)
+ panic("no cp1 base was set\n");
+ return cp1_base;
+}
+EXPORT_SYMBOL(ltq_get_cp1_base);
+
+static int __devinit vmmc_probe(struct platform_device *pdev)
+{
+#define CP1_SIZE (1 << 20)
+ int gpio_count;
+ dma_addr_t dma;
+ cp1_base =
+ (void*)CPHYSADDR(dma_alloc_coherent(NULL, CP1_SIZE, &dma, GFP_ATOMIC));
+
+ gpio_count = of_gpio_count(pdev->dev.of_node);
+ while (gpio_count) {
+ enum of_gpio_flags flags;
+ int gpio = of_get_gpio_flags(pdev->dev.of_node, --gpio_count, &flags);
+ if (gpio_request(gpio, "vmmc-relay"))
+ continue;
+ dev_info(&pdev->dev, "requested GPIO %d\n", gpio);
+ gpio_direction_output(gpio, (flags & OF_GPIO_ACTIVE_LOW) ? (0) : (1));
+ }
+
+ dev_info(&pdev->dev, "reserved %dMB at 0x%p", CP1_SIZE >> 20, cp1_base);
+
+ return 0;
+}
+
+static const struct of_device_id vmmc_match[] = {
+ { .compatible = "lantiq,vmmc" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, vmmc_match);
+
+static struct platform_driver vmmc_driver = {
+ .probe = vmmc_probe,
+ .driver = {
+ .name = "lantiq,vmmc",
+ .owner = THIS_MODULE,
+ .of_match_table = vmmc_match,
+ },
+};
+
+module_platform_driver(vmmc_driver);

View file

@ -5,15 +5,28 @@ CONFIG_INPUT=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_POLLDEV=y
# CONFIG_ISDN is not set
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_M25PXX_USE_FAST_READ=y
CONFIG_MTD_M25P80=y
CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_ECC=y
CONFIG_MTD_NAND_PLATFORM=y
CONFIG_MTD_NAND_XWAY=y
# CONFIG_MTD_PHYSMAP_OF is not set
# CONFIG_MTD_SM_COMMON is not set
CONFIG_MTD_UIMAGE_SPLIT=y
CONFIG_NLS=y
# CONFIG_PROC_DEVICETREE is not set
CONFIG_RTL8306_PHY=y
CONFIG_RTL8366S_PHY=y
CONFIG_RTL8367B_PHY=y
CONFIG_RTL8367_PHY=y
CONFIG_SPI=y
CONFIG_SPI_BITBANG=y
CONFIG_SPI_GPIO=y
CONFIG_SPI_MASTER=y
CONFIG_SPI_XWAY=y
CONFIG_USB=y
CONFIG_USB_COMMON=y
# CONFIG_USB_EHCI_HCD is not set
CONFIG_USB_SUPPORT=y
# CONFIG_USB_UHCI_HCD is not set

View file

@ -1,25 +1,104 @@
define Profile/ARV4525PW
NAME:=Speedport W502V Typ A - ARV4525PW
PACKAGES:=kmod-ath5k wpad-mini \
kmod-ltq-adsl-danube-mei kmod-ltq-adsl-danube \
kmod-ltq-adsl-danube-fw-b kmod-ltq-atm-danube \
ltq-adsl-app ppp-mod-pppoa
endef
$(eval $(call Profile,ARV4525PW))
define Profile/ARV7525PW
NAME:=Speedport W303V - ARV7525PW
NAME:=Speedport W303V Typ A - ARV7525PW
PACKAGES:=kmod-rt2800-pci wpad-mini \
kmod-ltq-adsl-danube-mei kmod-ltq-adsl-danube \
kmod-ltq-adsl-danube-fw-b kmod-ltq-atm-danube \
ltq-adsl-app ppp-mod-pppoa
endef
$(eval $(call Profile,ARV7525PW))
define Profile/ARV4518PW
NAME:=SMC7908A-ISP, Airties WAV-221 - ARV4518PW
PACKAGES:=kmod-ltq-hcd-danube kmod-ledtrig-usbdev \
kmod-ltq-adsl-danube-mei kmod-ltq-adsl-danube \
kmod-ltq-adsl-danube-fw-b kmod-ltq-atm-danube \
ltq-adsl-app ppp-mod-pppoa \
kmod-ath5k wpad-mini \
swconfig
endef
$(eval $(call Profile,ARV4518PW))
define Profile/ARV4510PW
NAME:=Wippies Homebox - ARV4510PW
PACKAGES:=kmod-ledtrig-usbdev kmod-usb2 kmod-usb-uhci \
kmod-ltq-adsl-danube-mei kmod-ltq-adsl-danube \
kmod-ltq-adsl-danube-fw-b kmod-ltq-atm-danube \
ltq-adsl-app ppp-mod-pppoa \
kmod-rt61 wpad-mini \
swconfig
endef
$(eval $(call Profile,ARV4510PW))
define Profile/ARV7518PW
NAME:=Astoria - ARV7518PW
PACKAGES:=kmod-ltq-hcd-danube kmod-ledtrig-usbdev \
kmod-ltq-adsl-danube-mei kmod-ltq-adsl-danube \
kmod-ltq-adsl-danube-fw-b kmod-ltq-atm-danube \
ltq-adsl-app ppp-mod-pppoa \
kmod-ath9k wpad-mini \
swconfig
endef
$(eval $(call Profile,ARV7518PW))
define Profile/ARV4520PW
NAME:=Easybox 800, WAV-281 - ARV4520PW
PACKAGES:=kmod-ltq-hcd-danube kmod-ledtrig-usbdev \
kmod-ltq-adsl-danube-mei kmod-ltq-adsl-danube \
kmod-ltq-adsl-danube-fw-b kmod-ltq-atm-danube \
ltq-adsl-app ppp-mod-pppoa \
kmod-rt61-pci wpad-mini \
swconfig
endef
$(eval $(call Profile,ARV4520PW))
define Profile/ARV452CQW
NAME:=Easybox 801 - ARV452CQW
PACKAGES:=kmod-ltq-hcd-danube kmod-ledtrig-usbdev \
kmod-ath5k wpad-mini \
kmod-ltq-adsl-danube-mei kmod-ltq-adsl-danube \
kmod-ltq-adsl-danube-fw-b kmod-ltq-atm-danube \
ltq-adsl-app ppp-mod-pppoa \
swconfig
endef
$(eval $(call Profile,ARV452CQW))
define Profile/ARV752DPW
NAME:=Easybox 802 - ARV752DPW
PACKAGES:=kmod-ltq-hcd-danube kmod-ledtrig-usbdev \
kmod-ltq-adsl-danube-mei kmod-ltq-adsl-danube \
kmod-ltq-adsl-danube-fw-b kmod-ltq-atm-danube \
ltq-adsl-app ppp-mod-pppoa \
kmod-ltq-tapi kmod-ltq-vmmc \
kmod-rt2800-pci wpad-mini \
swconfig
endef
$(eval $(call Profile,ARV752DPW))
define Profile/ARV752DPW22
NAME:=Easybox 803 - ARV752DPW22
PACKAGES:= kmod-usb-core kmod-usb2 kmod-usb-uhci kmod-usb-dwc-otg kmod-ledtrig-usbdev \
kmod-ltq-dsl-firmware-b-danube
PACKAGES:=kmod-usb2 kmod-usb-uhci kmod-ltq-hcd-danube kmod-ledtrig-usbdev \
kmod-ltq-adsl-danube-mei kmod-ltq-adsl-danube \
kmod-ltq-adsl-danube-fw-b kmod-ltq-atm-danube \
ltq-adsl-app ppp-mod-pppoa \
kmod-ltq-tapi kmod-ltq-vmmc \
swconfig
endef
$(eval $(call Profile,ARV752DPW22))

View file

@ -0,0 +1,10 @@
define Profile/FRITZ7320
NAME:=1&1 HomeServer - FRITZ7320
PACKAGES:=kmod-ath9k wpad-mini \
kmod-ltq-adsl-ar9-mei kmod-ltq-adsl-ar9 \
kmod-ltq-adsl-ar9-fw-b kmod-ltq-atm-ar9 \
ltq-adsl-app ppp-mod-pppoa \
kmod-ltq-deu-ar9
endef
$(eval $(call Profile,FRITZ7320))

View file

@ -1,19 +1,17 @@
define Profile/EASY80920-NOR
NAME:=EASY80920-NOR
define Profile/EASY50712
NAME:=Lantiq Danube - EASY50712
endef
define Profile/EASY80920-NOR/Description
Lantiq EASY80920 evalkit (NOR)
$(eval $(call Profile,EASY50712))
define Profile/EASY80920NOR
NAME:=Lantiq VR9 - EASY80920NOR
endef
$(eval $(call Profile,EASY80920-NOR))
$(eval $(call Profile,EASY80920NOR))
define Profile/EASY80920-NAND
NAME:=EASY80920-NAND
define Profile/EASY80920NAND
NAME:=Lantiq VR9 - EASY80920NAND
endef
define Profile/EASY80920-NAND/Description
Lantiq EASY80920 evalkit (NAND)
endef
$(eval $(call Profile,EASY80920-NAND))
$(eval $(call Profile,EASY80920NAND))

View file

@ -0,0 +1,21 @@
define Profile/DGN3500A
NAME:=Netgear DGN3500A
PACKAGES:=kmod-ath9k wpad-mini \
kmod-ltq-adsl-ar9-mei kmod-ltq-adsl-ar9 \
kmod-ltq-adsl-ar9-fw-a kmod-ltq-atm-ar9 \
ltq-adsl-app ppp-mod-pppoa \
kmod-ltq-deu-ar9
endef
$(eval $(call Profile,DGN3500A))
define Profile/DGN3500B
NAME:=Netgear DGN3500B
PACKAGES:=kmod-ath9k wpad-mini \
kmod-ltq-adsl-ar9-mei kmod-ltq-adsl-ar9 \
kmod-ltq-adsl-ar9-fw-b kmod-ltq-atm-ar9 \
ltq-adsl-app ppp-mod-pppoa \
kmod-ltq-deu-ar9
endef
$(eval $(call Profile,DGN3500B))

View file

@ -3,7 +3,7 @@ SUBTARGET:=xway
BOARDNAME:=XWAY
FEATURES:=squashfs jffs2 atm
DEFAULT_PACKAGES+=swconfig kmod-leds-gpio kmod-button-hotplug
DEFAULT_PACKAGES+=kmod-leds-gpio kmod-button-hotplug kmod-input-gpio-keys-polled
define Target/Description
Lantiq XWAY