diff options
38 files changed, 1545 insertions, 60 deletions
diff --git a/target/linux/lantiq/patches-3.14/0001-MIPS-lantiq-add-pcie-driver.patch b/target/linux/lantiq/patches-3.14/0001-MIPS-lantiq-add-pcie-driver.patch index 9a9ac3611d..3b4ad037d0 100644 --- a/target/linux/lantiq/patches-3.14/0001-MIPS-lantiq-add-pcie-driver.patch +++ b/target/linux/lantiq/patches-3.14/0001-MIPS-lantiq-add-pcie-driver.patch @@ -1,7 +1,7 @@ From 6f933347d0b4ed02d9534f5fa07f7b99f13eeaa1 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Thu, 7 Aug 2014 18:12:28 +0200 -Subject: [PATCH 01/31] MIPS: lantiq: add pcie driver +Subject: [PATCH 01/36] MIPS: lantiq: add pcie driver Signed-off-by: John Crispin <blogic@openwrt.org> --- diff --git a/target/linux/lantiq/patches-3.14/0002-MIPS-lantiq-dtb-image-hack.patch b/target/linux/lantiq/patches-3.14/0002-MIPS-lantiq-dtb-image-hack.patch index 0b23afe06b..ce6c637131 100644 --- a/target/linux/lantiq/patches-3.14/0002-MIPS-lantiq-dtb-image-hack.patch +++ b/target/linux/lantiq/patches-3.14/0002-MIPS-lantiq-dtb-image-hack.patch @@ -1,7 +1,7 @@ From 17348293f7f8103c97c8d2a6b0ef36eae06ec371 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Wed, 13 Mar 2013 09:36:16 +0100 -Subject: [PATCH 02/31] MIPS: lantiq: dtb image hack +Subject: [PATCH 02/36] MIPS: lantiq: dtb image hack Signed-off-by: John Crispin <blogic@openwrt.org> --- diff --git a/target/linux/lantiq/patches-3.14/0003-MIPS-lantiq-handle-vmmc-memory-reservation.patch b/target/linux/lantiq/patches-3.14/0003-MIPS-lantiq-handle-vmmc-memory-reservation.patch index 36a53f2bae..eb1e2004a1 100644 --- a/target/linux/lantiq/patches-3.14/0003-MIPS-lantiq-handle-vmmc-memory-reservation.patch +++ b/target/linux/lantiq/patches-3.14/0003-MIPS-lantiq-handle-vmmc-memory-reservation.patch @@ -1,7 +1,7 @@ From 16e315864132b59749faff739230daf4cee9abbb Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Wed, 13 Mar 2013 10:04:01 +0100 -Subject: [PATCH 03/31] MIPS: lantiq: handle vmmc memory reservation +Subject: [PATCH 03/36] MIPS: lantiq: handle vmmc memory reservation Signed-off-by: John Crispin <blogic@openwrt.org> --- diff --git a/target/linux/lantiq/patches-3.14/0004-MIPS-lantiq-add-atm-hack.patch b/target/linux/lantiq/patches-3.14/0004-MIPS-lantiq-add-atm-hack.patch index f4262e53f9..a01967f9c7 100644 --- a/target/linux/lantiq/patches-3.14/0004-MIPS-lantiq-add-atm-hack.patch +++ b/target/linux/lantiq/patches-3.14/0004-MIPS-lantiq-add-atm-hack.patch @@ -1,7 +1,7 @@ From 9afadf01b1be371ee88491819aa67364684461f9 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Fri, 3 Aug 2012 10:27:25 +0200 -Subject: [PATCH 04/31] MIPS: lantiq: add atm hack +Subject: [PATCH 04/36] MIPS: lantiq: add atm hack Signed-off-by: John Crispin <blogic@openwrt.org> --- diff --git a/target/linux/lantiq/patches-3.14/0005-MIPS-lantiq-add-reset-controller-api-support.patch b/target/linux/lantiq/patches-3.14/0005-MIPS-lantiq-add-reset-controller-api-support.patch index 36f6410686..c4540c9306 100644 --- a/target/linux/lantiq/patches-3.14/0005-MIPS-lantiq-add-reset-controller-api-support.patch +++ b/target/linux/lantiq/patches-3.14/0005-MIPS-lantiq-add-reset-controller-api-support.patch @@ -1,7 +1,7 @@ From 223f1c46e109a8420765aee099a5d1dc4ab7ee98 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Tue, 3 Sep 2013 13:18:12 +0200 -Subject: [PATCH 05/31] MIPS: lantiq: add reset-controller api support +Subject: [PATCH 05/36] MIPS: lantiq: add reset-controller api support Add a reset-controller binding for the reset registers found on the lantiq SoC. diff --git a/target/linux/lantiq/patches-3.14/0006-MIPS-lantiq-reboot-gphy-on-restart.patch b/target/linux/lantiq/patches-3.14/0006-MIPS-lantiq-reboot-gphy-on-restart.patch index 09a3b12b8c..42acac21f2 100644 --- a/target/linux/lantiq/patches-3.14/0006-MIPS-lantiq-reboot-gphy-on-restart.patch +++ b/target/linux/lantiq/patches-3.14/0006-MIPS-lantiq-reboot-gphy-on-restart.patch @@ -1,7 +1,7 @@ From f81979f4b297693ac70616feaa4a79bdcb11db35 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Thu, 7 Aug 2014 18:55:57 +0200 -Subject: [PATCH 06/31] MIPS: lantiq: reboot gphy on restart +Subject: [PATCH 06/36] MIPS: lantiq: reboot gphy on restart Signed-off-by: John Crispin <blogic@openwrt.org> --- diff --git a/target/linux/lantiq/patches-3.14/0007-MIPS-lantiq-add-basic-tffs-driver.patch b/target/linux/lantiq/patches-3.14/0007-MIPS-lantiq-add-basic-tffs-driver.patch index a031b8e9a0..a41d48ed32 100644 --- a/target/linux/lantiq/patches-3.14/0007-MIPS-lantiq-add-basic-tffs-driver.patch +++ b/target/linux/lantiq/patches-3.14/0007-MIPS-lantiq-add-basic-tffs-driver.patch @@ -1,7 +1,7 @@ From d27ec8bb97db0f60d81ab255d51ac4e967362067 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Thu, 7 Aug 2014 18:34:19 +0200 -Subject: [PATCH 07/31] MIPS: lantiq: add basic tffs driver +Subject: [PATCH 07/36] MIPS: lantiq: add basic tffs driver Signed-off-by: John Crispin <blogic@openwrt.org> --- diff --git a/target/linux/lantiq/patches-3.14/0008-MIPS-lantiq-backport-old-timer-code.patch b/target/linux/lantiq/patches-3.14/0008-MIPS-lantiq-backport-old-timer-code.patch index bceda4c587..d946e560a4 100644 --- a/target/linux/lantiq/patches-3.14/0008-MIPS-lantiq-backport-old-timer-code.patch +++ b/target/linux/lantiq/patches-3.14/0008-MIPS-lantiq-backport-old-timer-code.patch @@ -1,7 +1,7 @@ From 94800350cb8d2f29dda2206b5e9a3772024ee168 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Thu, 7 Aug 2014 18:30:56 +0200 -Subject: [PATCH 08/31] MIPS: lantiq: backport old timer code +Subject: [PATCH 08/36] MIPS: lantiq: backport old timer code Signed-off-by: John Crispin <blogic@openwrt.org> --- diff --git a/target/linux/lantiq/patches-3.14/0030-MIPS-lantiq-command-line-work-around.patch b/target/linux/lantiq/patches-3.14/0009-MIPS-lantiq-command-line-work-around.patch index 77aee7ebeb..2536745095 100644 --- a/target/linux/lantiq/patches-3.14/0030-MIPS-lantiq-command-line-work-around.patch +++ b/target/linux/lantiq/patches-3.14/0009-MIPS-lantiq-command-line-work-around.patch @@ -1,7 +1,7 @@ -From 015e22a637fe6ab9f9d2d94d3be1b0b312d21b39 Mon Sep 17 00:00:00 2001 +From ed348924cd59ef0c8a4bc4e015e2b7e581a00fa8 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Tue, 12 Aug 2014 21:40:41 +0200 -Subject: [PATCH 30/31] MIPS: lantiq: command line work around +Subject: [PATCH 09/36] MIPS: lantiq: command line work around Signed-off-by: John Crispin <blogic@openwrt.org> --- diff --git a/target/linux/lantiq/patches-3.14/0010-MIPS-lantiq-export-soc-type.patch b/target/linux/lantiq/patches-3.14/0010-MIPS-lantiq-export-soc-type.patch new file mode 100644 index 0000000000..de1cd52873 --- /dev/null +++ b/target/linux/lantiq/patches-3.14/0010-MIPS-lantiq-export-soc-type.patch @@ -0,0 +1,46 @@ +From 6804142b47f2634b0657e4dfcec7a34e982b6ddb Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Wed, 10 Sep 2014 22:29:21 +0200 +Subject: [PATCH 10/36] MIPS: lantiq: export soc type +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com> +--- + arch/mips/include/asm/mach-lantiq/lantiq.h | 2 ++ + arch/mips/lantiq/prom.c | 5 +++++ + 2 files changed, 7 insertions(+) + +diff --git a/arch/mips/include/asm/mach-lantiq/lantiq.h b/arch/mips/include/asm/mach-lantiq/lantiq.h +index f196cce..4e5ae65 100644 +--- a/arch/mips/include/asm/mach-lantiq/lantiq.h ++++ b/arch/mips/include/asm/mach-lantiq/lantiq.h +@@ -48,6 +48,8 @@ extern struct clk *clk_get_ppe(void); + extern unsigned char ltq_boot_select(void); + /* find out what caused the last cpu reset */ + extern int ltq_reset_cause(void); ++/* find out the soc type */ ++extern int ltq_soc_type(void); + + #define IOPORT_RESOURCE_START 0x10000000 + #define IOPORT_RESOURCE_END 0xffffffff +diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c +index 227feed..4c652c6 100644 +--- a/arch/mips/lantiq/prom.c ++++ b/arch/mips/lantiq/prom.c +@@ -36,6 +36,11 @@ const char *get_system_type(void) + return soc_info.sys_type; + } + ++int ltq_soc_type(void) ++{ ++ return soc_info.type; ++} ++ + void prom_free_prom_memory(void) + { + } +-- +1.7.10.4 + diff --git a/target/linux/lantiq/patches-3.14/0011-lantiq-add-support-for-xrx200-firmware-depending-on-.patch b/target/linux/lantiq/patches-3.14/0011-lantiq-add-support-for-xrx200-firmware-depending-on-.patch new file mode 100644 index 0000000000..36d03b19c9 --- /dev/null +++ b/target/linux/lantiq/patches-3.14/0011-lantiq-add-support-for-xrx200-firmware-depending-on-.patch @@ -0,0 +1,46 @@ +From 85f0df34dee96048515ef1e01d88524bd579f8e0 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Wed, 10 Sep 2014 22:39:19 +0200 +Subject: [PATCH 11/36] lantiq: add support for xrx200 firmware depending on + soc type +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com> +--- + arch/mips/lantiq/xway/xrx200_phy_fw.c | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +diff --git a/arch/mips/lantiq/xway/xrx200_phy_fw.c b/arch/mips/lantiq/xway/xrx200_phy_fw.c +index d4d9d31..3479b77 100644 +--- a/arch/mips/lantiq/xway/xrx200_phy_fw.c ++++ b/arch/mips/lantiq/xway/xrx200_phy_fw.c +@@ -24,7 +24,23 @@ static dma_addr_t xway_gphy_load(struct platform_device *pdev) + void *fw_addr; + size_t size; + +- if (of_property_read_string(pdev->dev.of_node, "firmware", &fw_name)) { ++ if (of_get_property(pdev->dev.of_node, "firmware1", NULL) || of_get_property(pdev->dev.of_node, "firmware2", NULL)) { ++ switch(ltq_soc_type()) { ++ case SOC_TYPE_VR9: ++ if (of_property_read_string(pdev->dev.of_node, "firmware1", &fw_name)) { ++ dev_err(&pdev->dev, "failed to load firmware filename\n"); ++ return 0; ++ } ++ break; ++ case SOC_TYPE_VR9_2: ++ if (of_property_read_string(pdev->dev.of_node, "firmware2", &fw_name)) { ++ dev_err(&pdev->dev, "failed to load firmware filename\n"); ++ return 0; ++ } ++ break; ++ } ++ } ++ else if (of_property_read_string(pdev->dev.of_node, "firmware", &fw_name)) { + dev_err(&pdev->dev, "failed to load firmware filename\n"); + return 0; + } +-- +1.7.10.4 + diff --git a/target/linux/lantiq/patches-3.14/0009-pinctrl-lantiq-fix-up-pinmux.patch b/target/linux/lantiq/patches-3.14/0012-pinctrl-lantiq-fix-up-pinmux.patch index 267c89860c..9b45bf7913 100644 --- a/target/linux/lantiq/patches-3.14/0009-pinctrl-lantiq-fix-up-pinmux.patch +++ b/target/linux/lantiq/patches-3.14/0012-pinctrl-lantiq-fix-up-pinmux.patch @@ -1,7 +1,7 @@ -From 29452de974f2cdc87876dbdc18a16405ef80c05f Mon Sep 17 00:00:00 2001 +From 25494c55a4007a1409f53ddbafd661636e47ea34 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Fri, 9 Aug 2013 20:38:15 +0200 -Subject: [PATCH 09/31] pinctrl/lantiq: fix up pinmux +Subject: [PATCH 12/36] pinctrl/lantiq: fix up pinmux We found out how to set the gphy led pinmuxing. diff --git a/target/linux/lantiq/patches-3.14/0013-MTD-lantiq-xway-fix-invalid-operator.patch b/target/linux/lantiq/patches-3.14/0013-MTD-lantiq-xway-fix-invalid-operator.patch index 5aad493a50..7d900fac79 100644 --- a/target/linux/lantiq/patches-3.14/0013-MTD-lantiq-xway-fix-invalid-operator.patch +++ b/target/linux/lantiq/patches-3.14/0013-MTD-lantiq-xway-fix-invalid-operator.patch @@ -1,7 +1,7 @@ -From c243da18ea2a02e8cfb3f821232783376131948a Mon Sep 17 00:00:00 2001 +From 8e34da603f442624bb70e887d8f42064bb924224 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Sun, 28 Jul 2013 18:03:54 +0200 -Subject: [PATCH 13/31] MTD: lantiq: xway: fix invalid operator +Subject: [PATCH 13/36] MTD: lantiq: xway: fix invalid operator xway_read_byte should use a logic or and not an add operator when working out the nand address. diff --git a/target/linux/lantiq/patches-3.14/0014-MTD-lantiq-xway-the-latched-command-should-be-persis.patch b/target/linux/lantiq/patches-3.14/0014-MTD-lantiq-xway-the-latched-command-should-be-persis.patch index a8b5c749fb..d3c197ef7e 100644 --- a/target/linux/lantiq/patches-3.14/0014-MTD-lantiq-xway-the-latched-command-should-be-persis.patch +++ b/target/linux/lantiq/patches-3.14/0014-MTD-lantiq-xway-the-latched-command-should-be-persis.patch @@ -1,7 +1,7 @@ -From b2ef79004dd8e26f3a4625610bff5362b70e956b Mon Sep 17 00:00:00 2001 +From b454cefd675fc1bd3d8c690c1bd1d8f4678e9922 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Sun, 28 Jul 2013 18:06:39 +0200 -Subject: [PATCH 14/31] MTD: lantiq: xway: the latched command should be +Subject: [PATCH 14/36] MTD: lantiq: xway: the latched command should be persistent Signed-off-by: John Crispin <blogic@openwrt.org> diff --git a/target/linux/lantiq/patches-3.14/0015-MTD-lantiq-xway-remove-endless-loop.patch b/target/linux/lantiq/patches-3.14/0015-MTD-lantiq-xway-remove-endless-loop.patch index 51c8dd3c63..910fc148ff 100644 --- a/target/linux/lantiq/patches-3.14/0015-MTD-lantiq-xway-remove-endless-loop.patch +++ b/target/linux/lantiq/patches-3.14/0015-MTD-lantiq-xway-remove-endless-loop.patch @@ -1,7 +1,7 @@ -From 836c433cec22555d81bf02bb205dee5772b8df08 Mon Sep 17 00:00:00 2001 +From 76e153079f02d26e3357302d2886a0c8aaaec64d Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Sun, 28 Jul 2013 18:02:06 +0200 -Subject: [PATCH 15/31] MTD: lantiq: xway: remove endless loop +Subject: [PATCH 15/36] MTD: lantiq: xway: remove endless loop The reset loop logic could run into a endless loop. Lets fix it as requested. diff --git a/target/linux/lantiq/patches-3.14/0016-MTD-lantiq-xway-add-missing-write_buf-and-read_buf-t.patch b/target/linux/lantiq/patches-3.14/0016-MTD-lantiq-xway-add-missing-write_buf-and-read_buf-t.patch index e00dc47941..8d07654d47 100644 --- a/target/linux/lantiq/patches-3.14/0016-MTD-lantiq-xway-add-missing-write_buf-and-read_buf-t.patch +++ b/target/linux/lantiq/patches-3.14/0016-MTD-lantiq-xway-add-missing-write_buf-and-read_buf-t.patch @@ -1,7 +1,7 @@ -From 6f5bf300afa3c6f41a973fb3f39827db59512343 Mon Sep 17 00:00:00 2001 +From 65df9d63eaee02c25e879b33dd42aceb78e57842 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Sun, 28 Jul 2013 17:59:51 +0200 -Subject: [PATCH 16/31] MTD: lantiq: xway: add missing write_buf and read_buf +Subject: [PATCH 16/36] MTD: lantiq: xway: add missing write_buf and read_buf to nand driver Signed-off-by: John Crispin <blogic@openwrt.org> diff --git a/target/linux/lantiq/patches-3.14/0017-MTD-xway-fix-nand-locking.patch b/target/linux/lantiq/patches-3.14/0017-MTD-xway-fix-nand-locking.patch index 9f87586d34..882a405f0a 100644 --- a/target/linux/lantiq/patches-3.14/0017-MTD-xway-fix-nand-locking.patch +++ b/target/linux/lantiq/patches-3.14/0017-MTD-xway-fix-nand-locking.patch @@ -1,7 +1,7 @@ -From bbaf5aaf4b430f2139e5f561b6372008d26766a2 Mon Sep 17 00:00:00 2001 +From aa705c1b0860da91f2ed1a4c0b57337e6de689e1 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Thu, 7 Aug 2014 18:55:31 +0200 -Subject: [PATCH 17/31] MTD: xway: fix nand locking +Subject: [PATCH 17/36] MTD: xway: fix nand locking Signed-off-by: John Crispin <blogic@openwrt.org> --- diff --git a/target/linux/lantiq/patches-3.14/0018-MTD-nand-lots-of-xrx200-fixes.patch b/target/linux/lantiq/patches-3.14/0018-MTD-nand-lots-of-xrx200-fixes.patch new file mode 100644 index 0000000000..1e1f299766 --- /dev/null +++ b/target/linux/lantiq/patches-3.14/0018-MTD-nand-lots-of-xrx200-fixes.patch @@ -0,0 +1,130 @@ +From 997a8965db8417266bea3fbdcfa3e5655a1b52fa Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Tue, 9 Sep 2014 23:12:15 +0200 +Subject: [PATCH 18/36] MTD: nand: lots of xrx200 fixes + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + drivers/mtd/nand/xway_nand.c | 63 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 63 insertions(+) + +diff --git a/drivers/mtd/nand/xway_nand.c b/drivers/mtd/nand/xway_nand.c +index e430f2d..fedf2c4 100644 +--- a/drivers/mtd/nand/xway_nand.c ++++ b/drivers/mtd/nand/xway_nand.c +@@ -54,8 +54,27 @@ + #define NAND_CON_CSMUX (1 << 1) + #define NAND_CON_NANDM 1 + ++#define DANUBE_PCI_REG32( addr ) (*(volatile u32 *)(addr)) ++#define PCI_CR_PR_OFFSET (KSEG1+0x1E105400) ++#define PCI_CR_PC_ARB (PCI_CR_PR_OFFSET + 0x0080) ++ + static u32 xway_latchcmd; + ++/* ++ * req_mask provides a mechanism to prevent interference between ++ * nand and pci (probably only relevant for the BT Home Hub 2B). ++ * Setting it causes the corresponding pci req pins to be masked ++ * during nand access, and also moves ebu locking from the read/write ++ * functions to the chip select function to ensure that the whole ++ * operation runs with interrupts disabled. ++ * In addition it switches on some extra waiting in xway_cmd_ctrl(). ++ * This seems to be necessary if the ebu_cs1 pin has open-drain disabled, ++ * which in turn seems to be necessary for the nor chip to be recognised ++ * reliably, on a board (Home Hub 2B again) which has both nor and nand. ++ */ ++ ++static __be32 req_mask = 0; ++ + static void xway_reset_chip(struct nand_chip *chip) + { + unsigned long nandaddr = (unsigned long) chip->IO_ADDR_W; +@@ -86,12 +105,24 @@ static void xway_select_chip(struct mtd_info *mtd, int chip) + case -1: + ltq_ebu_w32_mask(NAND_CON_CE, 0, EBU_NAND_CON); + ltq_ebu_w32_mask(NAND_CON_NANDM, 0, EBU_NAND_CON); ++ ++ if (req_mask) { ++ /* Unmask all external PCI request */ ++ DANUBE_PCI_REG32(PCI_CR_PC_ARB) &= ~(req_mask << 16); ++ } + spin_unlock_irqrestore(&ebu_lock, csflags); ++ + break; + case 0: + spin_lock_irqsave(&ebu_lock, csflags); ++ if (req_mask) { ++ /* Mask all external PCI request */ ++ DANUBE_PCI_REG32(PCI_CR_PC_ARB) |= (req_mask << 16); ++ } ++ + ltq_ebu_w32_mask(0, NAND_CON_NANDM, EBU_NAND_CON); + ltq_ebu_w32_mask(0, NAND_CON_CE, EBU_NAND_CON); ++ + break; + default: + BUG(); +@@ -103,6 +134,12 @@ static void xway_cmd_ctrl(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 (req_mask) { ++ if (cmd != NAND_CMD_STATUS) ++ ltq_ebu_w32(EBU_NAND_WAIT, 0); /* Clear nand ready */ ++ } ++ ++ + if (ctrl & NAND_CTRL_CHANGE) { + if (ctrl & NAND_CLE) + xway_latchcmd = NAND_WRITE_CMD; +@@ -115,6 +152,24 @@ static void xway_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) + while ((ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0) + ; + } ++ ++ if (req_mask) { ++ /* ++ * program and erase have their own busy handlers ++ * status and sequential in needs no delay ++ */ ++ switch (cmd) { ++ case NAND_CMD_ERASE1: ++ case NAND_CMD_SEQIN: ++ case NAND_CMD_STATUS: ++ case NAND_CMD_READID: ++ return; ++ } ++ ++ /* wait until command is processed */ ++ while ((ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_RD) == 0) ++ ; ++ } + } + + static int xway_dev_ready(struct mtd_info *mtd) +@@ -157,6 +212,8 @@ static int xway_nand_probe(struct platform_device *pdev) + { + struct nand_chip *this = platform_get_drvdata(pdev); + unsigned long nandaddr = (unsigned long) this->IO_ADDR_W; ++ const __be32 *req_mask_ptr = of_get_property(pdev->dev.of_node, ++ "req-mask", NULL); + const __be32 *cs = of_get_property(pdev->dev.of_node, + "lantiq,cs", NULL); + u32 cs_flag = 0; +@@ -165,6 +222,12 @@ static int xway_nand_probe(struct platform_device *pdev) + if (cs && (*cs == 1)) + cs_flag = NAND_CON_IN_CS1 | NAND_CON_OUT_CS1; + ++ /* ++ * Load the PCI req lines to mask from the device tree. If the ++ * property is not present, setting req_mask to 0 disables masking. ++ */ ++ req_mask = (req_mask_ptr ? *req_mask_ptr : 0); ++ + /* setup the EBU to run in NAND mode on our base addr */ + ltq_ebu_w32(CPHYSADDR(nandaddr) + | ADDSEL1_MASK(3) | ADDSEL1_REGEN, EBU_ADDSEL1); +-- +1.7.10.4 + diff --git a/target/linux/lantiq/patches-3.14/0018-MTD-lantiq-Add-NAND-support-on-Lantiq-Falcon-SoC.patch b/target/linux/lantiq/patches-3.14/0019-MTD-lantiq-Add-NAND-support-on-Lantiq-Falcon-SoC.patch index bfe5523299..ad1c2cf540 100644 --- a/target/linux/lantiq/patches-3.14/0018-MTD-lantiq-Add-NAND-support-on-Lantiq-Falcon-SoC.patch +++ b/target/linux/lantiq/patches-3.14/0019-MTD-lantiq-Add-NAND-support-on-Lantiq-Falcon-SoC.patch @@ -1,7 +1,7 @@ -From e2c285e95e75258c196fbc04a742d91be6d00f49 Mon Sep 17 00:00:00 2001 +From c21eed4418956ecc95966a2e174d47f58397071a Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Wed, 30 Jan 2013 21:12:47 +0100 -Subject: [PATCH 18/31] MTD: lantiq: Add NAND support on Lantiq Falcon SoC. +Subject: [PATCH 19/36] MTD: 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 falcon specific "struct platform_nand_data" diff --git a/target/linux/lantiq/patches-3.14/0012-MTD-lantiq-handle-NO_XIP-on-cfi0001-flash.patch b/target/linux/lantiq/patches-3.14/0020-MTD-lantiq-handle-NO_XIP-on-cfi0001-flash.patch index 432fa6b93e..4a2317030c 100644 --- a/target/linux/lantiq/patches-3.14/0012-MTD-lantiq-handle-NO_XIP-on-cfi0001-flash.patch +++ b/target/linux/lantiq/patches-3.14/0020-MTD-lantiq-handle-NO_XIP-on-cfi0001-flash.patch @@ -1,7 +1,7 @@ -From 6c476b89f3d685b41f2e216698fc8c90ddb11dfd Mon Sep 17 00:00:00 2001 +From e3b20f04e9f9cae1babe091fdc1d08d7703ae344 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Thu, 7 Aug 2014 18:18:00 +0200 -Subject: [PATCH 12/31] MTD: lantiq: handle NO_XIP on cfi0001 flash +Subject: [PATCH 20/36] MTD: lantiq: handle NO_XIP on cfi0001 flash Signed-off-by: John Crispin <blogic@openwrt.org> --- diff --git a/target/linux/lantiq/patches-3.14/0019-MTD-lantiq-Makes-the-Lantiq-flash-driver-try-jedec-p.patch b/target/linux/lantiq/patches-3.14/0021-MTD-lantiq-Makes-the-Lantiq-flash-driver-try-jedec-p.patch index 4f36270aa7..00a2c8e1d3 100644 --- a/target/linux/lantiq/patches-3.14/0019-MTD-lantiq-Makes-the-Lantiq-flash-driver-try-jedec-p.patch +++ b/target/linux/lantiq/patches-3.14/0021-MTD-lantiq-Makes-the-Lantiq-flash-driver-try-jedec-p.patch @@ -1,7 +1,7 @@ -From 4e2a4dcadb70985e86d9cebfca308891be377510 Mon Sep 17 00:00:00 2001 +From 11180582ca6efdff86314ae4514e9df3d34a6475 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Thu, 7 Aug 2014 18:57:30 +0200 -Subject: [PATCH 19/31] MTD: lantiq: Makes the Lantiq flash driver try jedec +Subject: [PATCH 21/36] MTD: lantiq: Makes the Lantiq flash driver try jedec probing if cfi probing fails. (Based on work by Simon Hayes first published on www.psidoc.com and diff --git a/target/linux/lantiq/patches-3.14/0022-MTD-m25p80-allow-loading-mtd-name-from-OF.patch b/target/linux/lantiq/patches-3.14/0022-MTD-m25p80-allow-loading-mtd-name-from-OF.patch new file mode 100644 index 0000000000..44970a5466 --- /dev/null +++ b/target/linux/lantiq/patches-3.14/0022-MTD-m25p80-allow-loading-mtd-name-from-OF.patch @@ -0,0 +1,41 @@ +From 4400e1f593ea40a51912128adb4f53d59e62cad8 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Wed, 10 Sep 2014 22:40:18 +0200 +Subject: [PATCH 22/36] MTD: m25p80: allow loading mtd name from OF + +In accordance with the physmap flash we should honour the linux,mtd-name +property when deciding what name the mtd device has. + +Signed-off-by: Thomas Langer <thomas.langer@lantiq.com> +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + drivers/mtd/devices/m25p80.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c +index ad19139..9f7b35a 100644 +--- a/drivers/mtd/devices/m25p80.c ++++ b/drivers/mtd/devices/m25p80.c +@@ -1097,6 +1097,10 @@ static int m25p_probe(struct spi_device *spi) + struct mtd_part_parser_data ppdata; + struct device_node *np = spi->dev.of_node; + int ret; ++ const char __maybe_unused *of_mtd_name = NULL; ++ ++ of_property_read_string(spi->dev.of_node, ++ "linux,mtd-name", &of_mtd_name); + + /* Platform data helps sort out which chip type we have, as + * well as how this board partitions it. If we don't have +@@ -1169,6 +1173,8 @@ static int m25p_probe(struct spi_device *spi) + + if (data && data->name) + flash->mtd.name = data->name; ++ else if (of_mtd_name) ++ flash->mtd.name = of_mtd_name; + else + flash->mtd.name = dev_name(&spi->dev); + +-- +1.7.10.4 + diff --git a/target/linux/lantiq/patches-3.14/0020-NET-PHY-adds-driver-for-lantiq-PHY11G.patch b/target/linux/lantiq/patches-3.14/0023-NET-PHY-adds-driver-for-lantiq-PHY11G.patch index 5d9d82bffa..bd769e7ff7 100644 --- a/target/linux/lantiq/patches-3.14/0020-NET-PHY-adds-driver-for-lantiq-PHY11G.patch +++ b/target/linux/lantiq/patches-3.14/0023-NET-PHY-adds-driver-for-lantiq-PHY11G.patch @@ -1,7 +1,7 @@ -From 6c895c9b0ceff79fdeb73876e35b536a312f851b Mon Sep 17 00:00:00 2001 +From 0a63ab263725c427051a8bbaa0732b749627da27 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Thu, 7 Aug 2014 18:15:36 +0200 -Subject: [PATCH 20/31] NET: PHY: adds driver for lantiq PHY11G +Subject: [PATCH 23/36] NET: PHY: adds driver for lantiq PHY11G Signed-off-by: John Crispin <blogic@openwrt.org> --- diff --git a/target/linux/lantiq/patches-3.14/0021-NET-lantiq-adds-PHY11G-firmware-blobs.patch b/target/linux/lantiq/patches-3.14/0024-NET-lantiq-adds-PHY11G-firmware-blobs.patch index 1de297fe14..e4c221c5bb 100644 --- a/target/linux/lantiq/patches-3.14/0021-NET-lantiq-adds-PHY11G-firmware-blobs.patch +++ b/target/linux/lantiq/patches-3.14/0024-NET-lantiq-adds-PHY11G-firmware-blobs.patch @@ -1,7 +1,7 @@ -From c64015eb950202f84829498a9c9daf949eded81f Mon Sep 17 00:00:00 2001 +From 77e89d5a28be35058041c79e9874ab26f222c603 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Mon, 22 Oct 2012 09:26:24 +0200 -Subject: [PATCH 21/31] NET: lantiq: adds PHY11G firmware blobs +Subject: [PATCH 24/36] NET: lantiq: adds PHY11G firmware blobs Signed-off-by: John Crispin <blogic@openwrt.org> --- diff --git a/target/linux/lantiq/patches-3.14/0022-NET-MIPS-lantiq-adds-xrx200-net.patch b/target/linux/lantiq/patches-3.14/0025-NET-MIPS-lantiq-adds-xrx200-net.patch index e47a519f3a..705430ea72 100644 --- a/target/linux/lantiq/patches-3.14/0022-NET-MIPS-lantiq-adds-xrx200-net.patch +++ b/target/linux/lantiq/patches-3.14/0025-NET-MIPS-lantiq-adds-xrx200-net.patch @@ -1,7 +1,7 @@ -From 96f50ccba9258367e5c3a48fe6295572daac69d3 Mon Sep 17 00:00:00 2001 +From fb0c9601f4414c39ff68e26b88681bef0bb04954 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Mon, 22 Oct 2012 12:22:23 +0200 -Subject: [PATCH 22/31] NET: MIPS: lantiq: adds xrx200-net +Subject: [PATCH 25/36] NET: MIPS: lantiq: adds xrx200-net --- drivers/net/ethernet/Kconfig | 8 +- diff --git a/target/linux/lantiq/patches-3.14/0023-NET-multi-phy-support.patch b/target/linux/lantiq/patches-3.14/0026-NET-multi-phy-support.patch index dcda21f487..9ffc6805a2 100644 --- a/target/linux/lantiq/patches-3.14/0023-NET-multi-phy-support.patch +++ b/target/linux/lantiq/patches-3.14/0026-NET-multi-phy-support.patch @@ -1,7 +1,7 @@ -From 2e265bc5154636daecf941acfea3087e7820877d Mon Sep 17 00:00:00 2001 +From c6feeeb407a3b8a6597ae377ba4dd138e185e3dd Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Sun, 27 Jul 2014 09:38:50 +0100 -Subject: [PATCH 23/31] NET: multi phy support +Subject: [PATCH 26/36] NET: multi phy support Signed-off-by: John Crispin <blogic@openwrt.org> --- diff --git a/target/linux/lantiq/patches-3.14/0024-NET-add-of_get_mac_address_mtd.patch b/target/linux/lantiq/patches-3.14/0027-NET-add-of_get_mac_address_mtd.patch index 7024278374..53489ed5a6 100644 --- a/target/linux/lantiq/patches-3.14/0024-NET-add-of_get_mac_address_mtd.patch +++ b/target/linux/lantiq/patches-3.14/0027-NET-add-of_get_mac_address_mtd.patch @@ -1,7 +1,7 @@ -From c4f036afb2016d21433c0214c55c01b8b9b7f4ee Mon Sep 17 00:00:00 2001 +From f393898476aef3e4f49c27725c3d2dd70fca38fe Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Sun, 27 Jul 2014 09:40:01 +0100 -Subject: [PATCH 24/31] NET: add of_get_mac_address_mtd() +Subject: [PATCH 27/36] NET: add of_get_mac_address_mtd() Many embedded devices have information such as mac addresses stored inside mtd devices. This patch allows us to add a property inside a node describing a diff --git a/target/linux/lantiq/patches-3.14/0028-NET-lantiq-various-etop-fixes.patch b/target/linux/lantiq/patches-3.14/0028-NET-lantiq-various-etop-fixes.patch new file mode 100644 index 0000000000..1c8821c88a --- /dev/null +++ b/target/linux/lantiq/patches-3.14/0028-NET-lantiq-various-etop-fixes.patch @@ -0,0 +1,937 @@ +From 870ed9cae083ff8a60a739ef7e74c5a1800533be Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Tue, 9 Sep 2014 22:45:34 +0200 +Subject: [PATCH 28/36] NET: lantiq: various etop fixes + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + drivers/net/ethernet/lantiq_etop.c | 555 +++++++++++++++++++++++++----------- + 1 file changed, 389 insertions(+), 166 deletions(-) + +diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c +index fd4b6ae..1712382 100644 +--- a/drivers/net/ethernet/lantiq_etop.c ++++ b/drivers/net/ethernet/lantiq_etop.c +@@ -11,7 +11,7 @@ + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + * +- * Copyright (C) 2011 John Crispin <blogic@openwrt.org> ++ * Copyright (C) 2011-12 John Crispin <blogic@openwrt.org> + */ + + #include <linux/kernel.h> +@@ -30,11 +30,16 @@ + #include <linux/mm.h> + #include <linux/platform_device.h> + #include <linux/ethtool.h> ++#include <linux/if_vlan.h> + #include <linux/init.h> + #include <linux/delay.h> + #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> + +@@ -42,7 +47,7 @@ + #include <xway_dma.h> + #include <lantiq_platform.h> + +-#define LTQ_ETOP_MDIO 0x11804 ++#define LTQ_ETOP_MDIO_ACC 0x11804 + #define MDIO_REQUEST 0x80000000 + #define MDIO_READ 0x40000000 + #define MDIO_ADDR_MASK 0x1f +@@ -51,44 +56,91 @@ + #define MDIO_REG_OFFSET 0x10 + #define MDIO_VAL_MASK 0xffff + +-#define PPE32_CGEN 0x800 +-#define LQ_PPE32_ENET_MAC_CFG 0x1840 ++#define LTQ_ETOP_MDIO_CFG 0x11800 ++#define MDIO_CFG_MASK 0x6 ++ ++#define LTQ_ETOP_CFG 0x11808 ++#define LTQ_ETOP_IGPLEN 0x11820 ++#define LTQ_ETOP_MAC_CFG 0x11840 + + #define LTQ_ETOP_ENETS0 0x11850 + #define LTQ_ETOP_MAC_DA0 0x1186C + #define LTQ_ETOP_MAC_DA1 0x11870 +-#define LTQ_ETOP_CFG 0x16020 +-#define LTQ_ETOP_IGPLEN 0x16080 ++ ++#define MAC_CFG_MASK 0xfff ++#define MAC_CFG_CGEN (1 << 11) ++#define MAC_CFG_DUPLEX (1 << 2) ++#define MAC_CFG_SPEED (1 << 1) ++#define MAC_CFG_LINK (1 << 0) + + #define MAX_DMA_CHAN 0x8 + #define MAX_DMA_CRC_LEN 0x4 + #define MAX_DMA_DATA_LEN 0x600 + + #define ETOP_FTCU BIT(28) +-#define ETOP_MII_MASK 0xf +-#define ETOP_MII_NORMAL 0xd +-#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 ETOP_CFG_MASK 0xfff ++#define ETOP_CFG_FEN0 (1 << 8) ++#define ETOP_CFG_SEN0 (1 << 6) ++#define ETOP_CFG_OFF1 (1 << 3) ++#define ETOP_CFG_REMII0 (1 << 1) ++#define ETOP_CFG_OFF0 (1 << 0) ++ ++#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 LTQ_GBIT_RGMII_CTL 0x78 ++ ++#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 ++ ++/* MDC clock divider, clock = 25MHz/((MDC_CLOCK + 1) * 2) */ ++#define MDC_CLOCK_MASK 0xff000000 ++#define MDC_CLOCK_OFFSET 24 ++ ++/* 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; +@@ -98,22 +150,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, +@@ -148,8 +213,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 +@@ -157,8 +225,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]; +@@ -172,7 +242,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; + } +@@ -184,12 +256,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, +@@ -202,7 +276,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; + } + +@@ -210,9 +286,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; + } + +@@ -224,7 +301,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]); +@@ -235,65 +312,133 @@ 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); ++ ++ /* enable gbit port0 on the SoC */ ++ ltq_gbit_w32_mask((1 << 17), (1 << 18), LTQ_GBIT_P0_CTL); ++ ++ 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); ++ /* set mdc clock to 2.5 MHz */ ++ ltq_gbit_w32_mask(MDC_CLOCK_MASK, 4 << MDC_CLOCK_OFFSET, ++ LTQ_GBIT_RGMII_CTL); + } + + static int + ltq_etop_hw_init(struct net_device *dev) + { + struct ltq_etop_priv *priv = netdev_priv(dev); +- int i; ++ int mii_mode = priv->mii_mode; ++ ++ clk_enable(priv->clk_ppe); + +- ltq_pmu_enable(PMU_PPE); ++ if (of_machine_is_compatible("lantiq,ar9")) { ++ ltq_etop_gbit_init(dev); ++ /* force the etops link to the gbit to MII */ ++ mii_mode = PHY_INTERFACE_MODE_MII; ++ } ++ ltq_etop_w32_mask(MDIO_CFG_MASK, 0, LTQ_ETOP_MDIO_CFG); ++ ltq_etop_w32_mask(MAC_CFG_MASK, MAC_CFG_CGEN | MAC_CFG_DUPLEX | ++ MAC_CFG_SPEED | MAC_CFG_LINK, LTQ_ETOP_MAC_CFG); + +- switch (priv->pldata->mii_mode) { ++ switch (mii_mode) { + case PHY_INTERFACE_MODE_RMII: +- ltq_etop_w32_mask(ETOP_MII_MASK, +- ETOP_MII_REVERSE, LTQ_ETOP_CFG); ++ ltq_etop_w32_mask(ETOP_CFG_MASK, ETOP_CFG_REMII0 | ETOP_CFG_OFF1 | ++ ETOP_CFG_SEN0 | ETOP_CFG_FEN0, LTQ_ETOP_CFG); + break; + + case PHY_INTERFACE_MODE_MII: +- ltq_etop_w32_mask(ETOP_MII_MASK, +- ETOP_MII_NORMAL, LTQ_ETOP_CFG); ++ ltq_etop_w32_mask(ETOP_CFG_MASK, ETOP_CFG_OFF1 | ++ ETOP_CFG_SEN0 | ETOP_CFG_FEN0, LTQ_ETOP_CFG); + 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); ++ 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, 0, "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, 0, "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, 0, "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, 0, "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 +@@ -309,7 +454,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 +@@ -317,7 +465,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 +@@ -325,7 +476,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 = { +@@ -336,6 +490,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 | +@@ -343,9 +530,9 @@ ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr, int phy_reg, u16 phy_data) + ((phy_reg & MDIO_REG_MASK) << MDIO_REG_OFFSET) | + phy_data; + +- while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST) ++ while (ltq_etop_r32(LTQ_ETOP_MDIO_ACC) & MDIO_REQUEST) + ; +- ltq_etop_w32(val, LTQ_ETOP_MDIO); ++ ltq_etop_w32(val, LTQ_ETOP_MDIO_ACC); + return 0; + } + +@@ -356,12 +543,12 @@ ltq_etop_mdio_rd(struct mii_bus *bus, int phy_addr, int phy_reg) + ((phy_addr & MDIO_ADDR_MASK) << MDIO_ADDR_OFFSET) | + ((phy_reg & MDIO_REG_MASK) << MDIO_REG_OFFSET); + +- while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST) ++ while (ltq_etop_r32(LTQ_ETOP_MDIO_ACC) & MDIO_REQUEST) + ; +- ltq_etop_w32(val, LTQ_ETOP_MDIO); +- while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST) ++ ltq_etop_w32(val, LTQ_ETOP_MDIO_ACC); ++ while (ltq_etop_r32(LTQ_ETOP_MDIO_ACC) & MDIO_REQUEST) + ; +- val = ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_VAL_MASK; ++ val = ltq_etop_r32(LTQ_ETOP_MDIO_ACC) & MDIO_VAL_MASK; + return val; + } + +@@ -376,14 +563,18 @@ 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; +- } +- } ++ u32 phy_supported = (SUPPORTED_10baseT_Half ++ | SUPPORTED_10baseT_Full ++ | SUPPORTED_100baseT_Half ++ | SUPPORTED_100baseT_Full ++ | SUPPORTED_Autoneg ++ | SUPPORTED_MII ++ | SUPPORTED_TP); ++ ++ 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"); +@@ -391,21 +582,18 @@ ltq_etop_mdio_probe(struct net_device *dev) + } + + phydev = phy_connect(dev, dev_name(&phydev->dev), +- <q_etop_mdio_link, priv->pldata->mii_mode); ++ <q_etop_mdio_link, priv->mii_mode); + + if (IS_ERR(phydev)) { + netdev_err(dev, "Could not attach to PHY\n"); + return PTR_ERR(phydev); + } + +- phydev->supported &= (SUPPORTED_10baseT_Half +- | SUPPORTED_10baseT_Full +- | SUPPORTED_100baseT_Half +- | SUPPORTED_100baseT_Full +- | SUPPORTED_Autoneg +- | SUPPORTED_MII +- | SUPPORTED_TP); ++ if (of_machine_is_compatible("lantiq,ar9")) ++ phy_supported |= SUPPORTED_1000baseT_Half ++ | SUPPORTED_1000baseT_Full; + ++ phydev->supported &= phy_supported; + phydev->advertising = phydev->supported; + priv->phydev = phydev; + pr_info("%s: attached PHY [%s] (phy_addr=%s, irq=%d)\n", +@@ -430,8 +618,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); +@@ -480,17 +673,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; + } +@@ -499,18 +694,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; + } + +@@ -520,16 +716,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; +@@ -537,7 +733,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; + +@@ -547,11 +743,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; +@@ -566,8 +762,10 @@ ltq_etop_change_mtu(struct net_device *dev, int new_mtu) + struct ltq_etop_priv *priv = netdev_priv(dev); + unsigned long flags; + ++ int max = ETH_HLEN + VLAN_HLEN + new_mtu + ETH_FCS_LEN; ++ + spin_lock_irqsave(&priv->lock, flags); +- ltq_etop_w32((ETOP_PLEN_UNDER << 16) | new_mtu, ++ ltq_etop_w32((ETOP_PLEN_UNDER << 16) | max, + LTQ_ETOP_IGPLEN); + spin_unlock_irqrestore(&priv->lock, flags); + } +@@ -631,34 +829,33 @@ 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)); ++ 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"); +- 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 = <q_etop_ethtool_ops; ++ else ++ pr_warn("etop: mdio probe failed\n");; + return 0; + + err_netdev: +@@ -678,6 +875,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; +@@ -701,14 +901,18 @@ static const struct net_device_ops ltq_eth_netdev_ops = { + .ndo_tx_timeout = ltq_etop_tx_timeout, + }; + +-static int __init +-ltq_etop_probe(struct platform_device *pdev) ++static int 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) { +@@ -734,30 +938,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 = <q_eth_netdev_ops; +- dev->ethtool_ops = <q_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); ++ of_get_mac_address_mtd(pdev->dev.of_node, priv->mac); ++ ++ 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) +@@ -786,32 +1018,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 = 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(<q_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(<q_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 + diff --git a/target/linux/lantiq/patches-3.14/0025-GPIO-MIPS-lantiq-add-gpio-driver-for-falcon-SoC.patch b/target/linux/lantiq/patches-3.14/0029-GPIO-MIPS-lantiq-add-gpio-driver-for-falcon-SoC.patch index 841401febb..a9be6fce0d 100644 --- a/target/linux/lantiq/patches-3.14/0025-GPIO-MIPS-lantiq-add-gpio-driver-for-falcon-SoC.patch +++ b/target/linux/lantiq/patches-3.14/0029-GPIO-MIPS-lantiq-add-gpio-driver-for-falcon-SoC.patch @@ -1,7 +1,7 @@ -From 8d45ea02fc0e9b5edd7deaf564663f1ffe8bed64 Mon Sep 17 00:00:00 2001 +From 7e178ce2e5f3aef38d4bdd2c0e02eae6100d5af4 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Thu, 7 Aug 2014 18:22:19 +0200 -Subject: [PATCH 25/31] GPIO: MIPS: lantiq: add gpio driver for falcon SoC +Subject: [PATCH 29/36] GPIO: MIPS: lantiq: 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. diff --git a/target/linux/lantiq/patches-3.14/0031-GPIO-add-named-gpio-exports.patch b/target/linux/lantiq/patches-3.14/0030-GPIO-add-named-gpio-exports.patch index 412a32a42a..0a1064208c 100644 --- a/target/linux/lantiq/patches-3.14/0031-GPIO-add-named-gpio-exports.patch +++ b/target/linux/lantiq/patches-3.14/0030-GPIO-add-named-gpio-exports.patch @@ -1,7 +1,7 @@ -From 6774a8fcd63da9511faa7501ee20c4dde289bb07 Mon Sep 17 00:00:00 2001 +From cc809a441d8f2924f785eb863dfa6aef47a25b0b Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Tue, 12 Aug 2014 20:49:27 +0200 -Subject: [PATCH 31/31] GPIO: add named gpio exports +Subject: [PATCH 30/36] GPIO: add named gpio exports Signed-off-by: John Crispin <blogic@openwrt.org> --- diff --git a/target/linux/lantiq/patches-3.14/0026-I2C-MIPS-lantiq-add-FALC-ON-i2c-bus-master.patch b/target/linux/lantiq/patches-3.14/0031-I2C-MIPS-lantiq-add-FALC-ON-i2c-bus-master.patch index 9a2e9616c9..713c2aa533 100644 --- a/target/linux/lantiq/patches-3.14/0026-I2C-MIPS-lantiq-add-FALC-ON-i2c-bus-master.patch +++ b/target/linux/lantiq/patches-3.14/0031-I2C-MIPS-lantiq-add-FALC-ON-i2c-bus-master.patch @@ -1,7 +1,7 @@ -From 5b376c19a3608cf37908c58b47483909b8ec173a Mon Sep 17 00:00:00 2001 +From f17e50f67fa3c77624edf2ca03fae0d50f0ce39b Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Thu, 7 Aug 2014 18:26:42 +0200 -Subject: [PATCH 26/31] I2C: MIPS: lantiq: add FALC-ON i2c bus master +Subject: [PATCH 31/36] I2C: MIPS: lantiq: add FALC-ON i2c bus master This patch adds the driver needed to make the I2C bus work on FALC-ON SoCs. diff --git a/target/linux/lantiq/patches-3.14/0027-USB-fix-roothub-for-IFXHCD.patch b/target/linux/lantiq/patches-3.14/0032-USB-fix-roothub-for-IFXHCD.patch index 68af3bf5ab..620942665d 100644 --- a/target/linux/lantiq/patches-3.14/0027-USB-fix-roothub-for-IFXHCD.patch +++ b/target/linux/lantiq/patches-3.14/0032-USB-fix-roothub-for-IFXHCD.patch @@ -1,7 +1,7 @@ -From 53c4acc1d3c7eae439b8bf3422de876e8a3e3bdb Mon Sep 17 00:00:00 2001 +From 326714a47233e4a524afa0c8398276fddf0dbd4d Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Thu, 6 Dec 2012 19:59:53 +0100 -Subject: [PATCH 27/31] USB: fix roothub for IFXHCD +Subject: [PATCH 32/36] USB: fix roothub for IFXHCD --- arch/mips/lantiq/Kconfig | 1 + diff --git a/target/linux/lantiq/patches-3.14/0028-SPI-MIPS-lantiq-adds-spi-xway.patch b/target/linux/lantiq/patches-3.14/0033-SPI-MIPS-lantiq-adds-spi-xway.patch index 3c3703e701..3a57416841 100644 --- a/target/linux/lantiq/patches-3.14/0028-SPI-MIPS-lantiq-adds-spi-xway.patch +++ b/target/linux/lantiq/patches-3.14/0033-SPI-MIPS-lantiq-adds-spi-xway.patch @@ -1,7 +1,7 @@ -From 855c99aff4c1fb440a679cc8481947daf95643b8 Mon Sep 17 00:00:00 2001 +From e75df4f96373e5d16f8ca13aa031e54cdcfeda62 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Wed, 13 Mar 2013 09:29:37 +0100 -Subject: [PATCH 28/31] SPI: MIPS: lantiq: adds spi-xway +Subject: [PATCH 33/36] SPI: MIPS: lantiq: adds spi-xway This patch adds support for the SPI core found on several Lantiq SoCs. The Driver has been runtime tested in combination with m25p80 Flash Devices diff --git a/target/linux/lantiq/patches-3.14/0029-reset-Fix-compile-when-reset-RESET_CONTROLLER-is-not.patch b/target/linux/lantiq/patches-3.14/0034-reset-Fix-compile-when-reset-RESET_CONTROLLER-is-not.patch index ca9dd5a369..9589baa169 100644 --- a/target/linux/lantiq/patches-3.14/0029-reset-Fix-compile-when-reset-RESET_CONTROLLER-is-not.patch +++ b/target/linux/lantiq/patches-3.14/0034-reset-Fix-compile-when-reset-RESET_CONTROLLER-is-not.patch @@ -1,7 +1,7 @@ -From 748c654a6ba890e9a1b5bd29d0f198ce6b2c091f Mon Sep 17 00:00:00 2001 +From b1b9fca8c317afc3f2b78bb54f877e8a830a819d Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Fri, 9 Aug 2013 18:47:27 +0200 -Subject: [PATCH 29/31] reset: Fix compile when reset RESET_CONTROLLER is not +Subject: [PATCH 34/36] reset: Fix compile when reset RESET_CONTROLLER is not selected Drivers need to protect their reset api calls with #ifdef to avoid compile diff --git a/target/linux/lantiq/patches-3.14/0010-owrt-lantiq-wifi-and-ethernet-eeprom-handling.patch b/target/linux/lantiq/patches-3.14/0035-owrt-lantiq-wifi-and-ethernet-eeprom-handling.patch index 849e6701bb..3b92b95b75 100644 --- a/target/linux/lantiq/patches-3.14/0010-owrt-lantiq-wifi-and-ethernet-eeprom-handling.patch +++ b/target/linux/lantiq/patches-3.14/0035-owrt-lantiq-wifi-and-ethernet-eeprom-handling.patch @@ -1,17 +1,18 @@ -From 9f921445b6dbf2beef397c6aa038db135e92eb80 Mon Sep 17 00:00:00 2001 +From f8c5db89e793a4bc6c1e87bd7b3a5cec16b75bc3 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> -Date: Wed, 13 Mar 2013 10:02:58 +0100 -Subject: [PATCH 10/31] owrt: lantiq: wifi and ethernet eeprom handling +Date: Wed, 10 Sep 2014 22:42:14 +0200 +Subject: [PATCH 35/36] owrt: lantiq: wifi and ethernet eeprom handling +Signed-off-by: John Crispin <blogic@openwrt.org> --- arch/mips/include/asm/mach-lantiq/pci-ath-fixup.h | 6 + .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 3 + arch/mips/lantiq/xway/Makefile | 3 + - arch/mips/lantiq/xway/ath_eep.c | 277 ++++++++++++++++++++ + arch/mips/lantiq/xway/ath_eep.c | 282 ++++++++++++++++++++ arch/mips/lantiq/xway/eth_mac.c | 76 ++++++ arch/mips/lantiq/xway/pci-ath-fixup.c | 109 ++++++++ arch/mips/lantiq/xway/rt_eep.c | 60 +++++ - 7 files changed, 534 insertions(+) + 7 files changed, 539 insertions(+) create mode 100644 arch/mips/include/asm/mach-lantiq/pci-ath-fixup.h create mode 100644 arch/mips/lantiq/xway/ath_eep.c create mode 100644 arch/mips/lantiq/xway/eth_mac.c @@ -57,10 +58,10 @@ index 2dd442c..de876e1 100644 obj-$(CONFIG_XRX200_PHY_FW) += xrx200_phy_fw.o diff --git a/arch/mips/lantiq/xway/ath_eep.c b/arch/mips/lantiq/xway/ath_eep.c new file mode 100644 -index 0000000..cd07f9a +index 0000000..aff42ac --- /dev/null +++ b/arch/mips/lantiq/xway/ath_eep.c -@@ -0,0 +1,277 @@ +@@ -0,0 +1,282 @@ +/* + * Copyright (C) 2011 Luca Olivetti <luca@ventoso.org> + * Copyright (C) 2011 John Crispin <blogic@openwrt.org> @@ -104,7 +105,7 @@ index 0000000..cd07f9a + struct device_node *np = pdev->dev.of_node, *mtd_np; + struct resource *eep_res, *mac_res = NULL; + void __iomem *eep, *mac; -+ int mac_offset; ++ int mac_offset, led_pin; + u32 mac_inc = 0, pci_slot = 0; + int i; + struct mtd_info *the_mtd; @@ -196,6 +197,11 @@ index 0000000..cd07f9a + + } + ++ if (!of_property_read_u32(np, "ath,led-pin", &led_pin)) { ++ ath9k_pdata.led_pin = led_pin; ++ dev_info(&pdev->dev, "using led pin %d.\n", led_pin); ++ } ++ + dev_info(&pdev->dev, "loaded ath9k eeprom\n"); + + return 0; diff --git a/target/linux/lantiq/patches-3.14/0011-owrt-generic-dtb-image-hack.patch b/target/linux/lantiq/patches-3.14/0036-owrt-generic-dtb-image-hack.patch index e07d7ceec2..fba8bb3ad5 100644 --- a/target/linux/lantiq/patches-3.14/0011-owrt-generic-dtb-image-hack.patch +++ b/target/linux/lantiq/patches-3.14/0036-owrt-generic-dtb-image-hack.patch @@ -1,7 +1,7 @@ -From 572e107a37deb7bc8512ca9144f4e8f24b36e451 Mon Sep 17 00:00:00 2001 +From dba8578e06aedf1e67312ebfc6162e2fadc9448d Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Thu, 7 Aug 2014 18:32:12 +0200 -Subject: [PATCH 11/31] owrt: generic dtb image hack +Subject: [PATCH 36/36] owrt: generic dtb image hack Signed-off-by: John Crispin <blogic@openwrt.org> --- diff --git a/target/linux/lantiq/patches-3.14/0037-MIPS-lantiq-move-eiu-init-after-irq_domain-register.patch b/target/linux/lantiq/patches-3.14/0037-MIPS-lantiq-move-eiu-init-after-irq_domain-register.patch new file mode 100644 index 0000000000..856733ad3b --- /dev/null +++ b/target/linux/lantiq/patches-3.14/0037-MIPS-lantiq-move-eiu-init-after-irq_domain-register.patch @@ -0,0 +1,79 @@ +From baea71233ed1796651cab6ead484a18666a765aa Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Thu, 11 Sep 2014 19:25:25 +0200 +Subject: [PATCH] MIPS: lantiq: move eiu init after irq_domain register + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/lantiq/irq.c | 48 ++++++++++++++++++++++++------------------------ + 1 file changed, 24 insertions(+), 24 deletions(-) + +diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c +index 6b94cc7..3bbedf6 100644 +--- a/arch/mips/lantiq/irq.c ++++ b/arch/mips/lantiq/irq.c +@@ -380,30 +380,6 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent) + panic("Failed to remap icu memory"); + } + +- /* the external interrupts are optional and xway only */ +- 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 */ +- exin_avail = of_irq_count(eiu_node); +- +- 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"); +- +- if (request_mem_region(res.start, resource_size(&res), +- res.name) < 0) +- pr_err("Failed to request eiu memory"); +- +- ltq_eiu_membase = ioremap_nocache(res.start, +- resource_size(&res)); +- if (!ltq_eiu_membase) +- panic("Failed to remap eiu memory"); +- } +- + /* turn off all irqs by default */ + for (i = 0; i < MAX_IM; i++) { + /* make sure all irqs are turned off by default */ +@@ -460,6 +436,30 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent) + if (MIPS_CPU_TIMER_IRQ != 7) + irq_create_mapping(ltq_domain, MIPS_CPU_TIMER_IRQ); + ++ /* the external interrupts are optional and xway only */ ++ 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 */ ++ exin_avail = of_irq_count(eiu_node); ++ ++ 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"); ++ ++ if (request_mem_region(res.start, resource_size(&res), ++ res.name) < 0) ++ pr_err("Failed to request eiu memory"); ++ ++ ltq_eiu_membase = ioremap_nocache(res.start, ++ resource_size(&res)); ++ if (!ltq_eiu_membase) ++ panic("Failed to remap eiu memory"); ++ } ++ + return 0; + } + +-- +1.7.10.4 + diff --git a/target/linux/lantiq/patches-3.14/0101-mtd-split.patch b/target/linux/lantiq/patches-3.14/0101-mtd-split.patch new file mode 100644 index 0000000000..e766207803 --- /dev/null +++ b/target/linux/lantiq/patches-3.14/0101-mtd-split.patch @@ -0,0 +1,200 @@ +Index: linux-3.14.18/arch/mips/lantiq/xway/Makefile +=================================================================== +--- linux-3.14.18.orig/arch/mips/lantiq/xway/Makefile 2014-09-11 16:31:10.000000000 +0200 ++++ linux-3.14.18/arch/mips/lantiq/xway/Makefile 2014-09-11 16:32:52.188968735 +0200 +@@ -1,6 +1,6 @@ + obj-y := prom.o sysctrl.o clk.o reset.o dma.o timer.o dcdc.o + +-obj-y += vmmc.o tffs.o ++obj-y += vmmc.o tffs.o mtd_split.o + + obj-y += eth_mac.o + obj-$(CONFIG_PCI) += ath_eep.o rt_eep.o pci-ath-fixup.o +Index: linux-3.14.18/arch/mips/lantiq/xway/mtd_split.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-3.14.18/arch/mips/lantiq/xway/mtd_split.c 2014-09-11 16:31:51.712967248 +0200 +@@ -0,0 +1,129 @@ ++#include <linux/magic.h> ++#include <linux/root_dev.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++ ++#define ROOTFS_SPLIT_NAME "rootfs_data" ++ ++struct squashfs_super_block { ++ __le32 s_magic; ++ __le32 pad0[9]; ++ __le64 bytes_used; ++}; ++ ++static void split_brnimage_kernel(struct mtd_info *master, const char *name, ++ int offset, int size) ++{ ++ unsigned long buf[4]; ++ // Assume at most 2MB of kernel image ++ unsigned long end = offset + (2 << 20); ++ unsigned long part_size = offset + 0x400 - 12; ++ size_t len; ++ int ret; ++ ++ if (strcmp(name, "firmware") != 0) ++ return; ++ while (part_size < end) { ++ long size_min = part_size - 0x400 - 12 - offset; ++ long size_max = part_size + 12 - offset; ++ ret = mtd_read(master, part_size, 16, &len, (void *)buf); ++ if (ret || len != 16) ++ return; ++ ++ if (le32_to_cpu(buf[0]) < size_min || ++ le32_to_cpu(buf[0]) > size_max) { ++ part_size += 0x400; ++ continue; ++ } ++ ++ if (le32_to_cpu(buf[3]) == SQUASHFS_MAGIC) { ++ part_size += 12 - offset; ++ __mtd_add_partition(master, "rootfs", offset + part_size, ++ size - part_size, false); ++ return; ++ } ++ part_size += 0x400; ++ } ++} ++ ++static void split_eva_kernel(struct mtd_info *master, const char *name, ++ int offset, int size) ++{ ++#define EVA_MAGIC 0xfeed1281 ++ unsigned long magic = 0; ++ unsigned long part_size = 0, p; ++ size_t len; ++ int ret; ++ ++ if (strcmp(name, CONFIG_MTD_SPLIT_FIRMWARE_NAME) != 0) ++ return; ++ ++ ret = mtd_read(master, offset, 4, &len, (void *)&magic); ++ if (ret || len != sizeof(magic)) ++ return; ++ ++ if (le32_to_cpu(magic) != EVA_MAGIC) ++ return; ++ ++ ret = mtd_read(master, offset + 4, 4, &len, (void *)&part_size); ++ if (ret || len != sizeof(part_size)) ++ return; ++ ++ p = part_size = le32_to_cpu(part_size) + 0x18; ++ p &= ~0xffff; ++ p += 0x10000; ++ ++ ret = mtd_read(master, offset + p, 4, &len, (void *)&magic); ++ if (ret || len != sizeof(magic)) ++ return; ++ ++ if (magic == SQUASHFS_MAGIC) ++ part_size = p + 0x100; ++ else ++ part_size = mtd_pad_erasesize(master, offset, len); ++ ++ if (part_size + master->erasesize > size) ++ return; ++ ++ __mtd_add_partition(master, "rootfs", offset + part_size, ++ size - part_size, false); ++} ++ ++static void split_tplink_kernel(struct mtd_info *master, const char *name, ++ int offset, int size) ++{ ++#define TPLINK_MAGIC 0x00000002 ++ unsigned long magic = 0; ++ unsigned long part_size = 0; ++ size_t len; ++ int ret; ++ ++ if (strcmp(name, CONFIG_MTD_SPLIT_FIRMWARE_NAME) != 0) ++ return; ++ ++ ret = mtd_read(master, offset, 4, &len, (void *)&magic); ++ if (ret || len != sizeof(magic)) ++ return; ++ ++ if (le32_to_cpu(magic) != TPLINK_MAGIC) ++ return; ++ ++ ret = mtd_read(master, offset + 0x78, 4, &len, (void *)&part_size); ++ if (ret || len != sizeof(part_size)) ++ return; ++ ++ part_size = be32_to_cpu(part_size) + 0x200; ++ if (part_size + master->erasesize > size) ++ return; ++ ++ __mtd_add_partition(master, "rootfs", offset + part_size, ++ size - part_size, false); ++} ++ ++void arch_split_mtd_part(struct mtd_info *master, const char *name, ++ int offset, int size) ++{ ++ split_tplink_kernel(master, name, offset, size); ++ split_eva_kernel(master, name, offset, size); ++ split_brnimage_kernel(master, name, offset, size); ++} +Index: linux-3.14.18/include/linux/mtd/partitions.h +=================================================================== +--- linux-3.14.18.orig/include/linux/mtd/partitions.h 2014-09-11 16:31:10.752966240 +0200 ++++ linux-3.14.18/include/linux/mtd/partitions.h 2014-09-11 16:44:49.432986380 +0200 +@@ -89,12 +89,17 @@ + int mtd_is_partition(const struct mtd_info *mtd); + int mtd_add_partition(struct mtd_info *master, const char *name, + long long offset, long long length); ++int __mtd_add_partition(struct mtd_info *master, const char *name, ++ long long offset, long long length, bool dup_check); ++ + int mtd_del_partition(struct mtd_info *master, int partno); + struct mtd_info *mtdpart_get_master(const struct mtd_info *mtd); + uint64_t mtdpart_get_offset(const struct mtd_info *mtd); + uint64_t mtd_get_device_size(const struct mtd_info *mtd); +-extern void __weak arch_split_mtd_part(struct mtd_info *master, +- const char *name, int offset, int size); ++void __weak arch_split_mtd_part(struct mtd_info *master, ++ const char *name, int offset, int size); ++unsigned long ++mtd_pad_erasesize(struct mtd_info *mtd, int offset, int len); + + int parse_mtd_partitions_by_type(struct mtd_info *master, + enum mtd_parser_type type, +Index: linux-3.14.18/drivers/mtd/mtdpart.c +=================================================================== +--- linux-3.14.18.orig/drivers/mtd/mtdpart.c 2014-09-11 16:31:10.752966240 +0200 ++++ linux-3.14.18/drivers/mtd/mtdpart.c 2014-09-11 16:33:11.732969216 +0200 +@@ -617,7 +617,7 @@ + } + + +-static int ++int + __mtd_add_partition(struct mtd_info *master, const char *name, + long long offset, long long length, bool dup_check) + { +@@ -738,7 +738,7 @@ + return nr_parts; + } + +-static inline unsigned long ++unsigned long + mtd_pad_erasesize(struct mtd_info *mtd, int offset, int len) + { + unsigned long mask = mtd->erasesize - 1; +@@ -807,7 +807,6 @@ + return; + + len = be32_to_cpu(hdr.size) + 0x40; +- len = mtd_pad_erasesize(master, part->offset, len); + if (len + master->erasesize > part->mtd.size) + return; + |