From bf183aeff85bb573238fd16ac980d9c40f7c2fc5 Mon Sep 17 00:00:00 2001 From: hauke Date: Thu, 4 Aug 2011 20:04:54 +0000 Subject: brcm47xx: update patches * this adds sflash support for ssb devices * the flash is now a platform device * minor updates git-svn-id: svn://svn.openwrt.org/openwrt/trunk@27902 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/broadcom-diag/src/diag.c | 2 +- package/broadcom-wl/src/glue/wl_glue.c | 2 +- ...-move-parsing-of-EEPROM-into-own-function.patch | 4 +- ...nitializing-of-struct-bcma_bus-to-own-fun.patch | 4 +- ...dd-functions-to-scan-cores-needed-on-SoCs.patch | 4 +- .../patches-3.0/0004-bcma-add-SOC-bus.patch | 47 +- .../patches-3.0/0005-bcma-add-mips-driver.patch | 8 +- .../0006-bcma-add-serial-console-support.patch | 4 +- .../patches-3.0/0007-bcma-get-CPU-clock.patch | 4 +- ...cm47xx-prepare-to-support-different-buses.patch | 46 +- ...e-it-possible-to-build-bcm47xx-without-ss.patch | 40 +- .../0010-bcm47xx-add-support-for-bcma-bus.patch | 14 +- ...1-bcm47xx-fix-irq-assignment-for-new-SoCs.patch | 6 +- ...012-bcma-move-parallel-flash-into-a-union.patch | 58 +- ...013-bcma-add-serial-flash-support-to-bcma.patch | 120 ++-- .../0014-mtd-bcm47xx-add-bcm47xx-part-parser.patch | 579 ----------------- .../0014-ssb-move-flash-to-chipcommon.patch | 143 +++++ ...015-mtd-bcm47xx-add-parallel-flash-driver.patch | 238 ------- .../0015-ssb-add-serial-flash-support.patch | 697 +++++++++++++++++++++ ...-brcm47xx-add-common-interface-for-sflash.patch | 193 ++++++ .../0016-mtd-bcm47xx-add-serial-flash-driver.patch | 312 --------- .../0017-bcm47xx-register-flash-drivers.patch | 74 --- .../0017-mtd-bcm47xx-add-bcm47xx-part-parser.patch | 579 +++++++++++++++++ ...018-mtd-bcm47xx-add-parallel-flash-driver.patch | 240 +++++++ ...bcma-to-not-route-irqs-on-non-pci-devices.patch | 29 - .../0019-mtd-bcm47xx-add-serial-flash-driver.patch | 330 ++++++++++ .../0020-bcm47xx-register-flash-drivers.patch | 100 +++ ...small-fixes-needed-to-get-b43-up-with-SoC.patch | 37 -- .../0021-add-workarround-for-wndr3400.patch | 51 ++ ...ndoom-mac-address-as-long-as-reading-it-o.patch | 33 - ...ndoom-mac-address-as-long-as-reading-it-o.patch | 33 + .../0025-bcm47xx-read-nvram-from-sflash.patch | 118 ++++ .../0026-bcma-export-needed-gpio-functions.patch | 47 ++ ...S-BCM47xx-Setup-and-register-serial-early.patch | 4 +- .../linux/brcm47xx/patches-3.0/220-bcm5354.patch | 2 +- .../280-activate_ssb_support_in_usb.patch | 2 +- .../brcm47xx/patches-3.0/400-arch-bcm47xx.patch | 6 +- .../patches-3.0/812-disable_wgt634u_crap.patch | 12 +- .../patches-3.0/820-wgt634u-nvram-fix.patch | 16 +- .../patches-3.0/900-bcm47xx_wdt-noprescale.patch | 4 +- .../980-wnr834b_no_cardbus_invariant.patch | 2 +- .../brcm47xx/patches-3.0/999-wl_exports.patch | 4 +- 42 files changed, 2746 insertions(+), 1502 deletions(-) delete mode 100644 target/linux/brcm47xx/patches-3.0/0014-mtd-bcm47xx-add-bcm47xx-part-parser.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0014-ssb-move-flash-to-chipcommon.patch delete mode 100644 target/linux/brcm47xx/patches-3.0/0015-mtd-bcm47xx-add-parallel-flash-driver.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0015-ssb-add-serial-flash-support.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0016-brcm47xx-add-common-interface-for-sflash.patch delete mode 100644 target/linux/brcm47xx/patches-3.0/0016-mtd-bcm47xx-add-serial-flash-driver.patch delete mode 100644 target/linux/brcm47xx/patches-3.0/0017-bcm47xx-register-flash-drivers.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0017-mtd-bcm47xx-add-bcm47xx-part-parser.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0018-mtd-bcm47xx-add-parallel-flash-driver.patch delete mode 100644 target/linux/brcm47xx/patches-3.0/0019-bcma-to-not-route-irqs-on-non-pci-devices.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0019-mtd-bcm47xx-add-serial-flash-driver.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0020-bcm47xx-register-flash-drivers.patch delete mode 100644 target/linux/brcm47xx/patches-3.0/0020-bcma-small-fixes-needed-to-get-b43-up-with-SoC.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0021-add-workarround-for-wndr3400.patch delete mode 100644 target/linux/brcm47xx/patches-3.0/0022-bcma-use-randoom-mac-address-as-long-as-reading-it-o.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0023-bcma-use-randoom-mac-address-as-long-as-reading-it-o.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0025-bcm47xx-read-nvram-from-sflash.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0026-bcma-export-needed-gpio-functions.patch diff --git a/package/broadcom-diag/src/diag.c b/package/broadcom-diag/src/diag.c index 8e7ffa6cc7..5ff1c278b8 100644 --- a/package/broadcom-diag/src/diag.c +++ b/package/broadcom-diag/src/diag.c @@ -1465,7 +1465,7 @@ static int __init diag_init(void) static struct platform_t *detected; #ifdef CONFIG_BCM47XX_SSB - if (bcm47xx_active_bus_type != BCM47XX_BUS_TYPE_SSB) { + if (bcm47xx_bus_type != BCM47XX_BUS_TYPE_SSB) { printk(MODULE_NAME ": bcma bus is not supported.\n"); return -ENODEV; } diff --git a/package/broadcom-wl/src/glue/wl_glue.c b/package/broadcom-wl/src/glue/wl_glue.c index 18e2b3a583..638a65321a 100644 --- a/package/broadcom-wl/src/glue/wl_glue.c +++ b/package/broadcom-wl/src/glue/wl_glue.c @@ -274,7 +274,7 @@ static int __init wl_glue_init(void) * determine the used one from the info set by the * platform setup code. */ - switch (bcm47xx_active_bus_type) + switch (bcm47xx_bus_type) { #ifdef CONFIG_SSB case BCM47XX_BUS_TYPE_SSB: diff --git a/target/linux/brcm47xx/patches-3.0/0001-bcma-move-parsing-of-EEPROM-into-own-function.patch b/target/linux/brcm47xx/patches-3.0/0001-bcma-move-parsing-of-EEPROM-into-own-function.patch index 63ba4e9d03..740e96e81f 100644 --- a/target/linux/brcm47xx/patches-3.0/0001-bcma-move-parsing-of-EEPROM-into-own-function.patch +++ b/target/linux/brcm47xx/patches-3.0/0001-bcma-move-parsing-of-EEPROM-into-own-function.patch @@ -1,7 +1,7 @@ -From e6defe46ea936ebb309c9cab4f7fd14bdc0c5416 Mon Sep 17 00:00:00 2001 +From a1bf12e78294c6cd3d8747e1e07c48977ca1e3e3 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 11 Jun 2011 16:47:38 +0200 -Subject: [PATCH 01/22] bcma: move parsing of EEPROM into own function. +Subject: [PATCH 01/26] bcma: move parsing of EEPROM into own function. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit diff --git a/target/linux/brcm47xx/patches-3.0/0002-bcma-move-initializing-of-struct-bcma_bus-to-own-fun.patch b/target/linux/brcm47xx/patches-3.0/0002-bcma-move-initializing-of-struct-bcma_bus-to-own-fun.patch index 19c64aba2d..48191abc3e 100644 --- a/target/linux/brcm47xx/patches-3.0/0002-bcma-move-initializing-of-struct-bcma_bus-to-own-fun.patch +++ b/target/linux/brcm47xx/patches-3.0/0002-bcma-move-initializing-of-struct-bcma_bus-to-own-fun.patch @@ -1,7 +1,7 @@ -From 47b0447e18f72724caf57ba7e4573e309fb2bfae Mon Sep 17 00:00:00 2001 +From 30ef571a04dc19171c6b6664d88b60c39161eb42 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 18 Jun 2011 11:55:47 +0200 -Subject: [PATCH 02/22] bcma: move initializing of struct bcma_bus to own function. +Subject: [PATCH 02/26] bcma: move initializing of struct bcma_bus to own function. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit diff --git a/target/linux/brcm47xx/patches-3.0/0003-bcma-add-functions-to-scan-cores-needed-on-SoCs.patch b/target/linux/brcm47xx/patches-3.0/0003-bcma-add-functions-to-scan-cores-needed-on-SoCs.patch index 3b00f06cb6..92cd65d396 100644 --- a/target/linux/brcm47xx/patches-3.0/0003-bcma-add-functions-to-scan-cores-needed-on-SoCs.patch +++ b/target/linux/brcm47xx/patches-3.0/0003-bcma-add-functions-to-scan-cores-needed-on-SoCs.patch @@ -1,7 +1,7 @@ -From beb36a1a49227ca6c5778a667aefc8cd3fd56a4f Mon Sep 17 00:00:00 2001 +From f3c07dd351161cb33f1c8e1ff55a65ae0cc6b661 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 18 Jun 2011 14:30:55 +0200 -Subject: [PATCH 03/22] bcma: add functions to scan cores needed on SoCs +Subject: [PATCH 03/26] bcma: add functions to scan cores needed on SoCs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit diff --git a/target/linux/brcm47xx/patches-3.0/0004-bcma-add-SOC-bus.patch b/target/linux/brcm47xx/patches-3.0/0004-bcma-add-SOC-bus.patch index 035da9d76a..6ad9dce4b8 100644 --- a/target/linux/brcm47xx/patches-3.0/0004-bcma-add-SOC-bus.patch +++ b/target/linux/brcm47xx/patches-3.0/0004-bcma-add-SOC-bus.patch @@ -1,7 +1,7 @@ -From 22573303ad477fa07c948a9944e9c18fea9af724 Mon Sep 17 00:00:00 2001 +From d743a740b76a6be9e88fe1ae6991682927a7769c Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 18 Jun 2011 14:31:53 +0200 -Subject: [PATCH 04/22] bcma: add SOC bus +Subject: [PATCH 04/26] bcma: add SOC bus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -18,12 +18,14 @@ Signed-off-by: Hauke Mehrtens --- drivers/bcma/Kconfig | 4 + drivers/bcma/Makefile | 1 + + drivers/bcma/core.c | 2 + + drivers/bcma/driver_pci.c | 9 ++- drivers/bcma/host_soc.c | 183 +++++++++++++++++++++++++++++++++++++++++ - drivers/bcma/main.c | 6 +- + drivers/bcma/main.c | 9 ++- drivers/bcma/scan.c | 42 ++++++++- include/linux/bcma/bcma.h | 5 +- include/linux/bcma/bcma_soc.h | 16 ++++ - 7 files changed, 250 insertions(+), 7 deletions(-) + 9 files changed, 263 insertions(+), 8 deletions(-) create mode 100644 drivers/bcma/host_soc.c create mode 100644 include/linux/bcma/bcma_soc.h @@ -50,6 +52,35 @@ Signed-off-by: Hauke Mehrtens obj-$(CONFIG_BCMA) += bcma.o ccflags-$(CONFIG_BCMA_DEBUG) := -DDEBUG +--- a/drivers/bcma/core.c ++++ b/drivers/bcma/core.c +@@ -110,6 +110,8 @@ EXPORT_SYMBOL_GPL(bcma_core_pll_ctl); + u32 bcma_core_dma_translation(struct bcma_device *core) + { + switch (core->bus->hosttype) { ++ case BCMA_HOSTTYPE_SOC: ++ return 0; + case BCMA_HOSTTYPE_PCI: + if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64) + return BCMA_DMA_TRANSLATION_DMA64_CMT; +--- a/drivers/bcma/driver_pci.c ++++ b/drivers/bcma/driver_pci.c +@@ -208,7 +208,14 @@ int bcma_core_pci_irq_ctl(struct bcma_dr + { + struct pci_dev *pdev = pc->core->bus->host_pci; + u32 coremask, tmp; +- int err; ++ int err = 0; ++ ++ if (core->bus->hosttype != BCMA_HOSTTYPE_PCI) { ++ /* This bcma device is not on a PCI host-bus. So the IRQs are ++ * not routed through the PCI core. ++ * So we must not enable routing through the PCI core. */ ++ goto out; ++ } + + err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp); + if (err) --- /dev/null +++ b/drivers/bcma/host_soc.c @@ -0,0 +1,183 @@ @@ -249,16 +280,18 @@ Signed-off-by: Hauke Mehrtens kfree(core); } -@@ -93,8 +97,8 @@ static int bcma_register_cores(struct bc +@@ -93,7 +97,10 @@ static int bcma_register_cores(struct bc core->dma_dev = &bus->host_pci->dev; core->irq = bus->host_pci->irq; break; - case BCMA_HOSTTYPE_NONE: - case BCMA_HOSTTYPE_SDIO: + case BCMA_HOSTTYPE_SOC: ++ core->dev.dma_mask = &core->dev.coherent_dma_mask; ++ core->dma_dev = &core->dev; ++ break; + case BCMA_HOSTTYPE_SDIO: break; } - --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c @@ -337,6 +337,16 @@ static int bcma_get_next_core(struct bcm diff --git a/target/linux/brcm47xx/patches-3.0/0005-bcma-add-mips-driver.patch b/target/linux/brcm47xx/patches-3.0/0005-bcma-add-mips-driver.patch index ddd13aef57..31181a4883 100644 --- a/target/linux/brcm47xx/patches-3.0/0005-bcma-add-mips-driver.patch +++ b/target/linux/brcm47xx/patches-3.0/0005-bcma-add-mips-driver.patch @@ -1,7 +1,7 @@ -From 5961a1401605cd1941d5260a03b1dc2e8ae80619 Mon Sep 17 00:00:00 2001 +From 3be3bbe24a1d49283864a1e1ea1d88a2e1700b50 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Mon, 6 Jun 2011 00:07:32 +0200 -Subject: [PATCH 05/22] bcma: add mips driver +Subject: [PATCH 05/26] bcma: add mips driver This adds a mips driver to bcma. This is only found on embedded devices. For now the driver just initializes the irqs used on this @@ -305,7 +305,7 @@ Signed-off-by: Hauke Mehrtens continue; } -@@ -144,6 +145,13 @@ int bcma_bus_register(struct bcma_bus *b +@@ -147,6 +148,13 @@ int bcma_bus_register(struct bcma_bus *b bcma_core_chipcommon_init(&bus->drv_cc); } @@ -319,7 +319,7 @@ Signed-off-by: Hauke Mehrtens /* Init PCIE core */ core = bcma_find_core(bus, BCMA_CORE_PCIE); if (core) { -@@ -214,6 +222,13 @@ int __init bcma_bus_early_register(struc +@@ -217,6 +225,13 @@ int __init bcma_bus_early_register(struc bcma_core_chipcommon_init(&bus->drv_cc); } diff --git a/target/linux/brcm47xx/patches-3.0/0006-bcma-add-serial-console-support.patch b/target/linux/brcm47xx/patches-3.0/0006-bcma-add-serial-console-support.patch index 6105f50748..fd7b8ae78e 100644 --- a/target/linux/brcm47xx/patches-3.0/0006-bcma-add-serial-console-support.patch +++ b/target/linux/brcm47xx/patches-3.0/0006-bcma-add-serial-console-support.patch @@ -1,7 +1,7 @@ -From 5088e81ecc5c953df7de84eeedd0817326bc4be4 Mon Sep 17 00:00:00 2001 +From 4d58b9a14669e5ea0026f0d27257041aecfcbed3 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Mon, 6 Jun 2011 00:07:33 +0200 -Subject: [PATCH 06/22] bcma: add serial console support +Subject: [PATCH 06/26] bcma: add serial console support This adds support for serial console to bcma, when operating on an SoC. diff --git a/target/linux/brcm47xx/patches-3.0/0007-bcma-get-CPU-clock.patch b/target/linux/brcm47xx/patches-3.0/0007-bcma-get-CPU-clock.patch index aa65dc8adf..7fa752056b 100644 --- a/target/linux/brcm47xx/patches-3.0/0007-bcma-get-CPU-clock.patch +++ b/target/linux/brcm47xx/patches-3.0/0007-bcma-get-CPU-clock.patch @@ -1,7 +1,7 @@ -From e993e8342e660f29a048be872522eedabaa177e1 Mon Sep 17 00:00:00 2001 +From bd2bb5fbf1982b18f44b6fd78e45717e0757cdc0 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 16 Jul 2011 15:19:38 +0200 -Subject: [PATCH 07/22] bcma: get CPU clock +Subject: [PATCH 07/26] bcma: get CPU clock Add method to return the clock of the CPU. This is needed by the arch code to calculate the mips_hpt_frequency. diff --git a/target/linux/brcm47xx/patches-3.0/0008-bcm47xx-prepare-to-support-different-buses.patch b/target/linux/brcm47xx/patches-3.0/0008-bcm47xx-prepare-to-support-different-buses.patch index a9ccdaeb02..5dd648da3c 100644 --- a/target/linux/brcm47xx/patches-3.0/0008-bcm47xx-prepare-to-support-different-buses.patch +++ b/target/linux/brcm47xx/patches-3.0/0008-bcm47xx-prepare-to-support-different-buses.patch @@ -1,7 +1,7 @@ -From 1db44bc4e7d5abb2966154ac57d1f035dc3e4ec1 Mon Sep 17 00:00:00 2001 +From 18fe82b600f9563e59e28746211a2ce3176a81de Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Mon, 6 Jun 2011 00:07:36 +0200 -Subject: [PATCH 08/22] bcm47xx: prepare to support different buses +Subject: [PATCH 08/26] bcm47xx: prepare to support different buses Prepare bcm47xx to support different System buses. Before adding support for bcma it should be possible to build bcm47xx without the @@ -40,7 +40,7 @@ Signed-off-by: Hauke Mehrtens - return -EBUSY; - - return 0; -+ switch (bcm47xx_active_bus_type) { ++ switch (bcm47xx_bus_type) { + case BCM47XX_BUS_TYPE_SSB: + if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) && + ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES)) @@ -64,7 +64,7 @@ Signed-off-by: Hauke Mehrtens - if (ssb_chipco_available(&ssb_bcm47xx.chipco) && - ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES)) - return; -+ switch (bcm47xx_active_bus_type) { ++ switch (bcm47xx_bus_type) { + case BCM47XX_BUS_TYPE_SSB: + if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) && + ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES)) @@ -92,7 +92,7 @@ Signed-off-by: Hauke Mehrtens - return ssb_mips_irq(ssb_bcm47xx.extif.dev) + 2; - else - return -EINVAL; -+ switch (bcm47xx_active_bus_type) { ++ switch (bcm47xx_bus_type) { + case BCM47XX_BUS_TYPE_SSB: + if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco)) + return ssb_mips_irq(bcm47xx_bus.ssb.chipco.dev) + 2; @@ -122,7 +122,7 @@ Signed-off-by: Hauke Mehrtens - base = mcore->flash_window; - lim = mcore->flash_window_size; -+ switch (bcm47xx_active_bus_type) { ++ switch (bcm47xx_bus_type) { + case BCM47XX_BUS_TYPE_SSB: + mcore_ssb = &bcm47xx_bus.ssb.mipscore; + base = mcore_ssb->flash_window; @@ -153,7 +153,7 @@ Signed-off-by: Hauke Mehrtens +static int __init uart8250_init(void) +{ -+ switch (bcm47xx_active_bus_type) { ++ switch (bcm47xx_bus_type) { + case BCM47XX_BUS_TYPE_SSB: + return uart8250_init_ssb(); + } @@ -174,8 +174,8 @@ Signed-off-by: Hauke Mehrtens +union bcm47xx_bus bcm47xx_bus; +EXPORT_SYMBOL(bcm47xx_bus); + -+enum bcm47xx_bus_type bcm47xx_active_bus_type; -+EXPORT_SYMBOL(bcm47xx_active_bus_type); ++enum bcm47xx_bus_type bcm47xx_bus_type; ++EXPORT_SYMBOL(bcm47xx_bus_type); static void bcm47xx_machine_restart(char *command) { @@ -183,7 +183,7 @@ Signed-off-by: Hauke Mehrtens local_irq_disable(); /* Set the watchdog timer to reset immediately */ - ssb_watchdog_timer_set(&ssb_bcm47xx, 1); -+ switch (bcm47xx_active_bus_type) { ++ switch (bcm47xx_bus_type) { + case BCM47XX_BUS_TYPE_SSB: + ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1); + break; @@ -196,7 +196,7 @@ Signed-off-by: Hauke Mehrtens /* Disable interrupts and watchdog and spin forever */ local_irq_disable(); - ssb_watchdog_timer_set(&ssb_bcm47xx, 0); -+ switch (bcm47xx_active_bus_type) { ++ switch (bcm47xx_bus_type) { + case BCM47XX_BUS_TYPE_SSB: + ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0); + break; @@ -238,7 +238,7 @@ Signed-off-by: Hauke Mehrtens +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + -+ bcm47xx_active_bus_type = BCM47XX_BUS_TYPE_SSB; ++ bcm47xx_bus_type = BCM47XX_BUS_TYPE_SSB; + bcm47xx_register_ssb(); _machine_restart = bcm47xx_machine_restart; @@ -259,7 +259,7 @@ Signed-off-by: Hauke Mehrtens write_c0_compare(0xffff); - hz = ssb_cpu_clock(&ssb_bcm47xx.mipscore) / 2; -+ switch (bcm47xx_active_bus_type) { ++ switch (bcm47xx_bus_type) { + case BCM47XX_BUS_TYPE_SSB: + hz = ssb_cpu_clock(&bcm47xx_bus.ssb.mipscore) / 2; + break; @@ -286,7 +286,7 @@ Signed-off-by: Hauke Mehrtens + u8 *et0mac; - u8 *et0mac = ssb_bcm47xx.sprom.et0mac; -+ if (bcm47xx_active_bus_type != BCM47XX_BUS_TYPE_SSB) ++ if (bcm47xx_bus_type != BCM47XX_BUS_TYPE_SSB) + return -ENODEV; + + et0mac = bcm47xx_bus.ssb.sprom.et0mac; @@ -329,7 +329,7 @@ Signed-off-by: Hauke Mehrtens +}; + +extern union bcm47xx_bus bcm47xx_bus; -+extern enum bcm47xx_bus_type bcm47xx_active_bus_type; ++extern enum bcm47xx_bus_type bcm47xx_bus_type; #endif /* __ASM_BCM47XX_H */ --- a/arch/mips/include/asm/mach-bcm47xx/gpio.h @@ -339,7 +339,7 @@ Signed-off-by: Hauke Mehrtens static inline int gpio_get_value(unsigned gpio) { - return ssb_gpio_in(&ssb_bcm47xx, 1 << gpio); -+ switch (bcm47xx_active_bus_type) { ++ switch (bcm47xx_bus_type) { + case BCM47XX_BUS_TYPE_SSB: + return ssb_gpio_in(&bcm47xx_bus.ssb, 1 << gpio); + } @@ -349,7 +349,7 @@ Signed-off-by: Hauke Mehrtens static inline void gpio_set_value(unsigned gpio, int value) { - ssb_gpio_out(&ssb_bcm47xx, 1 << gpio, value ? 1 << gpio : 0); -+ switch (bcm47xx_active_bus_type) { ++ switch (bcm47xx_bus_type) { + case BCM47XX_BUS_TYPE_SSB: + ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio, + value ? 1 << gpio : 0); @@ -360,7 +360,7 @@ Signed-off-by: Hauke Mehrtens { - ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 0); - return 0; -+ switch (bcm47xx_active_bus_type) { ++ switch (bcm47xx_bus_type) { + case BCM47XX_BUS_TYPE_SSB: + ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 0); + return 0; @@ -375,7 +375,7 @@ Signed-off-by: Hauke Mehrtens - /* then set the gpio mode */ - ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 1 << gpio); - return 0; -+ switch (bcm47xx_active_bus_type) { ++ switch (bcm47xx_bus_type) { + case BCM47XX_BUS_TYPE_SSB: + /* first set the gpio out value */ + ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio, @@ -392,7 +392,7 @@ Signed-off-by: Hauke Mehrtens - ssb_gpio_intmask(&ssb_bcm47xx, 1 << gpio, - value ? 1 << gpio : 0); - return 0; -+ switch (bcm47xx_active_bus_type) { ++ switch (bcm47xx_bus_type) { + case BCM47XX_BUS_TYPE_SSB: + ssb_gpio_intmask(&bcm47xx_bus.ssb, 1 << gpio, + value ? 1 << gpio : 0); @@ -406,7 +406,7 @@ Signed-off-by: Hauke Mehrtens - ssb_gpio_polarity(&ssb_bcm47xx, 1 << gpio, - value ? 1 << gpio : 0); - return 0; -+ switch (bcm47xx_active_bus_type) { ++ switch (bcm47xx_bus_type) { + case BCM47XX_BUS_TYPE_SSB: + ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << gpio, + value ? 1 << gpio : 0); @@ -423,7 +423,7 @@ Signed-off-by: Hauke Mehrtens { /* this is 2,5s on 100Mhz clock and 2s on 133 Mhz */ - ssb_watchdog_timer_set(&ssb_bcm47xx, 0xfffffff); -+ switch (bcm47xx_active_bus_type) { ++ switch (bcm47xx_bus_type) { + case BCM47XX_BUS_TYPE_SSB: + ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0xfffffff); + break; @@ -433,7 +433,7 @@ Signed-off-by: Hauke Mehrtens static inline int bcm47xx_wdt_hw_stop(void) { - return ssb_watchdog_timer_set(&ssb_bcm47xx, 0); -+ switch (bcm47xx_active_bus_type) { ++ switch (bcm47xx_bus_type) { + case BCM47XX_BUS_TYPE_SSB: + return ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0); + } diff --git a/target/linux/brcm47xx/patches-3.0/0009-bcm47xx-make-it-possible-to-build-bcm47xx-without-ss.patch b/target/linux/brcm47xx/patches-3.0/0009-bcm47xx-make-it-possible-to-build-bcm47xx-without-ss.patch index 2987ba7821..5b5771a85b 100644 --- a/target/linux/brcm47xx/patches-3.0/0009-bcm47xx-make-it-possible-to-build-bcm47xx-without-ss.patch +++ b/target/linux/brcm47xx/patches-3.0/0009-bcm47xx-make-it-possible-to-build-bcm47xx-without-ss.patch @@ -1,7 +1,7 @@ -From 1f25ff1b0bb5a8deae3aba2ea9c58f9b83f367bb Mon Sep 17 00:00:00 2001 +From 1ba12ca9e05153fbc611918ec0ea4cd9ec97f2c8 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Wed, 22 Jun 2011 22:16:35 +0200 -Subject: [PATCH 09/22] bcm47xx: make it possible to build bcm47xx without ssb. +Subject: [PATCH 09/26] bcm47xx: make it possible to build bcm47xx without ssb. Signed-off-by: Hauke Mehrtens @@ -82,7 +82,7 @@ Signed-off-by: Hauke Mehrtens @@ -21,6 +21,7 @@ static DECLARE_BITMAP(gpio_in_use, BCM47 int gpio_request(unsigned gpio, const char *tag) { - switch (bcm47xx_active_bus_type) { + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB case BCM47XX_BUS_TYPE_SSB: if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) && @@ -98,7 +98,7 @@ Signed-off-by: Hauke Mehrtens @@ -42,6 +44,7 @@ EXPORT_SYMBOL(gpio_request); void gpio_free(unsigned gpio) { - switch (bcm47xx_active_bus_type) { + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB case BCM47XX_BUS_TYPE_SSB: if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) && @@ -114,7 +114,7 @@ Signed-off-by: Hauke Mehrtens @@ -60,6 +64,7 @@ EXPORT_SYMBOL(gpio_free); int gpio_to_irq(unsigned gpio) { - switch (bcm47xx_active_bus_type) { + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB case BCM47XX_BUS_TYPE_SSB: if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco)) @@ -142,7 +142,7 @@ Signed-off-by: Hauke Mehrtens @@ -35,11 +37,13 @@ static void early_nvram_init(void) u32 *src, *dst; - switch (bcm47xx_active_bus_type) { + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB case BCM47XX_BUS_TYPE_SSB: mcore_ssb = &bcm47xx_bus.ssb.mipscore; @@ -171,7 +171,7 @@ Signed-off-by: Hauke Mehrtens static int __init uart8250_init(void) { - switch (bcm47xx_active_bus_type) { + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB case BCM47XX_BUS_TYPE_SSB: return uart8250_init_ssb(); @@ -184,7 +184,7 @@ Signed-off-by: Hauke Mehrtens @@ -47,9 +47,11 @@ static void bcm47xx_machine_restart(char local_irq_disable(); /* Set the watchdog timer to reset immediately */ - switch (bcm47xx_active_bus_type) { + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB case BCM47XX_BUS_TYPE_SSB: ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1); @@ -196,7 +196,7 @@ Signed-off-by: Hauke Mehrtens @@ -60,14 +62,17 @@ static void bcm47xx_machine_halt(void) /* Disable interrupts and watchdog and spin forever */ local_irq_disable(); - switch (bcm47xx_active_bus_type) { + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB case BCM47XX_BUS_TYPE_SSB: ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0); @@ -222,7 +222,7 @@ Signed-off-by: Hauke Mehrtens struct cpuinfo_mips *c = ¤t_cpu_data; +#ifdef CONFIG_BCM47XX_SSB - bcm47xx_active_bus_type = BCM47XX_BUS_TYPE_SSB; + bcm47xx_bus_type = BCM47XX_BUS_TYPE_SSB; bcm47xx_register_ssb(); +#endif @@ -233,7 +233,7 @@ Signed-off-by: Hauke Mehrtens @@ -40,9 +40,11 @@ void __init plat_time_init(void) write_c0_compare(0xffff); - switch (bcm47xx_active_bus_type) { + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB case BCM47XX_BUS_TYPE_SSB: hz = ssb_cpu_clock(&bcm47xx_bus.ssb.mipscore) / 2; @@ -265,7 +265,7 @@ Signed-off-by: Hauke Mehrtens @@ -22,8 +22,10 @@ extern int gpio_to_irq(unsigned gpio); static inline int gpio_get_value(unsigned gpio) { - switch (bcm47xx_active_bus_type) { + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB case BCM47XX_BUS_TYPE_SSB: return ssb_gpio_in(&bcm47xx_bus.ssb, 1 << gpio); @@ -276,7 +276,7 @@ Signed-off-by: Hauke Mehrtens @@ -31,18 +33,22 @@ static inline int gpio_get_value(unsigne static inline void gpio_set_value(unsigned gpio, int value) { - switch (bcm47xx_active_bus_type) { + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB case BCM47XX_BUS_TYPE_SSB: ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio, @@ -287,7 +287,7 @@ Signed-off-by: Hauke Mehrtens static inline int gpio_direction_input(unsigned gpio) { - switch (bcm47xx_active_bus_type) { + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB case BCM47XX_BUS_TYPE_SSB: ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 0); @@ -299,7 +299,7 @@ Signed-off-by: Hauke Mehrtens @@ -50,6 +56,7 @@ static inline int gpio_direction_input(u static inline int gpio_direction_output(unsigned gpio, int value) { - switch (bcm47xx_active_bus_type) { + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB case BCM47XX_BUS_TYPE_SSB: /* first set the gpio out value */ @@ -315,7 +315,7 @@ Signed-off-by: Hauke Mehrtens @@ -64,10 +72,12 @@ static inline int gpio_direction_output( static inline int gpio_intmask(unsigned gpio, int value) { - switch (bcm47xx_active_bus_type) { + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB case BCM47XX_BUS_TYPE_SSB: ssb_gpio_intmask(&bcm47xx_bus.ssb, 1 << gpio, @@ -328,7 +328,7 @@ Signed-off-by: Hauke Mehrtens @@ -75,10 +85,12 @@ static inline int gpio_intmask(unsigned static inline int gpio_polarity(unsigned gpio, int value) { - switch (bcm47xx_active_bus_type) { + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB case BCM47XX_BUS_TYPE_SSB: ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << gpio, @@ -356,7 +356,7 @@ Signed-off-by: Hauke Mehrtens int res; u8 slot, pin; -+ if (bcm47xx_active_bus_type != BCM47XX_BUS_TYPE_SSB) ++ if (bcm47xx_bus_type != BCM47XX_BUS_TYPE_SSB) + return 0; + res = ssb_pcibios_plat_dev_init(dev); @@ -374,7 +374,7 @@ Signed-off-by: Hauke Mehrtens @@ -55,17 +55,21 @@ static inline void bcm47xx_wdt_hw_start( { /* this is 2,5s on 100Mhz clock and 2s on 133 Mhz */ - switch (bcm47xx_active_bus_type) { + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB case BCM47XX_BUS_TYPE_SSB: ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0xfffffff); @@ -385,7 +385,7 @@ Signed-off-by: Hauke Mehrtens static inline int bcm47xx_wdt_hw_stop(void) { - switch (bcm47xx_active_bus_type) { + switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB case BCM47XX_BUS_TYPE_SSB: return ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0); diff --git a/target/linux/brcm47xx/patches-3.0/0010-bcm47xx-add-support-for-bcma-bus.patch b/target/linux/brcm47xx/patches-3.0/0010-bcm47xx-add-support-for-bcma-bus.patch index b2de30116a..fc8b09d91b 100644 --- a/target/linux/brcm47xx/patches-3.0/0010-bcm47xx-add-support-for-bcma-bus.patch +++ b/target/linux/brcm47xx/patches-3.0/0010-bcm47xx-add-support-for-bcma-bus.patch @@ -1,7 +1,7 @@ -From 27aa4f76cfe54b6ce3bf98f4d5fd70ab1f60071f Mon Sep 17 00:00:00 2001 +From d3fb63a710e1f04fed2c2703c6dce3531490c451 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Mon, 6 Jun 2011 00:07:37 +0200 -Subject: [PATCH 10/22] bcm47xx: add support for bcma bus +Subject: [PATCH 10/26] bcm47xx: add support for bcma bus This patch add support for the bcma bus. Broadcom uses only Mips 74K CPUs on the new SoC and on the old ons using ssb bus there are no Mips @@ -144,7 +144,7 @@ Signed-off-by: Hauke Mehrtens + static int __init uart8250_init(void) { - switch (bcm47xx_active_bus_type) { + switch (bcm47xx_bus_type) { @@ -54,6 +79,10 @@ static int __init uart8250_init(void) case BCM47XX_BUS_TYPE_SSB: return uart8250_init_ssb(); @@ -212,15 +212,15 @@ Signed-off-by: Hauke Mehrtens + if (c->cputype == CPU_74K) { + printk(KERN_INFO "bcm47xx: using bcma bus\n"); +#ifdef CONFIG_BCM47XX_BCMA -+ bcm47xx_active_bus_type = BCM47XX_BUS_TYPE_BCMA; ++ bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA; + bcm47xx_register_bcma(); +#endif + } else { + printk(KERN_INFO "bcm47xx: using ssb bus\n"); #ifdef CONFIG_BCM47XX_SSB -- bcm47xx_active_bus_type = BCM47XX_BUS_TYPE_SSB; +- bcm47xx_bus_type = BCM47XX_BUS_TYPE_SSB; - bcm47xx_register_ssb(); -+ bcm47xx_active_bus_type = BCM47XX_BUS_TYPE_SSB; ++ bcm47xx_bus_type = BCM47XX_BUS_TYPE_SSB; + bcm47xx_register_ssb(); #endif + } @@ -232,7 +232,7 @@ Signed-off-by: Hauke Mehrtens + +static int __init bcm47xx_register_bus_complete(void) +{ -+ switch (bcm47xx_active_bus_type) { ++ switch (bcm47xx_bus_type) { +#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + /* Nothing to do */ diff --git a/target/linux/brcm47xx/patches-3.0/0011-bcm47xx-fix-irq-assignment-for-new-SoCs.patch b/target/linux/brcm47xx/patches-3.0/0011-bcm47xx-fix-irq-assignment-for-new-SoCs.patch index f3229eb115..216c56d9e6 100644 --- a/target/linux/brcm47xx/patches-3.0/0011-bcm47xx-fix-irq-assignment-for-new-SoCs.patch +++ b/target/linux/brcm47xx/patches-3.0/0011-bcm47xx-fix-irq-assignment-for-new-SoCs.patch @@ -1,7 +1,7 @@ -From a277b0b02837a167a5766c048dedef8dfc2fb707 Mon Sep 17 00:00:00 2001 +From 1c44f60e3fd9336d19f56a67c1efc1129fd728a6 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Mon, 6 Jun 2011 00:07:38 +0200 -Subject: [PATCH 11/22] bcm47xx: fix irq assignment for new SoCs. +Subject: [PATCH 11/26] bcm47xx: fix irq assignment for new SoCs. Signed-off-by: Hauke Mehrtens --- @@ -23,7 +23,7 @@ Signed-off-by: Hauke Mehrtens void __init arch_init_irq(void) { +#ifdef CONFIG_BCM47XX_BCMA -+ if (bcm47xx_active_bus_type == BCM47XX_BUS_TYPE_BCMA) { ++ if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA) { + bcma_write32(bcm47xx_bus.bcma.bus.drv_mips.core, + BCMA_MIPS_MIPS74K_INTMASK(5), 1 << 31); + /* diff --git a/target/linux/brcm47xx/patches-3.0/0012-bcma-move-parallel-flash-into-a-union.patch b/target/linux/brcm47xx/patches-3.0/0012-bcma-move-parallel-flash-into-a-union.patch index 15629aca24..9a4e877287 100644 --- a/target/linux/brcm47xx/patches-3.0/0012-bcma-move-parallel-flash-into-a-union.patch +++ b/target/linux/brcm47xx/patches-3.0/0012-bcma-move-parallel-flash-into-a-union.patch @@ -1,54 +1,38 @@ -From a1d9c96a6c9b37b26dc1149706f3061b57a62b50 Mon Sep 17 00:00:00 2001 +From b7d9f9cd6a8e463c1061ea29ed3e614403625024 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sun, 17 Jul 2011 14:51:47 +0200 -Subject: [PATCH 12/22] bcma: move parallel flash into a union +Subject: [PATCH 12/26] bcma: move parallel flash into a union Signed-off-by: Hauke Mehrtens --- - arch/mips/bcm47xx/nvram.c | 7 ++- - drivers/bcma/driver_mips.c | 9 ++-- - include/linux/bcma/bcma_driver_chipcommon.h | 75 ++++++++++++++++++++++++++- - 3 files changed, 84 insertions(+), 7 deletions(-) + arch/mips/bcm47xx/nvram.c | 3 + + drivers/bcma/driver_mips.c | 1 + + include/linux/bcma/bcma_driver_chipcommon.h | 73 ++++++++++++++++++++++++++- + 3 files changed, 76 insertions(+), 1 deletions(-) --- a/arch/mips/bcm47xx/nvram.c +++ b/arch/mips/bcm47xx/nvram.c -@@ -50,8 +50,11 @@ static void early_nvram_init(void) +@@ -50,6 +50,9 @@ static void early_nvram_init(void) #ifdef CONFIG_BCM47XX_BCMA case BCM47XX_BUS_TYPE_BCMA: bcma_cc = &bcm47xx_bus.bcma.bus.drv_cc; -- base = bcma_cc->pflash.window; -- lim = bcma_cc->pflash.window_size; + if (bcma_cc->flash_type != BCMA_PFLASH) + return; + -+ base = bcma_cc->flash.pflash.window; -+ lim = bcma_cc->flash.pflash.window_size; + base = bcma_cc->pflash.window; + lim = bcma_cc->pflash.window_size; break; - #endif - } --- a/drivers/bcma/driver_mips.c +++ b/drivers/bcma/driver_mips.c -@@ -189,14 +189,15 @@ static void bcma_core_mips_flash_detect( +@@ -189,6 +189,7 @@ static void bcma_core_mips_flash_detect( break; case BCMA_CC_FLASHT_PARA: pr_info("found parallel flash.\n"); -- bus->drv_cc.pflash.window = 0x1c000000; -- bus->drv_cc.pflash.window_size = 0x02000000; + bus->drv_cc.flash_type = BCMA_PFLASH; -+ bus->drv_cc.flash.pflash.window = 0x1c000000; -+ bus->drv_cc.flash.pflash.window_size = 0x02000000; + bus->drv_cc.pflash.window = 0x1c000000; + bus->drv_cc.pflash.window_size = 0x02000000; - if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) & - BCMA_CC_FLASH_CFG_DS) == 0) -- bus->drv_cc.pflash.buswidth = 1; -+ bus->drv_cc.flash.pflash.buswidth = 1; - else -- bus->drv_cc.pflash.buswidth = 2; -+ bus->drv_cc.flash.pflash.buswidth = 2; - break; - default: - pr_err("flash not supported.\n"); --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h @@ -108,10 +108,68 @@ @@ -133,7 +117,7 @@ Signed-off-by: Hauke Mehrtens /* Data for the PMU, if available. * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU) */ -@@ -292,12 +356,20 @@ struct bcma_chipcommon_pmu { +@@ -292,6 +356,10 @@ struct bcma_chipcommon_pmu { }; #ifdef CONFIG_BCMA_DRIVER_MIPS @@ -144,23 +128,15 @@ Signed-off-by: Hauke Mehrtens struct bcma_pflash { u8 buswidth; u32 window; - u32 window_size; - }; - -+union bcma_flash { -+ struct bcma_pflash pflash; -+}; -+ - struct bcma_serial_port { - void *regs; - unsigned long clockspeed; -@@ -317,7 +389,8 @@ struct bcma_drv_cc { +@@ -317,7 +385,10 @@ struct bcma_drv_cc { u16 fast_pwrup_delay; struct bcma_chipcommon_pmu pmu; #ifdef CONFIG_BCMA_DRIVER_MIPS - struct bcma_pflash pflash; + enum bcma_flash_type flash_type; -+ union bcma_flash flash; ++ union { ++ struct bcma_pflash pflash; ++ }; int nr_serial_ports; struct bcma_serial_port serial_ports[4]; diff --git a/target/linux/brcm47xx/patches-3.0/0013-bcma-add-serial-flash-support-to-bcma.patch b/target/linux/brcm47xx/patches-3.0/0013-bcma-add-serial-flash-support-to-bcma.patch index bcaf85ba8f..14e5a3bcc9 100644 --- a/target/linux/brcm47xx/patches-3.0/0013-bcma-add-serial-flash-support-to-bcma.patch +++ b/target/linux/brcm47xx/patches-3.0/0013-bcma-add-serial-flash-support-to-bcma.patch @@ -1,7 +1,7 @@ -From b5be6e3037650ff5615cb869f1972dea5a49bcb6 Mon Sep 17 00:00:00 2001 +From a62940e988526c881966a8c72cc28c95fca89f3c Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sun, 17 Jul 2011 14:53:07 +0200 -Subject: [PATCH 13/22] bcma: add serial flash support to bcma +Subject: [PATCH 13/26] bcma: add serial flash support to bcma Signed-off-by: Hauke Mehrtens @@ -9,10 +9,10 @@ Signed-off-by: Hauke Mehrtens drivers/bcma/Kconfig | 5 + drivers/bcma/Makefile | 1 + drivers/bcma/bcma_private.h | 5 + - drivers/bcma/driver_chipcommon_sflash.c | 554 +++++++++++++++++++++++++++ + drivers/bcma/driver_chipcommon_sflash.c | 555 +++++++++++++++++++++++++++ drivers/bcma/driver_mips.c | 8 +- include/linux/bcma/bcma_driver_chipcommon.h | 24 ++ - 6 files changed, 596 insertions(+), 1 deletions(-) + 6 files changed, 597 insertions(+), 1 deletions(-) create mode 100644 drivers/bcma/driver_chipcommon_sflash.c --- a/drivers/bcma/Kconfig @@ -54,7 +54,7 @@ Signed-off-by: Hauke Mehrtens extern int __init bcma_host_pci_init(void); --- /dev/null +++ b/drivers/bcma/driver_chipcommon_sflash.c -@@ -0,0 +1,554 @@ +@@ -0,0 +1,555 @@ +/* + * Broadcom SiliconBackplane chipcommon serial flash interface + * @@ -78,8 +78,8 @@ Signed-off-by: Hauke Mehrtens +{ + bcma_cc_write32(cc, BCMA_CC_FLASHCTL, + BCMA_CC_FLASHCTL_START | opcode); -+ while (bcma_cc_read32(cc, BCMA_CC_FLASHCTL) -+ & BCMA_CC_FLASHCTL_BUSY); ++ while (bcma_cc_read32(cc, BCMA_CC_FLASHCTL) & BCMA_CC_FLASHCTL_BUSY) ++ ; +} + + @@ -95,7 +95,7 @@ Signed-off-by: Hauke Mehrtens +{ + u32 id, id2; + -+ memset(&cc->flash.sflash, 0, sizeof(struct bcma_sflash)); ++ memset(&cc->sflash, 0, sizeof(struct bcma_sflash)); + + switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { + case BCMA_CC_FLASHT_STSER: @@ -104,35 +104,35 @@ Signed-off-by: Hauke Mehrtens + bcma_cc_write32(cc, BCMA_CC_FLASHADDR, 0); + bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RES); + id = bcma_cc_read32(cc, BCMA_CC_FLASHDATA); -+ cc->flash.sflash.blocksize = 64 * 1024; ++ cc->sflash.blocksize = 64 * 1024; + switch (id) { + case 0x11: + /* ST M25P20 2 Mbit Serial Flash */ -+ cc->flash.sflash.numblocks = 4; ++ cc->sflash.numblocks = 4; + break; + case 0x12: + /* ST M25P40 4 Mbit Serial Flash */ -+ cc->flash.sflash.numblocks = 8; ++ cc->sflash.numblocks = 8; + break; + case 0x13: + /* ST M25P80 8 Mbit Serial Flash */ -+ cc->flash.sflash.numblocks = 16; ++ cc->sflash.numblocks = 16; + break; + case 0x14: + /* ST M25P16 16 Mbit Serial Flash */ -+ cc->flash.sflash.numblocks = 32; ++ cc->sflash.numblocks = 32; + break; + case 0x15: + /* ST M25P32 32 Mbit Serial Flash */ -+ cc->flash.sflash.numblocks = 64; ++ cc->sflash.numblocks = 64; + break; + case 0x16: + /* ST M25P64 64 Mbit Serial Flash */ -+ cc->flash.sflash.numblocks = 128; ++ cc->sflash.numblocks = 128; + break; + case 0x17: + /* ST M25FL128 128 Mbit Serial Flash */ -+ cc->flash.sflash.numblocks = 256; ++ cc->sflash.numblocks = 256; + break; + case 0xbf: + /* All of the following flashes are SST with @@ -140,7 +140,7 @@ Signed-off-by: Hauke Mehrtens + * We'll have to revamp the way we identify them + * since RES is not eough to disambiguate them. + */ -+ cc->flash.sflash.blocksize = 4 * 1024; ++ cc->sflash.blocksize = 4 * 1024; + bcma_cc_write32(cc, BCMA_CC_FLASHADDR, 1); + bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RES); + id2 = bcma_cc_read32(cc, BCMA_CC_FLASHDATA); @@ -149,19 +149,19 @@ Signed-off-by: Hauke Mehrtens + /* SST25WF512 512 Kbit Serial Flash */ + case 0x48: + /* SST25VF512 512 Kbit Serial Flash */ -+ cc->flash.sflash.numblocks = 16; ++ cc->sflash.numblocks = 16; + break; + case 2: + /* SST25WF010 1 Mbit Serial Flash */ + case 0x49: + /* SST25VF010 1 Mbit Serial Flash */ -+ cc->flash.sflash.numblocks = 32; ++ cc->sflash.numblocks = 32; + break; + case 3: + /* SST25WF020 2 Mbit Serial Flash */ + case 0x43: + /* SST25VF020 2 Mbit Serial Flash */ -+ cc->flash.sflash.numblocks = 64; ++ cc->sflash.numblocks = 64; + break; + case 4: + /* SST25WF040 4 Mbit Serial Flash */ @@ -169,25 +169,25 @@ Signed-off-by: Hauke Mehrtens + /* SST25VF040 4 Mbit Serial Flash */ + case 0x8d: + /* SST25VF040B 4 Mbit Serial Flash */ -+ cc->flash.sflash.numblocks = 128; ++ cc->sflash.numblocks = 128; + break; + case 5: + /* SST25WF080 8 Mbit Serial Flash */ + case 0x8e: + /* SST25VF080B 8 Mbit Serial Flash */ -+ cc->flash.sflash.numblocks = 256; ++ cc->sflash.numblocks = 256; + break; + case 0x41: + /* SST25VF016 16 Mbit Serial Flash */ -+ cc->flash.sflash.numblocks = 512; ++ cc->sflash.numblocks = 512; + break; + case 0x4a: + /* SST25VF032 32 Mbit Serial Flash */ -+ cc->flash.sflash.numblocks = 1024; ++ cc->sflash.numblocks = 1024; + break; + case 0x4b: + /* SST25VF064 64 Mbit Serial Flash */ -+ cc->flash.sflash.numblocks = 2048; ++ cc->sflash.numblocks = 2048; + break; + } + break; @@ -201,46 +201,46 @@ Signed-off-by: Hauke Mehrtens + switch (id) { + case 0xc: + /* Atmel AT45DB011 1Mbit Serial Flash */ -+ cc->flash.sflash.blocksize = 256; -+ cc->flash.sflash.numblocks = 512; ++ cc->sflash.blocksize = 256; ++ cc->sflash.numblocks = 512; + break; + case 0x14: + /* Atmel AT45DB021 2Mbit Serial Flash */ -+ cc->flash.sflash.blocksize = 256; -+ cc->flash.sflash.numblocks = 1024; ++ cc->sflash.blocksize = 256; ++ cc->sflash.numblocks = 1024; + break; + case 0x1c: + /* Atmel AT45DB041 4Mbit Serial Flash */ -+ cc->flash.sflash.blocksize = 256; -+ cc->flash.sflash.numblocks = 2048; ++ cc->sflash.blocksize = 256; ++ cc->sflash.numblocks = 2048; + break; + case 0x24: + /* Atmel AT45DB081 8Mbit Serial Flash */ -+ cc->flash.sflash.blocksize = 256; -+ cc->flash.sflash.numblocks = 4096; ++ cc->sflash.blocksize = 256; ++ cc->sflash.numblocks = 4096; + break; + case 0x2c: + /* Atmel AT45DB161 16Mbit Serial Flash */ -+ cc->flash.sflash.blocksize = 512; -+ cc->flash.sflash.numblocks = 4096; ++ cc->sflash.blocksize = 512; ++ cc->sflash.numblocks = 4096; + break; + case 0x34: + /* Atmel AT45DB321 32Mbit Serial Flash */ -+ cc->flash.sflash.blocksize = 512; -+ cc->flash.sflash.numblocks = 8192; ++ cc->sflash.blocksize = 512; ++ cc->sflash.numblocks = 8192; + break; + case 0x3c: + /* Atmel AT45DB642 64Mbit Serial Flash */ -+ cc->flash.sflash.blocksize = 1024; -+ cc->flash.sflash.numblocks = 8192; ++ cc->sflash.blocksize = 1024; ++ cc->sflash.numblocks = 8192; + break; + } + break; + } + -+ cc->flash.sflash.size = cc->flash.sflash.blocksize * cc->flash.sflash.numblocks; ++ cc->sflash.size = cc->sflash.blocksize * cc->sflash.numblocks; + -+ return cc->flash.sflash.size ? 0 : -ENODEV; ++ return cc->sflash.size ? 0 : -ENODEV; +} + +/* Read len bytes starting at offset into buf. Returns number of bytes read. */ @@ -253,7 +253,7 @@ Signed-off-by: Hauke Mehrtens + if (!len) + return 0; + -+ if ((offset + len) > cc->flash.sflash.size) ++ if ((offset + len) > cc->sflash.size) + return -EINVAL; + + if ((len >= 4) && (offset & 3)) @@ -293,7 +293,7 @@ Signed-off-by: Hauke Mehrtens +/* Poll for command completion. Returns zero when complete. */ +int bcma_sflash_poll(struct bcma_drv_cc *cc, u32 offset) +{ -+ if (offset >= cc->flash.sflash.size) ++ if (offset >= cc->sflash.size) + return -22; + + switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { @@ -407,7 +407,7 @@ Signed-off-by: Hauke Mehrtens +static int sflash_at_write(struct bcma_drv_cc *cc, u32 offset, u32 len, + const u8 *buf) +{ -+ struct bcma_sflash *sfl = &cc->flash.sflash; ++ struct bcma_sflash *sfl = &cc->sflash; + u32 page, byte, mask; + int ret = 0; + mask = sfl->blocksize - 1; @@ -450,10 +450,10 @@ Signed-off-by: Hauke Mehrtens + if (!len) + return 0; + -+ if ((offset + len) > cc->flash.sflash.size) ++ if ((offset + len) > cc->sflash.size) + return -EINVAL; + -+ sfl = &cc->flash.sflash; ++ sfl = &cc->sflash; + switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { + case BCMA_CC_FLASHT_STSER: + do { @@ -481,10 +481,10 @@ Signed-off-by: Hauke Mehrtens +{ + struct bcma_sflash *sfl; + -+ if (offset >= cc->flash.sflash.size) ++ if (offset >= cc->sflash.size) + return -EINVAL; + -+ sfl = &cc->flash.sflash; ++ sfl = &cc->sflash; + switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { + case BCMA_CC_FLASHT_STSER: + bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_WREN); @@ -521,7 +521,7 @@ Signed-off-by: Hauke Mehrtens + if (len <= 0) + return 0; + -+ sfl = &cc->flash.sflash; ++ sfl = &cc->sflash; + if ((offset + len) > sfl->size) + return -EINVAL; + @@ -592,7 +592,8 @@ Signed-off-by: Hauke Mehrtens + goto done; + } + -+ while (bcma_sflash_poll(cc, cur_offset)); ++ while (bcma_sflash_poll(cc, cur_offset)) ++ ; + + cur_offset += bytes; + cur_length -= bytes; @@ -636,7 +637,7 @@ Signed-off-by: Hauke Mehrtens }; struct bcma_pflash { -@@ -366,8 +367,19 @@ struct bcma_pflash { +@@ -366,6 +367,14 @@ struct bcma_pflash { u32 window_size; }; @@ -648,15 +649,20 @@ Signed-off-by: Hauke Mehrtens +}; +#endif /* CONFIG_BCMA_SFLASH */ + - union bcma_flash { - struct bcma_pflash pflash; + struct bcma_serial_port { + void *regs; + unsigned long clockspeed; +@@ -388,6 +397,9 @@ struct bcma_drv_cc { + enum bcma_flash_type flash_type; + union { + struct bcma_pflash pflash; +#ifdef CONFIG_BCMA_SFLASH -+ struct bcma_sflash sflash; ++ struct bcma_sflash sflash; +#endif /* CONFIG_BCMA_SFLASH */ - }; + }; - struct bcma_serial_port { -@@ -433,4 +445,16 @@ u32 bcma_chipco_gpio_polarity(struct bcm + int nr_serial_ports; +@@ -431,4 +443,16 @@ u32 bcma_chipco_gpio_polarity(struct bcm /* PMU support */ extern void bcma_pmu_init(struct bcma_drv_cc *cc); diff --git a/target/linux/brcm47xx/patches-3.0/0014-mtd-bcm47xx-add-bcm47xx-part-parser.patch b/target/linux/brcm47xx/patches-3.0/0014-mtd-bcm47xx-add-bcm47xx-part-parser.patch deleted file mode 100644 index 98b1a445c2..0000000000 --- a/target/linux/brcm47xx/patches-3.0/0014-mtd-bcm47xx-add-bcm47xx-part-parser.patch +++ /dev/null @@ -1,579 +0,0 @@ -From 4b449ce15d74e5973cde18381c2a3fa0616b2b3d Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens -Date: Sun, 17 Jul 2011 14:54:11 +0200 -Subject: [PATCH 14/18] mtd: bcm47xx: add bcm47xx part parser - - -Signed-off-by: Hauke Mehrtens ---- - drivers/mtd/Kconfig | 7 + - drivers/mtd/Makefile | 1 + - drivers/mtd/bcm47xxpart.c | 536 +++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 544 insertions(+), 0 deletions(-) - create mode 100644 drivers/mtd/bcm47xxpart.c - ---- a/drivers/mtd/Kconfig -+++ b/drivers/mtd/Kconfig -@@ -173,6 +173,13 @@ config MTD_MYLOADER_PARTS - You will still need the parsing functions to be called by the driver - for your particular device. It won't happen automatically. - -+config MTD_BCM47XX_PARTS -+ tristate "BCM47XX partitioning support" -+ default y -+ depends on BCM47XX -+ ---help--- -+ bcm47XX partitioning support -+ - comment "User Modules And Translation Layers" - - config MTD_CHAR ---- a/drivers/mtd/Makefile -+++ b/drivers/mtd/Makefile -@@ -12,6 +12,7 @@ obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdli - obj-$(CONFIG_MTD_AFS_PARTS) += afs.o - obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o - obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o -+obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o - - # 'Users' - code which presents functionality to userspace. - obj-$(CONFIG_MTD_CHAR) += mtdchar.o ---- /dev/null -+++ b/drivers/mtd/bcm47xxpart.c -@@ -0,0 +1,536 @@ -+/* -+ * Copyright (C) 2006 Felix Fietkau -+ * Copyright (C) 2005 Waldemar Brodkorb -+ * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org) -+ * -+ * original functions for finding root filesystem from Mike Baker -+ * -+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN -+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * 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., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ * -+ * Copyright 2001-2003, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ * Flash mapping for BCM947XX boards -+ */ -+ -+#define pr_fmt(fmt) "bcm47xx_part: " fmt -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+#define TRX_MAGIC 0x30524448 /* "HDR0" */ -+#define TRX_VERSION 1 -+#define TRX_MAX_LEN 0x3A0000 -+#define TRX_NO_HEADER 1 /* Do not write TRX header */ -+#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */ -+#define TRX_MAX_OFFSET 3 -+ -+struct trx_header { -+ u32 magic; /* "HDR0" */ -+ u32 len; /* Length of file including header */ -+ u32 crc32; /* 32-bit CRC from flag_version to end of file */ -+ u32 flag_version; /* 0:15 flags, 16:31 version */ -+ u32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */ -+}; -+ -+/* for Edimax Print servers which use an additional header -+ * then the firmware on flash looks like : -+ * EDIMAX HEADER | TRX HEADER -+ * As this header is 12 bytes long we have to handle it -+ * and skip it to find the TRX header -+ */ -+#define EDIMAX_PS_HEADER_MAGIC 0x36315350 /* "PS16" */ -+#define EDIMAX_PS_HEADER_LEN 0xc /* 12 bytes long for edimax header */ -+ -+#define NVRAM_SPACE 0x8000 -+ -+#define ROUTER_NETGEAR_WGR614L 1 -+#define ROUTER_NETGEAR_WNR834B 2 -+#define ROUTER_NETGEAR_WNDR3300 3 -+#define ROUTER_NETGEAR_WNR3500L 4 -+#define ROUTER_SIMPLETECH_SIMPLESHARE 5 -+ -+static struct mtd_partition bcm47xx_parts[] = { -+ { name: "cfe", offset: 0, size: 0, mask_flags: MTD_WRITEABLE, }, -+ { name: "linux", offset: 0, size: 0, }, -+ { name: "rootfs", offset: 0, size: 0, }, -+ { name: "nvram", offset: 0, size: 0, }, -+ { name: NULL, }, /* Used to create custom partitons with the function get_router() */ -+ { name: NULL, }, -+}; -+ -+static int -+find_cfe_size(struct mtd_info *mtd) -+{ -+ struct trx_header *trx; -+ unsigned char buf[512]; -+ int off; -+ size_t len; -+ int blocksize; -+ -+ trx = (struct trx_header *) buf; -+ -+ blocksize = mtd->erasesize; -+ if (blocksize < 0x10000) -+ blocksize = 0x10000; -+ -+ for (off = (128*1024); off < mtd->size; off += blocksize) { -+ memset(buf, 0xe5, sizeof(buf)); -+ -+ /* -+ * Read into buffer -+ */ -+ if (mtd->read(mtd, off, sizeof(buf), &len, buf) || -+ len != sizeof(buf)) -+ continue; -+ -+ if (le32_to_cpu(trx->magic) == EDIMAX_PS_HEADER_MAGIC) { -+ if (mtd->read(mtd, off + EDIMAX_PS_HEADER_LEN, -+ sizeof(buf), &len, buf) || len != sizeof(buf)) { -+ continue; -+ } else { -+ pr_notice("Found edimax header\n"); -+ } -+ } -+ -+ /* found a TRX header */ -+ if (le32_to_cpu(trx->magic) == TRX_MAGIC) { -+ goto found; -+ } -+ } -+ -+ pr_notice("%s: Couldn't find bootloader size\n", mtd->name); -+ return -1; -+ -+ found: -+ pr_notice("bootloader size: %d\n", off); -+ return off; -+ -+} -+ -+/* -+ * Copied from mtdblock.c -+ * -+ * Cache stuff... -+ * -+ * Since typical flash erasable sectors are much larger than what Linux's -+ * buffer cache can handle, we must implement read-modify-write on flash -+ * sectors for each block write requests. To avoid over-erasing flash sectors -+ * and to speed things up, we locally cache a whole flash sector while it is -+ * being written to until a different sector is required. -+ */ -+ -+static void erase_callback(struct erase_info *done) -+{ -+ wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv; -+ wake_up(wait_q); -+} -+ -+static int erase_write (struct mtd_info *mtd, unsigned long pos, -+ int len, const char *buf) -+{ -+ struct erase_info erase; -+ DECLARE_WAITQUEUE(wait, current); -+ wait_queue_head_t wait_q; -+ size_t retlen; -+ int ret; -+ -+ /* -+ * First, let's erase the flash block. -+ */ -+ -+ init_waitqueue_head(&wait_q); -+ erase.mtd = mtd; -+ erase.callback = erase_callback; -+ erase.addr = pos; -+ erase.len = len; -+ erase.priv = (u_long)&wait_q; -+ -+ set_current_state(TASK_INTERRUPTIBLE); -+ add_wait_queue(&wait_q, &wait); -+ -+ ret = mtd->erase(mtd, &erase); -+ if (ret) { -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&wait_q, &wait); -+ pr_warn("erase of region [0x%lx, 0x%x] on \"%s\" failed\n", -+ pos, len, mtd->name); -+ return ret; -+ } -+ -+ schedule(); /* Wait for erase to finish. */ -+ remove_wait_queue(&wait_q, &wait); -+ -+ /* -+ * Next, write data to flash. -+ */ -+ -+ ret = mtd->write (mtd, pos, len, &retlen, buf); -+ if (ret) -+ return ret; -+ if (retlen != len) -+ return -EIO; -+ return 0; -+} -+ -+ -+static int -+find_dual_image_off (struct mtd_info *mtd) -+{ -+ struct trx_header trx; -+ int off, blocksize; -+ size_t len; -+ -+ blocksize = mtd->erasesize; -+ if (blocksize < 0x10000) -+ blocksize = 0x10000; -+ -+ for (off = (128*1024); off < mtd->size; off += blocksize) { -+ memset(&trx, 0xe5, sizeof(trx)); -+ /* -+ * Read into buffer -+ */ -+ if (mtd->read(mtd, off, sizeof(trx), &len, (char *) &trx) || -+ len != sizeof(trx)) -+ continue; -+ /* found last TRX header */ -+ if (le32_to_cpu(trx.magic) == TRX_MAGIC){ -+ if (le32_to_cpu(trx.flag_version >> 16)==2){ -+ pr_notice("dual image TRX header found\n"); -+ return mtd->size / 2; -+ } else { -+ return 0; -+ } -+ } -+ } -+ return 0; -+} -+ -+ -+static int -+find_root(struct mtd_info *mtd, struct mtd_partition *part) -+{ -+ struct trx_header trx, *trx2; -+ unsigned char buf[512], *block; -+ int off, blocksize, trxoff = 0; -+ u32 i, crc = ~0; -+ size_t len; -+ bool edimax = false; -+ -+ blocksize = mtd->erasesize; -+ if (blocksize < 0x10000) -+ blocksize = 0x10000; -+ -+ for (off = (128*1024); off < mtd->size; off += blocksize) { -+ memset(&trx, 0xe5, sizeof(trx)); -+ -+ /* -+ * Read into buffer -+ */ -+ if (mtd->read(mtd, off, sizeof(trx), &len, (char *) &trx) || -+ len != sizeof(trx)) -+ continue; -+ -+ /* found an edimax header */ -+ if (le32_to_cpu(trx.magic) == EDIMAX_PS_HEADER_MAGIC) { -+ /* read the correct trx header */ -+ if (mtd->read(mtd, off + EDIMAX_PS_HEADER_LEN, -+ sizeof(trx), &len, (char *) &trx) || -+ len != sizeof(trx)) { -+ continue; -+ } else { -+ pr_notice("Found an edimax ps header\n"); -+ edimax = true; -+ } -+ } -+ -+ /* found a TRX header */ -+ if (le32_to_cpu(trx.magic) == TRX_MAGIC) { -+ part->offset = le32_to_cpu(trx.offsets[2]) ? : -+ le32_to_cpu(trx.offsets[1]); -+ part->size = le32_to_cpu(trx.len); -+ -+ part->size -= part->offset; -+ part->offset += off; -+ if (edimax) { -+ off += EDIMAX_PS_HEADER_LEN; -+ trxoff = EDIMAX_PS_HEADER_LEN; -+ } -+ -+ goto found; -+ } -+ } -+ -+ pr_warn("%s: Couldn't find root filesystem\n", -+ mtd->name); -+ return -1; -+ -+ found: -+ pr_notice("TRX offset : %x\n", trxoff); -+ if (part->size == 0) -+ return 0; -+ -+ if (mtd->read(mtd, part->offset, sizeof(buf), &len, buf) || len != sizeof(buf)) -+ return 0; -+ -+ /* Move the fs outside of the trx */ -+ part->size = 0; -+ -+ if (trx.len != part->offset + part->size - off) { -+ /* Update the trx offsets and length */ -+ trx.len = part->offset + part->size - off; -+ -+ /* Update the trx crc32 */ -+ for (i = (u32) &(((struct trx_header *)NULL)->flag_version); i <= trx.len; i += sizeof(buf)) { -+ if (mtd->read(mtd, off + i, sizeof(buf), &len, buf) || len != sizeof(buf)) -+ return 0; -+ crc = crc32_le(crc, buf, min(sizeof(buf), trx.len - i)); -+ } -+ trx.crc32 = crc; -+ -+ /* read first eraseblock from the trx */ -+ block = kmalloc(mtd->erasesize, GFP_KERNEL); -+ trx2 = (struct trx_header *) block; -+ if (mtd->read(mtd, off - trxoff, mtd->erasesize, &len, block) || len != mtd->erasesize) { -+ pr_err("Error accessing the first trx eraseblock\n"); -+ return 0; -+ } -+ -+ pr_notice("Updating TRX offsets and length:\n"); -+ pr_notice("old trx = [0x%08x, 0x%08x, 0x%08x], len=0x%08x crc32=0x%08x\n", trx2->offsets[0], trx2->offsets[1], trx2->offsets[2], trx2->len, trx2->crc32); -+ pr_notice("new trx = [0x%08x, 0x%08x, 0x%08x], len=0x%08x crc32=0x%08x\n", trx.offsets[0], trx.offsets[1], trx.offsets[2], trx.len, trx.crc32); -+ -+ /* Write updated trx header to the flash */ -+ memcpy(block + trxoff, &trx, sizeof(trx)); -+ if (mtd->unlock) -+ mtd->unlock(mtd, off - trxoff, mtd->erasesize); -+ erase_write(mtd, off - trxoff, mtd->erasesize, block); -+ if (mtd->sync) -+ mtd->sync(mtd); -+ kfree(block); -+ pr_notice("Done\n"); -+ } -+ -+ return part->size; -+} -+ -+static int get_router(void) -+{ -+ char buf[20]; -+ u32 boardnum = 0; -+ u16 boardtype = 0; -+ u16 boardrev = 0; -+ u32 boardflags = 0; -+ u16 sdram_init = 0; -+ u16 cardbus = 0; -+ u16 strev = 0; -+ -+ if (nvram_getenv("boardnum", buf, sizeof(buf)) >= 0) -+ boardnum = simple_strtoul(buf, NULL, 0); -+ if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0) -+ boardtype = simple_strtoul(buf, NULL, 0); -+ if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0) -+ boardrev = simple_strtoul(buf, NULL, 0); -+ if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0) -+ boardflags = simple_strtoul(buf, NULL, 0); -+ if (nvram_getenv("sdram_init", buf, sizeof(buf)) >= 0) -+ sdram_init = simple_strtoul(buf, NULL, 0); -+ if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0) -+ cardbus = simple_strtoul(buf, NULL, 0); -+ if (nvram_getenv("st_rev", buf, sizeof(buf)) >= 0) -+ strev = simple_strtoul(buf, NULL, 0); -+ -+ if ((boardnum == 8 || boardnum == 01) -+ && boardtype == 0x0472 && cardbus == 1) { -+ /* Netgear WNR834B, Netgear WNR834Bv2 */ -+ return ROUTER_NETGEAR_WNR834B; -+ } -+ -+ if (boardnum == 01 && boardtype == 0x0472 && boardrev == 0x23) { -+ /* Netgear WNDR-3300 */ -+ return ROUTER_NETGEAR_WNDR3300; -+ } -+ -+ if ((boardnum == 83258 || boardnum == 01) -+ && boardtype == 0x048e -+ && (boardrev == 0x11 || boardrev == 0x10) -+ && boardflags == 0x750 -+ && sdram_init == 0x000A) { -+ /* Netgear WGR614v8/L/WW 16MB ram, cfe v1.3 or v1.5 */ -+ return ROUTER_NETGEAR_WGR614L; -+ } -+ -+ if ((boardnum == 1 || boardnum == 3500) -+ && boardtype == 0x04CF -+ && (boardrev == 0x1213 || boardrev == 02)) { -+ /* Netgear WNR3500v2/U/L */ -+ return ROUTER_NETGEAR_WNR3500L; -+ } -+ -+ if (boardtype == 0x042f -+ && boardrev == 0x10 -+ && boardflags == 0 -+ && strev == 0x11) { -+ /* Simpletech Simpleshare */ -+ return ROUTER_SIMPLETECH_SIMPLESHARE; -+ } -+ -+ return 0; -+} -+ -+static int parse_bcm47xx_partitions(struct mtd_info *mtd, -+ struct mtd_partition **pparts, -+// struct mtd_part_parser_data *data) -+ unsigned long data) -+{ -+ int cfe_size; -+ int dual_image_offset = 0; -+ /* e.g Netgear 0x003e0000-0x003f0000 : "board_data", we exclude this -+ * part from our mapping to prevent overwriting len/checksum on e.g. -+ * Netgear WGR614v8/L/WW -+ */ -+ int custom_data_size = 0; -+ -+ if ((cfe_size = find_cfe_size(mtd)) < 0) -+ return 0; -+ -+ /* boot loader */ -+ bcm47xx_parts[0].offset = 0; -+ bcm47xx_parts[0].size = cfe_size; -+ -+ /* nvram */ -+ if (cfe_size != 384 * 1024) { -+ -+ switch (get_router()) { -+ case ROUTER_NETGEAR_WGR614L: -+ case ROUTER_NETGEAR_WNR834B: -+ case ROUTER_NETGEAR_WNDR3300: -+ case ROUTER_NETGEAR_WNR3500L: -+ /* Netgear: checksum is @ 0x003AFFF8 for 4M flash or checksum -+ * is @ 0x007AFFF8 for 8M flash -+ */ -+ custom_data_size = mtd->erasesize; -+ -+ bcm47xx_parts[3].offset = mtd->size - roundup(NVRAM_SPACE, mtd->erasesize); -+ bcm47xx_parts[3].size = roundup(NVRAM_SPACE, mtd->erasesize); -+ -+ /* Place CFE board_data into a partition */ -+ bcm47xx_parts[4].name = "board_data"; -+ bcm47xx_parts[4].offset = bcm47xx_parts[3].offset - custom_data_size; -+ bcm47xx_parts[4].size = custom_data_size; -+ break; -+ -+ case ROUTER_SIMPLETECH_SIMPLESHARE: -+ /* Fixup Simpletech Simple share nvram */ -+ -+ pr_notice("Setting up simpletech nvram\n"); -+ custom_data_size = mtd->erasesize; -+ -+ bcm47xx_parts[3].offset = mtd->size - roundup(NVRAM_SPACE, mtd->erasesize) * 2; -+ bcm47xx_parts[3].size = roundup(NVRAM_SPACE, mtd->erasesize); -+ -+ /* Place backup nvram into a partition */ -+ bcm47xx_parts[4].name = "nvram_copy"; -+ bcm47xx_parts[4].offset = mtd->size - roundup(NVRAM_SPACE, mtd->erasesize); -+ bcm47xx_parts[4].size = roundup(NVRAM_SPACE, mtd->erasesize); -+ break; -+ -+ default: -+ bcm47xx_parts[3].offset = mtd->size - roundup(NVRAM_SPACE, mtd->erasesize); -+ bcm47xx_parts[3].size = roundup(NVRAM_SPACE, mtd->erasesize); -+ } -+ -+ } else { -+ /* nvram (old 128kb config partition on netgear wgt634u) */ -+ bcm47xx_parts[3].offset = bcm47xx_parts[0].size; -+ bcm47xx_parts[3].size = roundup(NVRAM_SPACE, mtd->erasesize); -+ } -+ -+ /* dual image offset*/ -+ pr_notice("Looking for dual image\n"); -+ dual_image_offset=find_dual_image_off(mtd); -+ /* linux (kernel and rootfs) */ -+ if (cfe_size != 384 * 1024) { -+ if (get_router() == ROUTER_SIMPLETECH_SIMPLESHARE) { -+ bcm47xx_parts[1].offset = bcm47xx_parts[0].size; -+ bcm47xx_parts[1].size = bcm47xx_parts[4].offset - dual_image_offset - -+ bcm47xx_parts[1].offset - custom_data_size; -+ } else { -+ bcm47xx_parts[1].offset = bcm47xx_parts[0].size; -+ bcm47xx_parts[1].size = bcm47xx_parts[3].offset - dual_image_offset - -+ bcm47xx_parts[1].offset - custom_data_size; -+ } -+ } else { -+ /* do not count the elf loader, which is on one block */ -+ bcm47xx_parts[1].offset = bcm47xx_parts[0].size + -+ bcm47xx_parts[3].size + mtd->erasesize; -+ bcm47xx_parts[1].size = mtd->size - -+ bcm47xx_parts[0].size - -+ (2*bcm47xx_parts[3].size) - -+ mtd->erasesize - custom_data_size; -+ } -+ -+ /* find and size rootfs */ -+ find_root(mtd, &bcm47xx_parts[2]); -+ bcm47xx_parts[2].size = mtd->size - dual_image_offset - -+ bcm47xx_parts[2].offset - -+ bcm47xx_parts[3].size - custom_data_size; -+ *pparts = bcm47xx_parts; -+ return bcm47xx_parts[4].name == NULL ? 4 : 5; -+} -+ -+static struct mtd_part_parser bcm47xx_parser = { -+ .owner = THIS_MODULE, -+ .parse_fn = parse_bcm47xx_partitions, -+ .name = "bcm47xx", -+}; -+ -+static int __init bcm47xx_parser_init(void) -+{ -+ return register_mtd_parser(&bcm47xx_parser); -+} -+ -+static void __exit bcm47xx_parser_exit(void) -+{ -+ deregister_mtd_parser(&bcm47xx_parser); -+} -+ -+module_init(bcm47xx_parser_init); -+module_exit(bcm47xx_parser_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("Parsing code for flash partitions on bcm47xx SoCs"); diff --git a/target/linux/brcm47xx/patches-3.0/0014-ssb-move-flash-to-chipcommon.patch b/target/linux/brcm47xx/patches-3.0/0014-ssb-move-flash-to-chipcommon.patch new file mode 100644 index 0000000000..0d478883f3 --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0014-ssb-move-flash-to-chipcommon.patch @@ -0,0 +1,143 @@ +From be495ba9c365a31cf6a9fa0f67df9a9a9e0f1a1f Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sat, 23 Jul 2011 23:57:06 +0200 +Subject: [PATCH 14/26] ssb: move flash to chipcommon + + +Signed-off-by: Hauke Mehrtens +--- + arch/mips/bcm47xx/nvram.c | 8 +++--- + arch/mips/bcm47xx/wgt634u.c | 8 +++--- + drivers/ssb/driver_mipscore.c | 31 +++++++++++++++++++--------- + include/linux/ssb/ssb_driver_chipcommon.h | 18 ++++++++++++++++ + include/linux/ssb/ssb_driver_mips.h | 4 --- + 5 files changed, 47 insertions(+), 22 deletions(-) + +--- a/arch/mips/bcm47xx/nvram.c ++++ b/arch/mips/bcm47xx/nvram.c +@@ -27,7 +27,7 @@ static char nvram_buf[NVRAM_SPACE]; + static void early_nvram_init(void) + { + #ifdef CONFIG_BCM47XX_SSB +- struct ssb_mipscore *mcore_ssb; ++ struct ssb_chipcommon *ssb_cc; + #endif + #ifdef CONFIG_BCM47XX_BCMA + struct bcma_drv_cc *bcma_cc; +@@ -42,9 +42,9 @@ static void early_nvram_init(void) + switch (bcm47xx_bus_type) { + #ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: +- mcore_ssb = &bcm47xx_bus.ssb.mipscore; +- base = mcore_ssb->flash_window; +- lim = mcore_ssb->flash_window_size; ++ ssb_cc = &bcm47xx_bus.ssb.chipco; ++ base = ssb_cc->pflash.window; ++ lim = ssb_cc->pflash.window_size; + break; + #endif + #ifdef CONFIG_BCM47XX_BCMA +--- a/arch/mips/bcm47xx/wgt634u.c ++++ b/arch/mips/bcm47xx/wgt634u.c +@@ -156,10 +156,10 @@ static int __init wgt634u_init(void) + SSB_CHIPCO_IRQ_GPIO); + } + +- wgt634u_flash_data.width = mcore->flash_buswidth; +- wgt634u_flash_resource.start = mcore->flash_window; +- wgt634u_flash_resource.end = mcore->flash_window +- + mcore->flash_window_size ++ wgt634u_flash_data.width = mcore->pflash.buswidth; ++ wgt634u_flash_resource.start = mcore->pflash.window; ++ wgt634u_flash_resource.end = mcore->pflash.window ++ + mcore->pflash.window_size + - 1; + return platform_add_devices(wgt634u_devices, + ARRAY_SIZE(wgt634u_devices)); +--- a/drivers/ssb/driver_mipscore.c ++++ b/drivers/ssb/driver_mipscore.c +@@ -190,16 +190,27 @@ static void ssb_mips_flash_detect(struct + { + struct ssb_bus *bus = mcore->dev->bus; + +- mcore->flash_buswidth = 2; +- if (bus->chipco.dev) { +- mcore->flash_window = 0x1c000000; +- mcore->flash_window_size = 0x02000000; +- if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG) +- & SSB_CHIPCO_CFG_DS16) == 0) +- mcore->flash_buswidth = 1; +- } else { +- mcore->flash_window = 0x1fc00000; +- mcore->flash_window_size = 0x00400000; ++ switch (bus->chipco.capabilities & SSB_CHIPCO_CAP_FLASHT) { ++ case SSB_CHIPCO_FLASHT_STSER: ++ case SSB_CHIPCO_FLASHT_ATSER: ++ pr_info("serial flash not supported.\n"); ++ break; ++ case SSB_CHIPCO_FLASHT_PARA: ++ pr_info("found parallel flash.\n"); ++ bus->chipco.flash_type = SSB_PFLASH; ++ bus->chipco.pflash.buswidth = 2; ++ if (bus->chipco.dev) { ++ bus->chipco.pflash.window = 0x1c000000; ++ bus->chipco.pflash.window_size = 0x02000000; ++ if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG) ++ & SSB_CHIPCO_CFG_DS16) == 0) ++ bus->chipco.pflash.buswidth = 1; ++ } else { ++ bus->chipco.pflash.window = 0x1fc00000; ++ bus->chipco.pflash.window_size = 0x00400000; ++ } ++ default: ++ pr_err("flash not supported.\n"); + } + } + +--- a/include/linux/ssb/ssb_driver_chipcommon.h ++++ b/include/linux/ssb/ssb_driver_chipcommon.h +@@ -582,6 +582,18 @@ struct ssb_chipcommon_pmu { + u32 crystalfreq; /* The active crystal frequency (in kHz) */ + }; + ++#ifdef CONFIG_SSB_DRIVER_MIPS ++enum ssb_flash_type { ++ SSB_PFLASH, ++}; ++ ++struct ssb_pflash { ++ u8 buswidth; ++ u32 window; ++ u32 window_size; ++}; ++#endif /* CONFIG_SSB_DRIVER_MIPS */ ++ + struct ssb_chipcommon { + struct ssb_device *dev; + u32 capabilities; +@@ -589,6 +601,12 @@ struct ssb_chipcommon { + /* Fast Powerup Delay constant */ + u16 fast_pwrup_delay; + struct ssb_chipcommon_pmu pmu; ++#ifdef CONFIG_SSB_DRIVER_MIPS ++ enum ssb_flash_type flash_type; ++ union { ++ struct ssb_pflash pflash; ++ }; ++#endif /* CONFIG_SSB_DRIVER_MIPS */ + }; + + static inline bool ssb_chipco_available(struct ssb_chipcommon *cc) +--- a/include/linux/ssb/ssb_driver_mips.h ++++ b/include/linux/ssb/ssb_driver_mips.h +@@ -19,10 +19,6 @@ struct ssb_mipscore { + + int nr_serial_ports; + struct ssb_serial_port serial_ports[4]; +- +- u8 flash_buswidth; +- u32 flash_window; +- u32 flash_window_size; + }; + + extern void ssb_mipscore_init(struct ssb_mipscore *mcore); diff --git a/target/linux/brcm47xx/patches-3.0/0015-mtd-bcm47xx-add-parallel-flash-driver.patch b/target/linux/brcm47xx/patches-3.0/0015-mtd-bcm47xx-add-parallel-flash-driver.patch deleted file mode 100644 index b70140f1b4..0000000000 --- a/target/linux/brcm47xx/patches-3.0/0015-mtd-bcm47xx-add-parallel-flash-driver.patch +++ /dev/null @@ -1,238 +0,0 @@ -From 941c7a12af5d985c9dabc6813db3b75908bd619c Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens -Date: Sun, 17 Jul 2011 14:55:18 +0200 -Subject: [PATCH 15/22] mtd: bcm47xx: add parallel flash driver - - -Signed-off-by: Hauke Mehrtens ---- - drivers/mtd/maps/Kconfig | 9 ++ - drivers/mtd/maps/Makefile | 1 + - drivers/mtd/maps/bcm47xx-pflash.c | 196 +++++++++++++++++++++++++++++++++++++ - 3 files changed, 206 insertions(+), 0 deletions(-) - create mode 100644 drivers/mtd/maps/bcm47xx-pflash.c - ---- a/drivers/mtd/maps/Kconfig -+++ b/drivers/mtd/maps/Kconfig -@@ -264,6 +264,15 @@ config MTD_LANTIQ - help - Support for NOR flash attached to the Lantiq SoC's External Bus Unit. - -+config MTD_BCM47XX_PFLASH -+ tristate "bcm47xx parallel flash support" -+ default y -+ depends on BCM47XX -+ select MTD_PARTITIONS -+ select MTD_BCM47XX_PARTS -+ help -+ Support for bcm47xx parallel flash -+ - config MTD_DILNETPC - tristate "CFI Flash device mapped on DIL/Net PC" - depends on X86 && MTD_CFI_INTELEXT && BROKEN ---- a/drivers/mtd/maps/Makefile -+++ b/drivers/mtd/maps/Makefile -@@ -60,3 +60,4 @@ obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr - obj-$(CONFIG_MTD_BCM963XX) += bcm963xx-flash.o - obj-$(CONFIG_MTD_LATCH_ADDR) += latch-addr-flash.o - obj-$(CONFIG_MTD_LANTIQ) += lantiq-flash.o -+obj-$(CONFIG_MTD_BCM47XX_PFLASH)+= bcm47xx-pflash.o ---- /dev/null -+++ b/drivers/mtd/maps/bcm47xx-pflash.c -@@ -0,0 +1,196 @@ -+/* -+ * Copyright (C) 2006 Felix Fietkau -+ * Copyright (C) 2005 Waldemar Brodkorb -+ * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org) -+ * -+ * original functions for finding root filesystem from Mike Baker -+ * -+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN -+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * 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., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ * -+ * Copyright 2001-2003, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ * Flash mapping for BCM947XX boards -+ */ -+ -+#define pr_fmt(fmt) "bcm47xx_pflash: " fmt -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define WINDOW_ADDR 0x1fc00000 -+#define WINDOW_SIZE 0x400000 -+#define BUSWIDTH 2 -+ -+static struct mtd_info *bcm47xx_mtd; -+ -+static void bcm47xx_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) -+{ -+ if (len==1) { -+ memcpy_fromio(to, map->virt + from, len); -+ } else { -+ int i; -+ u16 *dest = (u16 *) to; -+ u16 *src = (u16 *) (map->virt + from); -+ for (i = 0; i < (len / 2); i++) { -+ dest[i] = src[i]; -+ } -+ if (len & 1) -+ *((u8 *)dest+len-1) = src[i] & 0xff; -+ } -+} -+ -+static struct map_info bcm47xx_map = { -+ name: "Physically mapped flash", -+ size: WINDOW_SIZE, -+ bankwidth: BUSWIDTH, -+ phys: WINDOW_ADDR, -+}; -+ -+static const char *probes[] = { "bcm47xx", NULL }; -+ -+static int bcm47xx_mtd_probe(struct platform_device *pdev) -+{ -+#ifdef CONFIG_BCM47XX_SSB -+ struct ssb_mipscore *mcore_ssb; -+#endif -+#ifdef CONFIG_BCM47XX_BCMA -+ struct bcma_drv_cc *bcma_cc; -+#endif -+ int ret = 0; -+ struct mtd_partition *partitions = NULL; -+ int num_partitions = 0; -+ -+ switch (bcm47xx_active_bus_type) { -+#ifdef CONFIG_BCM47XX_SSB -+ case BCM47XX_BUS_TYPE_SSB: -+ mcore_ssb = &bcm47xx_bus.ssb.mipscore; -+ bcm47xx_map.phys = mcore_ssb->flash_window; -+ bcm47xx_map.size = mcore_ssb->flash_window_size; -+ bcm47xx_map.bankwidth = mcore_ssb->flash_buswidth; -+ break; -+#endif -+#ifdef CONFIG_BCM47XX_BCMA -+ case BCM47XX_BUS_TYPE_BCMA: -+ bcma_cc = &bcm47xx_bus.bcma.bus.drv_cc; -+ if (bcma_cc->flash_type != BCMA_PFLASH) -+ return -ENODEV; -+ -+ bcm47xx_map.phys = bcma_cc->flash.pflash.window; -+ bcm47xx_map.size = bcma_cc->flash.pflash.window_size; -+ bcm47xx_map.bankwidth = bcma_cc->flash.pflash.buswidth; -+ break; -+#endif -+ } -+ -+ pr_notice("flash init: 0x%08x 0x%08lx\n", bcm47xx_map.phys, bcm47xx_map.size); -+ bcm47xx_map.virt = ioremap_nocache(bcm47xx_map.phys, bcm47xx_map.size); -+ -+ if (!bcm47xx_map.virt) { -+ pr_err("Failed to ioremap\n"); -+ return -EIO; -+ } -+ -+ simple_map_init(&bcm47xx_map); -+ /* override copy_from routine */ -+ bcm47xx_map.copy_from = bcm47xx_map_copy_from; -+ -+ bcm47xx_mtd = do_map_probe("cfi_probe", &bcm47xx_map); -+ if (!bcm47xx_mtd) { -+ pr_err("Failed to do_map_probe\n"); -+ ret = -ENXIO; -+ goto err_unmap; -+ } -+ bcm47xx_mtd->owner = THIS_MODULE; -+ -+ pr_notice("Flash device: 0x%lx at 0x%x\n", bcm47xx_map.size, WINDOW_ADDR); -+ -+ num_partitions = parse_mtd_partitions(bcm47xx_mtd, probes, &partitions, 0); -+ if (num_partitions < 0) { -+ ret = num_partitions; -+ goto err_unmap; -+ } -+ -+ ret = mtd_device_register(bcm47xx_mtd, partitions, num_partitions); -+ -+// ret = mtd_device_parse_register(bcm47xx_mtd, "bcm47xx", NULL, NULL, 0); -+ -+ if (ret) { -+ pr_err("Flash: mtd_device_register failed\n"); -+ goto err_destroy; -+ } -+ return 0; -+ -+err_destroy: -+ map_destroy(bcm47xx_mtd); -+err_unmap: -+ iounmap(bcm47xx_map.virt); -+ return ret; -+} -+ -+static int __devexit bcm47xx_mtd_remove(struct platform_device *pdev) -+{ -+ mtd_device_unregister(bcm47xx_mtd); -+ map_destroy(bcm47xx_mtd); -+ iounmap(bcm47xx_map.virt); -+ return 0; -+} -+ -+static struct platform_driver bcm47xx_mtd_driver = { -+ .remove = __devexit_p(bcm47xx_mtd_remove), -+ .driver = { -+ .name = "bcm47xx_pflash", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static int __init init_bcm47xx_mtd(void) -+{ -+ int ret = platform_driver_probe(&bcm47xx_mtd_driver, bcm47xx_mtd_probe); -+ -+ if (ret) -+ pr_err("error registering platform driver: %i\n", ret); -+ return ret; -+} -+ -+static void __exit exit_bcm47xx_mtd(void) -+{ -+ platform_driver_unregister(&bcm47xx_mtd_driver); -+} -+ -+module_init(init_bcm47xx_mtd); -+module_exit(exit_bcm47xx_mtd); -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("BCM47XX parallel flash driver"); diff --git a/target/linux/brcm47xx/patches-3.0/0015-ssb-add-serial-flash-support.patch b/target/linux/brcm47xx/patches-3.0/0015-ssb-add-serial-flash-support.patch new file mode 100644 index 0000000000..1e7762b4b2 --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0015-ssb-add-serial-flash-support.patch @@ -0,0 +1,697 @@ +From 980da78179592a3f5f99168bc5af415835aa8c13 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sun, 24 Jul 2011 20:20:36 +0200 +Subject: [PATCH 15/26] ssb: add serial flash support + + +Signed-off-by: Hauke Mehrtens +--- + drivers/ssb/Kconfig | 6 + + drivers/ssb/Makefile | 1 + + drivers/ssb/driver_chipcommon_sflash.c | 556 +++++++++++++++++++++++++++++ + drivers/ssb/driver_mipscore.c | 6 + + drivers/ssb/ssb_private.h | 4 + + include/linux/ssb/ssb_driver_chipcommon.h | 30 ++- + 6 files changed, 601 insertions(+), 2 deletions(-) + create mode 100644 drivers/ssb/driver_chipcommon_sflash.c + +--- a/drivers/ssb/Kconfig ++++ b/drivers/ssb/Kconfig +@@ -137,6 +137,12 @@ config SSB_DRIVER_MIPS + + If unsure, say N + ++config SSB_SFLASH ++ bool ++ depends on SSB_DRIVER_MIPS ++ default y ++ ++ + # Assumption: We are on embedded, if we compile the MIPS core. + config SSB_EMBEDDED + bool +--- a/drivers/ssb/Makefile ++++ b/drivers/ssb/Makefile +@@ -11,6 +11,7 @@ ssb-$(CONFIG_SSB_SDIOHOST) += sdio.o + # built-in drivers + ssb-y += driver_chipcommon.o + ssb-y += driver_chipcommon_pmu.o ++ssb-$(CONFIG_SSB_SFLASH) += driver_chipcommon_sflash.o + ssb-$(CONFIG_SSB_DRIVER_MIPS) += driver_mipscore.o + ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o + ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o +--- /dev/null ++++ b/drivers/ssb/driver_chipcommon_sflash.c +@@ -0,0 +1,556 @@ ++/* ++ * Broadcom SiliconBackplane chipcommon serial flash interface ++ * ++ * Copyright 2011, Jonas Gorski ++ * Copyright 2010, Broadcom Corporation ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++#include ++#include ++#include ++ ++#include "ssb_private.h" ++ ++#define NUM_RETRIES 3 ++ ++ ++/* Issue a serial flash command */ ++static inline void ssb_sflash_cmd(struct ssb_chipcommon *cc, u32 opcode) ++{ ++ chipco_write32(cc, SSB_CHIPCO_FLASHCTL, ++ SSB_CHIPCO_FLASHCTL_START | opcode); ++ while (chipco_read32(cc, SSB_CHIPCO_FLASHCTL) ++ & SSB_CHIPCO_FLASHCTL_BUSY) ++ ; ++} ++ ++ ++static inline void ssb_sflash_write_u8(struct ssb_chipcommon *cc, ++ u32 offset, u8 byte) ++{ ++ chipco_write32(cc, SSB_CHIPCO_FLASHADDR, offset); ++ chipco_write32(cc, SSB_CHIPCO_FLASHDATA, byte); ++} ++ ++/* Initialize serial flash access */ ++int ssb_sflash_init(struct ssb_chipcommon *cc) ++{ ++ u32 id, id2; ++ ++ memset(&cc->sflash, 0, sizeof(struct ssb_sflash)); ++ ++ switch (cc->capabilities & SSB_CHIPCO_CAP_FLASHT) { ++ case SSB_CHIPCO_FLASHT_STSER: ++ /* Probe for ST chips */ ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_DP); ++ chipco_write32(cc, SSB_CHIPCO_FLASHADDR, 0); ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_RES); ++ id = chipco_read32(cc, SSB_CHIPCO_FLASHDATA); ++ cc->sflash.blocksize = 64 * 1024; ++ switch (id) { ++ case 0x11: ++ /* ST M25P20 2 Mbit Serial Flash */ ++ cc->sflash.numblocks = 4; ++ break; ++ case 0x12: ++ /* ST M25P40 4 Mbit Serial Flash */ ++ cc->sflash.numblocks = 8; ++ break; ++ case 0x13: ++ /* ST M25P80 8 Mbit Serial Flash */ ++ cc->sflash.numblocks = 16; ++ break; ++ case 0x14: ++ /* ST M25P16 16 Mbit Serial Flash */ ++ cc->sflash.numblocks = 32; ++ break; ++ case 0x15: ++ /* ST M25P32 32 Mbit Serial Flash */ ++ cc->sflash.numblocks = 64; ++ break; ++ case 0x16: ++ /* ST M25P64 64 Mbit Serial Flash */ ++ cc->sflash.numblocks = 128; ++ break; ++ case 0x17: ++ /* ST M25FL128 128 Mbit Serial Flash */ ++ cc->sflash.numblocks = 256; ++ break; ++ case 0xbf: ++ /* All of the following flashes are SST with ++ * 4KB subsectors. Others should be added but ++ * We'll have to revamp the way we identify them ++ * since RES is not eough to disambiguate them. ++ */ ++ cc->sflash.blocksize = 4 * 1024; ++ chipco_write32(cc, SSB_CHIPCO_FLASHADDR, 1); ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_RES); ++ id2 = chipco_read32(cc, SSB_CHIPCO_FLASHDATA); ++ switch (id2) { ++ case 1: ++ /* SST25WF512 512 Kbit Serial Flash */ ++ case 0x48: ++ /* SST25VF512 512 Kbit Serial Flash */ ++ cc->sflash.numblocks = 16; ++ break; ++ case 2: ++ /* SST25WF010 1 Mbit Serial Flash */ ++ case 0x49: ++ /* SST25VF010 1 Mbit Serial Flash */ ++ cc->sflash.numblocks = 32; ++ break; ++ case 3: ++ /* SST25WF020 2 Mbit Serial Flash */ ++ case 0x43: ++ /* SST25VF020 2 Mbit Serial Flash */ ++ cc->sflash.numblocks = 64; ++ break; ++ case 4: ++ /* SST25WF040 4 Mbit Serial Flash */ ++ case 0x44: ++ /* SST25VF040 4 Mbit Serial Flash */ ++ case 0x8d: ++ /* SST25VF040B 4 Mbit Serial Flash */ ++ cc->sflash.numblocks = 128; ++ break; ++ case 5: ++ /* SST25WF080 8 Mbit Serial Flash */ ++ case 0x8e: ++ /* SST25VF080B 8 Mbit Serial Flash */ ++ cc->sflash.numblocks = 256; ++ break; ++ case 0x41: ++ /* SST25VF016 16 Mbit Serial Flash */ ++ cc->sflash.numblocks = 512; ++ break; ++ case 0x4a: ++ /* SST25VF032 32 Mbit Serial Flash */ ++ cc->sflash.numblocks = 1024; ++ break; ++ case 0x4b: ++ /* SST25VF064 64 Mbit Serial Flash */ ++ cc->sflash.numblocks = 2048; ++ break; ++ } ++ break; ++ } ++ break; ++ ++ case SSB_CHIPCO_FLASHT_ATSER: ++ /* Probe for Atmel chips */ ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_AT_STATUS); ++ id = chipco_read32(cc, SSB_CHIPCO_FLASHDATA) & 0x3c; ++ switch (id) { ++ case 0xc: ++ /* Atmel AT45DB011 1Mbit Serial Flash */ ++ cc->sflash.blocksize = 256; ++ cc->sflash.numblocks = 512; ++ break; ++ case 0x14: ++ /* Atmel AT45DB021 2Mbit Serial Flash */ ++ cc->sflash.blocksize = 256; ++ cc->sflash.numblocks = 1024; ++ break; ++ case 0x1c: ++ /* Atmel AT45DB041 4Mbit Serial Flash */ ++ cc->sflash.blocksize = 256; ++ cc->sflash.numblocks = 2048; ++ break; ++ case 0x24: ++ /* Atmel AT45DB081 8Mbit Serial Flash */ ++ cc->sflash.blocksize = 256; ++ cc->sflash.numblocks = 4096; ++ break; ++ case 0x2c: ++ /* Atmel AT45DB161 16Mbit Serial Flash */ ++ cc->sflash.blocksize = 512; ++ cc->sflash.numblocks = 4096; ++ break; ++ case 0x34: ++ /* Atmel AT45DB321 32Mbit Serial Flash */ ++ cc->sflash.blocksize = 512; ++ cc->sflash.numblocks = 8192; ++ break; ++ case 0x3c: ++ /* Atmel AT45DB642 64Mbit Serial Flash */ ++ cc->sflash.blocksize = 1024; ++ cc->sflash.numblocks = 8192; ++ break; ++ } ++ break; ++ } ++ ++ cc->sflash.size = cc->sflash.blocksize * cc->sflash.numblocks; ++ ++ return cc->sflash.size ? 0 : -ENODEV; ++} ++ ++/* Read len bytes starting at offset into buf. Returns number of bytes read. */ ++int ssb_sflash_read(struct ssb_chipcommon *cc, u32 offset, u32 len, ++ u8 *buf) ++{ ++ u8 *from, *to; ++ u32 cnt, i; ++ ++ if (!len) ++ return 0; ++ ++ if ((offset + len) > cc->sflash.size) ++ return -EINVAL; ++ ++ if ((len >= 4) && (offset & 3)) ++ cnt = 4 - (offset & 3); ++ else if ((len >= 4) && ((u32)buf & 3)) ++ cnt = 4 - ((u32)buf & 3); ++ else ++ cnt = len; ++ ++ ++ if (cc->dev->id.revision == 12) ++ from = (u8 *)KSEG1ADDR(SSB_FLASH2 + offset); ++ else ++ from = (u8 *)KSEG0ADDR(SSB_FLASH2 + offset); ++ ++ to = (u8 *)buf; ++ ++ if (cnt < 4) { ++ for (i = 0; i < cnt; i++) { ++ *to = readb(from); ++ from++; ++ to++; ++ } ++ return cnt; ++ } ++ ++ while (cnt >= 4) { ++ *(u32 *)to = readl(from); ++ from += 4; ++ to += 4; ++ cnt -= 4; ++ } ++ ++ return len - cnt; ++} ++ ++/* Poll for command completion. Returns zero when complete. */ ++int ssb_sflash_poll(struct ssb_chipcommon *cc, u32 offset) ++{ ++ if (offset >= cc->sflash.size) ++ return -22; ++ ++ switch (cc->capabilities & SSB_CHIPCO_CAP_FLASHT) { ++ case SSB_CHIPCO_FLASHT_STSER: ++ /* Check for ST Write In Progress bit */ ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_RDSR); ++ return chipco_read32(cc, SSB_CHIPCO_FLASHDATA) ++ & SSB_CHIPCO_FLASHSTA_ST_WIP; ++ case SSB_CHIPCO_FLASHT_ATSER: ++ /* Check for Atmel Ready bit */ ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_AT_STATUS); ++ return !(chipco_read32(cc, SSB_CHIPCO_FLASHDATA) ++ & SSB_CHIPCO_FLASHSTA_AT_READY); ++ } ++ ++ return 0; ++} ++ ++ ++static int sflash_st_write(struct ssb_chipcommon *cc, u32 offset, u32 len, ++ const u8 *buf) ++{ ++ struct ssb_bus *bus = cc->dev->bus; ++ int ret = 0; ++ bool is4712b0 = (bus->chip_id == 0x4712) && (bus->chip_rev == 3); ++ u32 mask; ++ ++ ++ /* Enable writes */ ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_WREN); ++ if (is4712b0) { ++ mask = 1 << 14; ++ ssb_sflash_write_u8(cc, offset, *buf++); ++ /* Set chip select */ ++ chipco_set32(cc, SSB_CHIPCO_GPIOOUT, mask); ++ /* Issue a page program with the first byte */ ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_PP); ++ ret = 1; ++ offset++; ++ len--; ++ while (len > 0) { ++ if ((offset & 255) == 0) { ++ /* Page boundary, drop cs and return */ ++ chipco_mask32(cc, SSB_CHIPCO_GPIOOUT, ~mask); ++ udelay(1); ++ if (!ssb_sflash_poll(cc, offset)) { ++ /* Flash rejected command */ ++ return -EAGAIN; ++ } ++ return ret; ++ } else { ++ /* Write single byte */ ++ ssb_sflash_cmd(cc, *buf++); ++ } ++ ret++; ++ offset++; ++ len--; ++ } ++ /* All done, drop cs */ ++ chipco_mask32(cc, SSB_CHIPCO_GPIOOUT, ~mask); ++ udelay(1); ++ if (!ssb_sflash_poll(cc, offset)) { ++ /* Flash rejected command */ ++ return -EAGAIN; ++ } ++ } else if (cc->dev->id.revision >= 20) { ++ ssb_sflash_write_u8(cc, offset, *buf++); ++ /* Issue a page program with CSA bit set */ ++ ssb_sflash_cmd(cc, ++ SSB_CHIPCO_FLASHCTL_ST_CSA | ++ SSB_CHIPCO_FLASHCTL_ST_PP); ++ ret = 1; ++ offset++; ++ len--; ++ while (len > 0) { ++ if ((offset & 255) == 0) { ++ /* Page boundary, poll droping cs and return */ ++ chipco_write32(cc, SSB_CHIPCO_FLASHCTL, 0); ++ udelay(1); ++ if (!ssb_sflash_poll(cc, offset)) { ++ /* Flash rejected command */ ++ return -EAGAIN; ++ } ++ return ret; ++ } else { ++ /* Write single byte */ ++ ssb_sflash_cmd(cc, ++ SSB_CHIPCO_FLASHCTL_ST_CSA | ++ *buf++); ++ } ++ ret++; ++ offset++; ++ len--; ++ } ++ /* All done, drop cs & poll */ ++ chipco_write32(cc, SSB_CHIPCO_FLASHCTL, 0); ++ udelay(1); ++ if (!ssb_sflash_poll(cc, offset)) { ++ /* Flash rejected command */ ++ return -EAGAIN; ++ } ++ } else { ++ ret = 1; ++ ssb_sflash_write_u8(cc, offset, *buf); ++ /* Page program */ ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_PP); ++ } ++ return ret; ++} ++ ++static int sflash_at_write(struct ssb_chipcommon *cc, u32 offset, u32 len, ++ const u8 *buf) ++{ ++ struct ssb_sflash *sfl = &cc->sflash; ++ u32 page, byte, mask; ++ int ret = 0; ++ mask = sfl->blocksize - 1; ++ page = (offset & ~mask) << 1; ++ byte = offset & mask; ++ /* Read main memory page into buffer 1 */ ++ if (byte || (len < sfl->blocksize)) { ++ int i = 100; ++ chipco_write32(cc, SSB_CHIPCO_FLASHADDR, page); ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_AT_BUF1_LOAD); ++ /* 250 us for AT45DB321B */ ++ while (i > 0 && ssb_sflash_poll(cc, offset)) { ++ udelay(10); ++ i--; ++ } ++ BUG_ON(!ssb_sflash_poll(cc, offset)); ++ } ++ /* Write into buffer 1 */ ++ for (ret = 0; (ret < (int)len) && (byte < sfl->blocksize); ret++) { ++ ssb_sflash_write_u8(cc, byte++, *buf++); ++ ssb_sflash_cmd(cc, ++ SSB_CHIPCO_FLASHCTL_AT_BUF1_WRITE); ++ } ++ /* Write buffer 1 into main memory page */ ++ chipco_write32(cc, SSB_CHIPCO_FLASHADDR, page); ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_AT_BUF1_PROGRAM); ++ ++ return ret; ++} ++ ++/* Write len bytes starting at offset into buf. Returns number of bytes ++ * written. Caller should poll for completion. ++ */ ++int ssb_sflash_write(struct ssb_chipcommon *cc, u32 offset, u32 len, ++ const u8 *buf) ++{ ++ struct ssb_sflash *sfl; ++ int ret = 0, tries = NUM_RETRIES; ++ ++ if (!len) ++ return 0; ++ ++ if ((offset + len) > cc->sflash.size) ++ return -EINVAL; ++ ++ sfl = &cc->sflash; ++ switch (cc->capabilities & SSB_CHIPCO_CAP_FLASHT) { ++ case SSB_CHIPCO_FLASHT_STSER: ++ do { ++ ret = sflash_st_write(cc, offset, len, buf); ++ tries--; ++ } while (ret == -EAGAIN && tries > 0); ++ ++ if (ret == -EAGAIN && tries == 0) { ++ pr_info("ST Flash rejected write\n"); ++ ret = -EIO; ++ } ++ break; ++ case SSB_CHIPCO_FLASHT_ATSER: ++ ret = sflash_at_write(cc, offset, len, buf); ++ break; ++ } ++ ++ return ret; ++} ++ ++/* Erase a region. Returns number of bytes scheduled for erasure. ++ * Caller should poll for completion. ++ */ ++int ssb_sflash_erase(struct ssb_chipcommon *cc, u32 offset) ++{ ++ struct ssb_sflash *sfl; ++ ++ if (offset >= cc->sflash.size) ++ return -EINVAL; ++ ++ sfl = &cc->sflash; ++ switch (cc->capabilities & SSB_CHIPCO_CAP_FLASHT) { ++ case SSB_CHIPCO_FLASHT_STSER: ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_WREN); ++ chipco_write32(cc, SSB_CHIPCO_FLASHADDR, offset); ++ /* Newer flashes have "sub-sectors" which can be erased independently ++ * with a new command: ST_SSE. The ST_SE command erases 64KB just as ++ * before. ++ */ ++ ssb_sflash_cmd(cc, (sfl->blocksize < (64 * 1024)) ? SSB_CHIPCO_FLASHCTL_ST_SSE : SSB_CHIPCO_FLASHCTL_ST_SE); ++ return sfl->blocksize; ++ case SSB_CHIPCO_FLASHT_ATSER: ++ chipco_write32(cc, SSB_CHIPCO_FLASHADDR, offset << 1); ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_AT_PAGE_ERASE); ++ return sfl->blocksize; ++ } ++ ++ return 0; ++} ++ ++/* ++ * writes the appropriate range of flash, a NULL buf simply erases ++ * the region of flash ++ */ ++int ssb_sflash_commit(struct ssb_chipcommon *cc, u32 offset, u32 len, ++ const u8 *buf) ++{ ++ struct ssb_sflash *sfl; ++ u8 *block = NULL, *cur_ptr, *blk_ptr; ++ u32 blocksize = 0, mask, cur_offset, cur_length, cur_retlen, remainder; ++ u32 blk_offset, blk_len, copied; ++ int bytes, ret = 0; ++ ++ /* Check address range */ ++ if (len <= 0) ++ return 0; ++ ++ sfl = &cc->sflash; ++ if ((offset + len) > sfl->size) ++ return -EINVAL; ++ ++ blocksize = sfl->blocksize; ++ mask = blocksize - 1; ++ ++ /* Allocate a block of mem */ ++ block = kmalloc(blocksize, GFP_KERNEL); ++ if (!block) ++ return -ENOMEM; ++ ++ while (len) { ++ /* Align offset */ ++ cur_offset = offset & ~mask; ++ cur_length = blocksize; ++ cur_ptr = block; ++ ++ remainder = blocksize - (offset & mask); ++ if (len < remainder) ++ cur_retlen = len; ++ else ++ cur_retlen = remainder; ++ ++ /* buf == NULL means erase only */ ++ if (buf) { ++ /* Copy existing data into holding block if necessary */ ++ if ((offset & mask) || (len < blocksize)) { ++ blk_offset = cur_offset; ++ blk_len = cur_length; ++ blk_ptr = cur_ptr; ++ ++ /* Copy entire block */ ++ while (blk_len) { ++ copied = ssb_sflash_read(cc, ++ blk_offset, ++ blk_len, blk_ptr); ++ blk_offset += copied; ++ blk_len -= copied; ++ blk_ptr += copied; ++ } ++ } ++ ++ /* Copy input data into holding block */ ++ memcpy(cur_ptr + (offset & mask), buf, cur_retlen); ++ } ++ ++ /* Erase block */ ++ ret = ssb_sflash_erase(cc, cur_offset); ++ if (ret < 0) ++ goto done; ++ ++ while (ssb_sflash_poll(cc, cur_offset)); ++ ++ /* buf == NULL means erase only */ ++ if (!buf) { ++ offset += cur_retlen; ++ len -= cur_retlen; ++ continue; ++ } ++ ++ /* Write holding block */ ++ while (cur_length > 0) { ++ bytes = ssb_sflash_write(cc, cur_offset, ++ cur_length, cur_ptr); ++ ++ if (bytes < 0) { ++ ret = bytes; ++ goto done; ++ } ++ ++ while (ssb_sflash_poll(cc, cur_offset)) ++ ; ++ ++ cur_offset += bytes; ++ cur_length -= bytes; ++ cur_ptr += bytes; ++ } ++ ++ offset += cur_retlen; ++ len -= cur_retlen; ++ buf += cur_retlen; ++ } ++ ++ ret = len; ++done: ++ kfree(block); ++ return ret; ++} +--- a/drivers/ssb/driver_mipscore.c ++++ b/drivers/ssb/driver_mipscore.c +@@ -193,7 +193,13 @@ static void ssb_mips_flash_detect(struct + switch (bus->chipco.capabilities & SSB_CHIPCO_CAP_FLASHT) { + case SSB_CHIPCO_FLASHT_STSER: + case SSB_CHIPCO_FLASHT_ATSER: ++#ifdef CONFIG_SSB_SFLASH ++ pr_info("found serial flash.\n"); ++ bus->chipco.flash_type = SSB_SFLASH; ++ ssb_sflash_init(&bus->chipco); ++#else + pr_info("serial flash not supported.\n"); ++#endif /* CONFIG_SSB_SFLASH */ + break; + case SSB_CHIPCO_FLASHT_PARA: + pr_info("found parallel flash.\n"); +--- a/drivers/ssb/ssb_private.h ++++ b/drivers/ssb/ssb_private.h +@@ -192,6 +192,10 @@ extern int ssb_devices_freeze(struct ssb + extern int ssb_devices_thaw(struct ssb_freeze_context *ctx); + + ++#ifdef CONFIG_SSB_SFLASH ++/* driver_chipcommon_sflash.c */ ++int ssb_sflash_init(struct ssb_chipcommon *cc); ++#endif /* CONFIG_SSB_SFLASH */ + + /* b43_pci_bridge.c */ + #ifdef CONFIG_SSB_B43_PCI_BRIDGE +--- a/include/linux/ssb/ssb_driver_chipcommon.h ++++ b/include/linux/ssb/ssb_driver_chipcommon.h +@@ -503,8 +503,10 @@ + #define SSB_CHIPCO_FLASHCTL_ST_PP 0x0302 /* Page Program */ + #define SSB_CHIPCO_FLASHCTL_ST_SE 0x02D8 /* Sector Erase */ + #define SSB_CHIPCO_FLASHCTL_ST_BE 0x00C7 /* Bulk Erase */ +-#define SSB_CHIPCO_FLASHCTL_ST_DP 0x00B9 /* Deep Power-down */ +-#define SSB_CHIPCO_FLASHCTL_ST_RSIG 0x03AB /* Read Electronic Signature */ ++#define SSB_CHIPCO_FLASHCTL_ST_DP 0x00D9 /* Deep Power-down */ ++#define SSB_CHIPCO_FLASHCTL_ST_RES 0x03AB /* Read Electronic Signature */ ++#define SSB_CHIPCO_FLASHCTL_ST_CSA 0x1000 /* Keep chip select asserted */ ++#define SSB_CHIPCO_FLASHCTL_ST_SSE 0x0220 /* Sub-sector Erase */ + + /* Status register bits for ST flashes */ + #define SSB_CHIPCO_FLASHSTA_ST_WIP 0x01 /* Write In Progress */ +@@ -585,6 +587,7 @@ struct ssb_chipcommon_pmu { + #ifdef CONFIG_SSB_DRIVER_MIPS + enum ssb_flash_type { + SSB_PFLASH, ++ SSB_SFLASH, + }; + + struct ssb_pflash { +@@ -592,6 +595,14 @@ struct ssb_pflash { + u32 window; + u32 window_size; + }; ++ ++#ifdef CONFIG_SSB_SFLASH ++struct ssb_sflash { ++ u32 blocksize; /* Block size */ ++ u32 numblocks; /* Number of blocks */ ++ u32 size; /* Total size in bytes */ ++}; ++#endif /* CONFIG_SSB_SFLASH */ + #endif /* CONFIG_SSB_DRIVER_MIPS */ + + struct ssb_chipcommon { +@@ -605,6 +616,9 @@ struct ssb_chipcommon { + enum ssb_flash_type flash_type; + union { + struct ssb_pflash pflash; ++#ifdef CONFIG_SSB_SFLASH ++ struct ssb_sflash sflash; ++#endif /* CONFIG_SSB_SFLASH */ + }; + #endif /* CONFIG_SSB_DRIVER_MIPS */ + }; +@@ -666,6 +680,18 @@ extern int ssb_chipco_serial_init(struct + struct ssb_serial_port *ports); + #endif /* CONFIG_SSB_SERIAL */ + ++#ifdef CONFIG_SSB_SFLASH ++/* Chipcommon sflash support. */ ++int ssb_sflash_read(struct ssb_chipcommon *cc, u32 offset, u32 len, ++ u8 *buf); ++int ssb_sflash_poll(struct ssb_chipcommon *cc, u32 offset); ++int ssb_sflash_write(struct ssb_chipcommon *cc, u32 offset, u32 len, ++ const u8 *buf); ++int ssb_sflash_erase(struct ssb_chipcommon *cc, u32 offset); ++int ssb_sflash_commit(struct ssb_chipcommon *cc, u32 offset, u32 len, ++ const u8 *buf); ++#endif /* CONFIG_SSB_SFLASH */ ++ + /* PMU support */ + extern void ssb_pmu_init(struct ssb_chipcommon *cc); + diff --git a/target/linux/brcm47xx/patches-3.0/0016-brcm47xx-add-common-interface-for-sflash.patch b/target/linux/brcm47xx/patches-3.0/0016-brcm47xx-add-common-interface-for-sflash.patch new file mode 100644 index 0000000000..841c44dc2a --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0016-brcm47xx-add-common-interface-for-sflash.patch @@ -0,0 +1,193 @@ +From 4f314ac9edbc80897f158fdb4e1b1de8a2d0d432 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sun, 24 Jul 2011 21:10:49 +0200 +Subject: [PATCH 16/26] brcm47xx: add common interface for sflash + + +Signed-off-by: Hauke Mehrtens +--- + arch/mips/bcm47xx/Makefile | 2 +- + arch/mips/bcm47xx/bus.c | 94 ++++++++++++++++++++++++++++++ + arch/mips/bcm47xx/setup.c | 8 +++ + arch/mips/include/asm/mach-bcm47xx/bus.h | 37 ++++++++++++ + 4 files changed, 140 insertions(+), 1 deletions(-) + create mode 100644 arch/mips/bcm47xx/bus.c + create mode 100644 arch/mips/include/asm/mach-bcm47xx/bus.h + +--- a/arch/mips/bcm47xx/Makefile ++++ b/arch/mips/bcm47xx/Makefile +@@ -3,5 +3,5 @@ + # under Linux. + # + +-obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o ++obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o bus.o + obj-$(CONFIG_BCM47XX_SSB) += wgt634u.o +--- /dev/null ++++ b/arch/mips/bcm47xx/bus.c +@@ -0,0 +1,94 @@ ++/* ++ * BCM947xx nvram variable access ++ * ++ * Copyright (C) 2011 Hauke Mehrtens ++ * ++ * 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. ++ */ ++ ++#include ++ ++static int bcm47xx_sflash_bcma_read(struct bcm47xx_sflash *dev, u32 offset, u32 len, u8 *buf) ++{ ++ return bcma_sflash_read(dev->bcc, offset, len, buf); ++} ++ ++static int bcm47xx_sflash_bcma_poll(struct bcm47xx_sflash *dev, u32 offset) ++{ ++ return bcma_sflash_poll(dev->bcc, offset); ++} ++ ++static int bcm47xx_sflash_bcma_write(struct bcm47xx_sflash *dev, u32 offset, u32 len, const u8 *buf) ++{ ++ return bcma_sflash_write(dev->bcc, offset, len, buf); ++} ++ ++static int bcm47xx_sflash_bcma_erase(struct bcm47xx_sflash *dev, u32 offset) ++{ ++ return bcma_sflash_erase(dev->bcc, offset); ++} ++ ++static int bcm47xx_sflash_bcma_commit(struct bcm47xx_sflash *dev, u32 offset, u32 len, const u8 *buf) ++{ ++ return bcma_sflash_commit(dev->bcc, offset, len, buf); ++} ++ ++void bcm47xx_sflash_struct_bcma_init(struct bcm47xx_sflash *sflash, struct bcma_drv_cc *bcc) ++{ ++ sflash->sflash_type = BCM47XX_BUS_TYPE_BCMA; ++ sflash->bcc = bcc; ++ ++ sflash->read = bcm47xx_sflash_bcma_read; ++ sflash->poll = bcm47xx_sflash_bcma_poll; ++ sflash->write = bcm47xx_sflash_bcma_write; ++ sflash->erase = bcm47xx_sflash_bcma_erase; ++ sflash->commit = bcm47xx_sflash_bcma_commit; ++ ++ sflash->blocksize = bcc->sflash.blocksize; ++ sflash->numblocks = bcc->sflash.numblocks; ++ sflash->size = bcc->sflash.size; ++} ++ ++static int bcm47xx_sflash_ssb_read(struct bcm47xx_sflash *dev, u32 offset, u32 len, u8 *buf) ++{ ++ return ssb_sflash_read(dev->scc, offset, len, buf); ++} ++ ++static int bcm47xx_sflash_ssb_poll(struct bcm47xx_sflash *dev, u32 offset) ++{ ++ return ssb_sflash_poll(dev->scc, offset); ++} ++ ++static int bcm47xx_sflash_ssb_write(struct bcm47xx_sflash *dev, u32 offset, u32 len, const u8 *buf) ++{ ++ return ssb_sflash_write(dev->scc, offset, len, buf); ++} ++ ++static int bcm47xx_sflash_ssb_erase(struct bcm47xx_sflash *dev, u32 offset) ++{ ++ return ssb_sflash_erase(dev->scc, offset); ++} ++ ++static int bcm47xx_sflash_ssb_commit(struct bcm47xx_sflash *dev, u32 offset, u32 len, const u8 *buf) ++{ ++ return ssb_sflash_commit(dev->scc, offset, len, buf); ++} ++ ++void bcm47xx_sflash_struct_ssb_init(struct bcm47xx_sflash *sflash, struct ssb_chipcommon *scc) ++{ ++ sflash->sflash_type = BCM47XX_BUS_TYPE_SSB; ++ sflash->scc = scc; ++ ++ sflash->read = bcm47xx_sflash_ssb_read; ++ sflash->poll = bcm47xx_sflash_ssb_poll; ++ sflash->write = bcm47xx_sflash_ssb_write; ++ sflash->erase = bcm47xx_sflash_ssb_erase; ++ sflash->commit = bcm47xx_sflash_ssb_commit; ++ ++ sflash->blocksize = scc->sflash.blocksize; ++ sflash->numblocks = scc->sflash.numblocks; ++ sflash->size = scc->sflash.size; ++} +--- a/arch/mips/bcm47xx/setup.c ++++ b/arch/mips/bcm47xx/setup.c +@@ -42,6 +42,8 @@ EXPORT_SYMBOL(bcm47xx_bus); + enum bcm47xx_bus_type bcm47xx_bus_type; + EXPORT_SYMBOL(bcm47xx_bus_type); + ++struct bcm47xx_sflash bcm47xx_sflash; ++ + static void bcm47xx_machine_restart(char *command) + { + printk(KERN_ALERT "Please stand by while rebooting the system...\n"); +@@ -290,6 +292,9 @@ static void __init bcm47xx_register_ssb( + if (err) + panic("Failed to initialize SSB bus (err %d)\n", err); + ++ if (bcm47xx_bus.ssb.chipco.flash_type == SSB_SFLASH) ++ bcm47xx_sflash_struct_ssb_init(&bcm47xx_sflash, &bcm47xx_bus.ssb.chipco); ++ + mcore = &bcm47xx_bus.ssb.mipscore; + if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) { + if (strstr(buf, "console=ttyS1")) { +@@ -314,6 +319,9 @@ static void __init bcm47xx_register_bcma + err = bcma_host_soc_register(&bcm47xx_bus.bcma); + if (err) + panic("Failed to initialize BCMA bus (err %d)\n", err); ++ ++ if (bcm47xx_bus.bcma.bus.drv_cc.flash_type == BCMA_SFLASH) ++ bcm47xx_sflash_struct_bcma_init(&bcm47xx_sflash, &bcm47xx_bus.bcma.bus.drv_cc); + } + #endif + +--- /dev/null ++++ b/arch/mips/include/asm/mach-bcm47xx/bus.h +@@ -0,0 +1,37 @@ ++/* ++ * BCM947xx nvram variable access ++ * ++ * Copyright (C) 2011 Hauke Mehrtens ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++ ++struct bcm47xx_sflash { ++ enum bcm47xx_bus_type sflash_type; ++ union { ++ struct ssb_chipcommon *scc; ++ struct bcma_drv_cc *bcc; ++ }; ++ ++ int (*read)(struct bcm47xx_sflash *dev, u32 offset, u32 len, u8 *buf); ++ int (*poll)(struct bcm47xx_sflash *dev, u32 offset); ++ int (*write)(struct bcm47xx_sflash *dev, u32 offset, u32 len, const u8 *buf); ++ int (*erase)(struct bcm47xx_sflash *dev, u32 offset); ++ int (*commit)(struct bcm47xx_sflash *dev, u32 offset, u32 len, const u8 *buf); ++ ++ u32 blocksize; /* Block size */ ++ u32 numblocks; /* Number of blocks */ ++ u32 size; /* Total size in bytes */ ++}; ++ ++void bcm47xx_sflash_struct_bcma_init(struct bcm47xx_sflash *sflash, struct bcma_drv_cc *bcc); ++void bcm47xx_sflash_struct_ssb_init(struct bcm47xx_sflash *sflash, struct ssb_chipcommon *scc); ++ ++extern struct bcm47xx_sflash bcm47xx_sflash; diff --git a/target/linux/brcm47xx/patches-3.0/0016-mtd-bcm47xx-add-serial-flash-driver.patch b/target/linux/brcm47xx/patches-3.0/0016-mtd-bcm47xx-add-serial-flash-driver.patch deleted file mode 100644 index 20e5711faa..0000000000 --- a/target/linux/brcm47xx/patches-3.0/0016-mtd-bcm47xx-add-serial-flash-driver.patch +++ /dev/null @@ -1,312 +0,0 @@ -From 8a6398687998886c451c6df381c2320b6dddb3fe Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens -Date: Sun, 17 Jul 2011 14:55:45 +0200 -Subject: [PATCH 16/22] mtd: bcm47xx: add serial flash driver - - -Signed-off-by: Hauke Mehrtens ---- - drivers/mtd/maps/Kconfig | 9 ++ - drivers/mtd/maps/Makefile | 1 + - drivers/mtd/maps/bcm47xx-sflash.c | 270 +++++++++++++++++++++++++++++++++++++ - 3 files changed, 280 insertions(+), 0 deletions(-) - create mode 100644 drivers/mtd/maps/bcm47xx-sflash.c - ---- a/drivers/mtd/maps/Kconfig -+++ b/drivers/mtd/maps/Kconfig -@@ -273,6 +273,15 @@ config MTD_BCM47XX_PFLASH - help - Support for bcm47xx parallel flash - -+config MTD_BCM47XX_SFLASH -+ tristate "bcm47xx serial flash support" -+ default y -+ depends on BCM47XX -+ select MTD_PARTITIONS -+ select MTD_BCM47XX_PARTS -+ help -+ Support for bcm47xx parallel flash -+ - config MTD_DILNETPC - tristate "CFI Flash device mapped on DIL/Net PC" - depends on X86 && MTD_CFI_INTELEXT && BROKEN ---- a/drivers/mtd/maps/Makefile -+++ b/drivers/mtd/maps/Makefile -@@ -61,3 +61,4 @@ obj-$(CONFIG_MTD_BCM963XX) += bcm963xx-f - obj-$(CONFIG_MTD_LATCH_ADDR) += latch-addr-flash.o - obj-$(CONFIG_MTD_LANTIQ) += lantiq-flash.o - obj-$(CONFIG_MTD_BCM47XX_PFLASH)+= bcm47xx-pflash.o -+obj-$(CONFIG_MTD_BCM47XX_SFLASH)+= bcm47xx-sflash.o ---- /dev/null -+++ b/drivers/mtd/maps/bcm47xx-sflash.c -@@ -0,0 +1,270 @@ -+/* -+ * Broadcom SiliconBackplane chipcommon serial flash interface -+ * -+ * Copyright 2006, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY -+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM -+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. -+ * -+ * $Id$ -+ */ -+ -+#define pr_fmt(fmt) "bcm47xx_sflash: " fmt -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+ -+struct sflash_mtd { -+ struct bcma_drv_cc *cc; -+ struct mtd_info mtd; -+ struct mtd_erase_region_info region; -+}; -+ -+static struct sflash_mtd *sflash; -+ -+static int -+sflash_mtd_poll(struct sflash_mtd *sflash, unsigned int offset, int timeout) -+{ -+ unsigned long now = jiffies; -+ int ret = 0; -+ -+ for (;;) { -+ if (!bcma_sflash_poll(sflash->cc, offset)) { -+ ret = 0; -+ break; -+ } -+ if (time_after(jiffies, now + timeout)) { -+ pr_err("timeout while polling\n"); -+ ret = -ETIMEDOUT; -+ break; -+ } -+ udelay(1); -+ } -+ -+ return ret; -+} -+ -+static int -+sflash_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) -+{ -+ struct sflash_mtd *sflash = (struct sflash_mtd *) mtd->priv; -+ -+ /* Check address range */ -+ if (!len) -+ return 0; -+ -+ if ((from + len) > mtd->size) -+ return -EINVAL; -+ -+ *retlen = 0; -+ -+ while (len) { -+ int ret = bcma_sflash_read(sflash->cc, from, len, buf); -+ if (ret < 0) -+ return ret; -+ -+ from += (loff_t) ret; -+ len -= ret; -+ buf += ret; -+ *retlen += ret; -+ } -+ -+ return 0; -+} -+ -+static int -+sflash_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) -+{ -+ struct sflash_mtd *sflash = (struct sflash_mtd *) mtd->priv; -+ -+ /* Check address range */ -+ if (!len) -+ return 0; -+ -+ if ((to + len) > mtd->size) -+ return -EINVAL; -+ -+ *retlen = 0; -+ while (len) { -+ int bytes; -+ int ret = bcma_sflash_write(sflash->cc, to, len, buf); -+ if (ret < 0) -+ return ret; -+ -+ bytes = ret; -+ -+ ret = sflash_mtd_poll(sflash, (unsigned int) to, HZ / 10); -+ if (ret) -+ return ret; -+ -+ to += (loff_t) bytes; -+ len -= bytes; -+ buf += bytes; -+ *retlen += bytes; -+ } -+ -+ return 0; -+} -+ -+static int -+sflash_mtd_erase(struct mtd_info *mtd, struct erase_info *erase) -+{ -+ struct sflash_mtd *sflash = (struct sflash_mtd *) mtd->priv; -+ int i, j, ret = 0; -+ unsigned int addr, len; -+ -+ /* Check address range */ -+ if (!erase->len) -+ return 0; -+ if ((erase->addr + erase->len) > mtd->size) -+ return -EINVAL; -+ -+ addr = erase->addr; -+ len = erase->len; -+ -+ /* Ensure that requested regions are aligned */ -+ for (i = 0; i < mtd->numeraseregions; i++) { -+ for (j = 0; j < mtd->eraseregions[i].numblocks; j++) { -+ if (addr == mtd->eraseregions[i].offset + -+ mtd->eraseregions[i].erasesize * j && -+ len >= mtd->eraseregions[i].erasesize) { -+ if ((ret = bcma_sflash_erase(sflash->cc, addr)) < 0) -+ break; -+ if ((ret = sflash_mtd_poll(sflash, addr, 10 * HZ))) -+ break; -+ addr += mtd->eraseregions[i].erasesize; -+ len -= mtd->eraseregions[i].erasesize; -+ } -+ } -+ if (ret) -+ break; -+ } -+ -+ /* Set erase status */ -+ if (ret) -+ erase->state = MTD_ERASE_FAILED; -+ else -+ erase->state = MTD_ERASE_DONE; -+ -+ /* Call erase callback */ -+ if (erase->callback) -+ erase->callback(erase); -+ -+ return ret; -+} -+ -+static const char *probes[] = { "bcm47xx", NULL }; -+ -+static int bcm47xx_sflash_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ struct mtd_partition *parts; -+ int num_partitions = 0; -+ -+ sflash = kzalloc(sizeof(struct sflash_mtd), GFP_KERNEL); -+ if (!sflash) -+ return -ENOMEM; -+ -+ sflash->cc = &bcm47xx_bus.bcma.bus.drv_cc; -+ if (sflash->cc->flash_type != BCMA_SFLASH) -+ return -ENODEV; -+ -+ pr_info("found serial flash: blocksize=%dKB, numblocks=%d, size=%dKB\n", -+ sflash->cc->flash.sflash.blocksize/1024, -+ sflash->cc->flash.sflash.numblocks, -+ sflash->cc->flash.sflash.size/1024); -+ -+ /* Setup region info */ -+ sflash->region.offset = 0; -+ sflash->region.erasesize = sflash->cc->flash.sflash.blocksize; -+ sflash->region.numblocks = sflash->cc->flash.sflash.numblocks; -+ if (sflash->region.erasesize > sflash->mtd.erasesize) -+ sflash->mtd.erasesize = sflash->region.erasesize; -+ sflash->mtd.size = sflash->cc->flash.sflash.size; -+ sflash->mtd.numeraseregions = 1; -+ -+ /* Register with MTD */ -+ sflash->mtd.name = "bcm47xx-sflash"; -+ sflash->mtd.type = MTD_NORFLASH; -+ sflash->mtd.flags = MTD_CAP_NORFLASH; -+ sflash->mtd.eraseregions = &sflash->region; -+ sflash->mtd.erase = sflash_mtd_erase; -+ sflash->mtd.read = sflash_mtd_read; -+ sflash->mtd.write = sflash_mtd_write; -+ sflash->mtd.writesize = 1; -+ sflash->mtd.priv = sflash; -+ sflash->mtd.owner = THIS_MODULE; -+ -+ num_partitions = parse_mtd_partitions(&sflash->mtd, probes, &parts, 0); -+ if (num_partitions < 0) { -+ ret = num_partitions; -+ goto err_destroy; -+ } -+ -+ ret = mtd_device_register(&sflash->mtd, parts, num_partitions); -+ -+// ret = mtd_device_parse_register(bcm47xx_mtd, "bcm47xx", NULL, NULL, 0); -+ -+ if (ret) { -+ pr_err("mtd_device_register failed\n"); -+ return ret; -+ } -+ return 0; -+ -+err_destroy: -+ map_destroy(&sflash->mtd); -+ return ret; -+} -+ -+static int __devexit bcm47xx_sflash_remove(struct platform_device *pdev) -+{ -+ if (sflash) { -+ mtd_device_unregister(&sflash->mtd); -+ map_destroy(&sflash->mtd); -+ } -+ return 0; -+} -+ -+static struct platform_driver bcm47xx_sflash_driver = { -+ .remove = __devexit_p(bcm47xx_sflash_remove), -+ .driver = { -+ .name = "bcm47xx_sflash", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static int __init init_bcm47xx_sflash(void) -+{ -+ int ret = platform_driver_probe(&bcm47xx_sflash_driver, bcm47xx_sflash_probe); -+ -+ if (ret) -+ pr_err("error registering platform driver: %i\n", ret); -+ return ret; -+} -+ -+static void __exit exit_bcm47xx_sflash(void) -+{ -+ platform_driver_unregister(&bcm47xx_sflash_driver); -+} -+ -+module_init(init_bcm47xx_sflash); -+module_exit(exit_bcm47xx_sflash); -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("BCM47XX parallel flash driver"); diff --git a/target/linux/brcm47xx/patches-3.0/0017-bcm47xx-register-flash-drivers.patch b/target/linux/brcm47xx/patches-3.0/0017-bcm47xx-register-flash-drivers.patch deleted file mode 100644 index 383e019634..0000000000 --- a/target/linux/brcm47xx/patches-3.0/0017-bcm47xx-register-flash-drivers.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 89b904335338c86ef2c40e7cc51e19673feb62c1 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens -Date: Sun, 17 Jul 2011 15:02:10 +0200 -Subject: [PATCH 17/22] bcm47xx: register flash drivers - - -Signed-off-by: Hauke Mehrtens ---- - arch/mips/bcm47xx/setup.c | 50 +++++++++++++++++++++++++++++++++++++++++++++ - 1 files changed, 50 insertions(+), 0 deletions(-) - ---- a/arch/mips/bcm47xx/setup.c -+++ b/arch/mips/bcm47xx/setup.c -@@ -30,6 +30,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -357,3 +358,52 @@ static int __init bcm47xx_register_bus_c - return 0; - } - device_initcall(bcm47xx_register_bus_complete); -+ -+static struct resource bcm47xx_pflash_resource = { -+ .name = "para", -+ .start = 0, -+ .end = 0, -+ .flags = 0, -+}; -+ -+static struct platform_device bcm47xx_pflash = { -+ .name = "bcm47xx_pflash", -+ .resource = &bcm47xx_pflash_resource, -+ .num_resources = 1, -+}; -+ -+static struct resource bcm47xx_sflash_resource = { -+ .name = "serial", -+ .start = 0, -+ .end = 0, -+ .flags = 0, -+}; -+ -+static struct platform_device bcm47xx_sflash = { -+ .name = "bcm47xx_sflash", -+ .resource = &bcm47xx_sflash_resource, -+ .num_resources = 1, -+}; -+ -+static int __init bcm47xx_register_flash(void) -+{ -+ switch (bcm47xx_active_bus_type) { -+#ifdef CONFIG_BCM47XX_SSB -+ case BCM47XX_BUS_TYPE_SSB: -+ return platform_device_register(&bcm47xx_pflash); -+#endif -+#ifdef CONFIG_BCM47XX_BCMA -+ case BCM47XX_BUS_TYPE_BCMA: -+ if (bcm47xx_bus.bcma.bus.drv_cc.flash_type == BCMA_PFLASH) { -+ return platform_device_register(&bcm47xx_pflash); -+ } else if (bcm47xx_bus.bcma.bus.drv_cc.flash_type == BCMA_SFLASH) { -+ return platform_device_register(&bcm47xx_sflash); -+ } else { -+ printk(KERN_ERR "No flash device found\n"); -+ return -1; -+ } -+#endif -+ } -+ return 0; -+} -+fs_initcall(bcm47xx_register_flash); diff --git a/target/linux/brcm47xx/patches-3.0/0017-mtd-bcm47xx-add-bcm47xx-part-parser.patch b/target/linux/brcm47xx/patches-3.0/0017-mtd-bcm47xx-add-bcm47xx-part-parser.patch new file mode 100644 index 0000000000..284b83aa52 --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0017-mtd-bcm47xx-add-bcm47xx-part-parser.patch @@ -0,0 +1,579 @@ +From 1934b89b42976a083c2ad8d8fdc526ab5b05c5e4 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sun, 17 Jul 2011 14:54:11 +0200 +Subject: [PATCH 17/26] mtd: bcm47xx: add bcm47xx part parser + + +Signed-off-by: Hauke Mehrtens +--- + drivers/mtd/Kconfig | 7 + + drivers/mtd/Makefile | 1 + + drivers/mtd/bcm47xxpart.c | 536 +++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 544 insertions(+), 0 deletions(-) + create mode 100644 drivers/mtd/bcm47xxpart.c + +--- a/drivers/mtd/Kconfig ++++ b/drivers/mtd/Kconfig +@@ -173,6 +173,13 @@ config MTD_MYLOADER_PARTS + You will still need the parsing functions to be called by the driver + for your particular device. It won't happen automatically. + ++config MTD_BCM47XX_PARTS ++ tristate "BCM47XX partitioning support" ++ default y ++ depends on BCM47XX ++ ---help--- ++ bcm47XX partitioning support ++ + comment "User Modules And Translation Layers" + + config MTD_CHAR +--- a/drivers/mtd/Makefile ++++ b/drivers/mtd/Makefile +@@ -12,6 +12,7 @@ obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdli + obj-$(CONFIG_MTD_AFS_PARTS) += afs.o + obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o + obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o ++obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o + + # 'Users' - code which presents functionality to userspace. + obj-$(CONFIG_MTD_CHAR) += mtdchar.o +--- /dev/null ++++ b/drivers/mtd/bcm47xxpart.c +@@ -0,0 +1,536 @@ ++/* ++ * Copyright (C) 2006 Felix Fietkau ++ * Copyright (C) 2005 Waldemar Brodkorb ++ * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org) ++ * ++ * original functions for finding root filesystem from Mike Baker ++ * ++ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN ++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * 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., ++ * 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * Copyright 2001-2003, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * Flash mapping for BCM947XX boards ++ */ ++ ++#define pr_fmt(fmt) "bcm47xx_part: " fmt ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#define TRX_MAGIC 0x30524448 /* "HDR0" */ ++#define TRX_VERSION 1 ++#define TRX_MAX_LEN 0x3A0000 ++#define TRX_NO_HEADER 1 /* Do not write TRX header */ ++#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */ ++#define TRX_MAX_OFFSET 3 ++ ++struct trx_header { ++ u32 magic; /* "HDR0" */ ++ u32 len; /* Length of file including header */ ++ u32 crc32; /* 32-bit CRC from flag_version to end of file */ ++ u32 flag_version; /* 0:15 flags, 16:31 version */ ++ u32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */ ++}; ++ ++/* for Edimax Print servers which use an additional header ++ * then the firmware on flash looks like : ++ * EDIMAX HEADER | TRX HEADER ++ * As this header is 12 bytes long we have to handle it ++ * and skip it to find the TRX header ++ */ ++#define EDIMAX_PS_HEADER_MAGIC 0x36315350 /* "PS16" */ ++#define EDIMAX_PS_HEADER_LEN 0xc /* 12 bytes long for edimax header */ ++ ++#define NVRAM_SPACE 0x8000 ++ ++#define ROUTER_NETGEAR_WGR614L 1 ++#define ROUTER_NETGEAR_WNR834B 2 ++#define ROUTER_NETGEAR_WNDR3300 3 ++#define ROUTER_NETGEAR_WNR3500L 4 ++#define ROUTER_SIMPLETECH_SIMPLESHARE 5 ++ ++static struct mtd_partition bcm47xx_parts[] = { ++ { name: "cfe", offset:0, size:0, mask_flags:MTD_WRITEABLE, }, ++ { name: "linux", offset:0, size:0, }, ++ { name: "rootfs", offset:0, size:0, }, ++ { name: "nvram", offset:0, size:0, }, ++ { name: NULL, }, /* Used to create custom partitons with the function get_router() */ ++ { name: NULL, }, ++}; ++ ++static int ++find_cfe_size(struct mtd_info *mtd) ++{ ++ struct trx_header *trx; ++ unsigned char buf[512]; ++ int off; ++ size_t len; ++ int blocksize; ++ ++ trx = (struct trx_header *) buf; ++ ++ blocksize = mtd->erasesize; ++ if (blocksize < 0x10000) ++ blocksize = 0x10000; ++ ++ for (off = (128*1024); off < mtd->size; off += blocksize) { ++ memset(buf, 0xe5, sizeof(buf)); ++ ++ /* ++ * Read into buffer ++ */ ++ if (mtd->read(mtd, off, sizeof(buf), &len, buf) || ++ len != sizeof(buf)) ++ continue; ++ ++ if (le32_to_cpu(trx->magic) == EDIMAX_PS_HEADER_MAGIC) { ++ if (mtd->read(mtd, off + EDIMAX_PS_HEADER_LEN, ++ sizeof(buf), &len, buf) || len != sizeof(buf)) { ++ continue; ++ } else { ++ pr_notice("Found edimax header\n"); ++ } ++ } ++ ++ /* found a TRX header */ ++ if (le32_to_cpu(trx->magic) == TRX_MAGIC) ++ goto found; ++ } ++ ++ pr_notice("%s: Couldn't find bootloader size\n", mtd->name); ++ return -1; ++ ++ found: ++ pr_notice("bootloader size: %d\n", off); ++ return off; ++ ++} ++ ++/* ++ * Copied from mtdblock.c ++ * ++ * Cache stuff... ++ * ++ * Since typical flash erasable sectors are much larger than what Linux's ++ * buffer cache can handle, we must implement read-modify-write on flash ++ * sectors for each block write requests. To avoid over-erasing flash sectors ++ * and to speed things up, we locally cache a whole flash sector while it is ++ * being written to until a different sector is required. ++ */ ++ ++static void erase_callback(struct erase_info *done) ++{ ++ wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv; ++ wake_up(wait_q); ++} ++ ++static int erase_write(struct mtd_info *mtd, unsigned long pos, ++ int len, const char *buf) ++{ ++ struct erase_info erase; ++ DECLARE_WAITQUEUE(wait, current); ++ wait_queue_head_t wait_q; ++ size_t retlen; ++ int ret; ++ ++ /* ++ * First, let's erase the flash block. ++ */ ++ ++ init_waitqueue_head(&wait_q); ++ erase.mtd = mtd; ++ erase.callback = erase_callback; ++ erase.addr = pos; ++ erase.len = len; ++ erase.priv = (u_long)&wait_q; ++ ++ set_current_state(TASK_INTERRUPTIBLE); ++ add_wait_queue(&wait_q, &wait); ++ ++ ret = mtd->erase(mtd, &erase); ++ if (ret) { ++ set_current_state(TASK_RUNNING); ++ remove_wait_queue(&wait_q, &wait); ++ pr_warn("erase of region [0x%lx, 0x%x] on \"%s\" failed\n", ++ pos, len, mtd->name); ++ return ret; ++ } ++ ++ schedule(); /* Wait for erase to finish. */ ++ remove_wait_queue(&wait_q, &wait); ++ ++ /* ++ * Next, write data to flash. ++ */ ++ ++ ret = mtd->write(mtd, pos, len, &retlen, buf); ++ if (ret) ++ return ret; ++ if (retlen != len) ++ return -EIO; ++ return 0; ++} ++ ++ ++static int ++find_dual_image_off(struct mtd_info *mtd) ++{ ++ struct trx_header trx; ++ int off, blocksize; ++ size_t len; ++ ++ blocksize = mtd->erasesize; ++ if (blocksize < 0x10000) ++ blocksize = 0x10000; ++ ++ for (off = (128*1024); off < mtd->size; off += blocksize) { ++ memset(&trx, 0xe5, sizeof(trx)); ++ /* ++ * Read into buffer ++ */ ++ if (mtd->read(mtd, off, sizeof(trx), &len, (char *) &trx) || ++ len != sizeof(trx)) ++ continue; ++ /* found last TRX header */ ++ if (le32_to_cpu(trx.magic) == TRX_MAGIC) { ++ if (le32_to_cpu(trx.flag_version >> 16) == 2) { ++ pr_notice("dual image TRX header found\n"); ++ return mtd->size / 2; ++ } else { ++ return 0; ++ } ++ } ++ } ++ return 0; ++} ++ ++ ++static int ++find_root(struct mtd_info *mtd, struct mtd_partition *part) ++{ ++ struct trx_header trx, *trx2; ++ unsigned char buf[512], *block; ++ int off, blocksize, trxoff = 0; ++ u32 i, crc = ~0; ++ size_t len; ++ bool edimax = false; ++ ++ blocksize = mtd->erasesize; ++ if (blocksize < 0x10000) ++ blocksize = 0x10000; ++ ++ for (off = (128*1024); off < mtd->size; off += blocksize) { ++ memset(&trx, 0xe5, sizeof(trx)); ++ ++ /* ++ * Read into buffer ++ */ ++ if (mtd->read(mtd, off, sizeof(trx), &len, (char *) &trx) || ++ len != sizeof(trx)) ++ continue; ++ ++ /* found an edimax header */ ++ if (le32_to_cpu(trx.magic) == EDIMAX_PS_HEADER_MAGIC) { ++ /* read the correct trx header */ ++ if (mtd->read(mtd, off + EDIMAX_PS_HEADER_LEN, ++ sizeof(trx), &len, (char *) &trx) || ++ len != sizeof(trx)) { ++ continue; ++ } else { ++ pr_notice("Found an edimax ps header\n"); ++ edimax = true; ++ } ++ } ++ ++ /* found a TRX header */ ++ if (le32_to_cpu(trx.magic) == TRX_MAGIC) { ++ part->offset = le32_to_cpu(trx.offsets[2]) ? : ++ le32_to_cpu(trx.offsets[1]); ++ part->size = le32_to_cpu(trx.len); ++ ++ part->size -= part->offset; ++ part->offset += off; ++ if (edimax) { ++ off += EDIMAX_PS_HEADER_LEN; ++ trxoff = EDIMAX_PS_HEADER_LEN; ++ } ++ ++ goto found; ++ } ++ } ++ ++ pr_warn("%s: Couldn't find root filesystem\n", ++ mtd->name); ++ return -1; ++ ++ found: ++ pr_notice("TRX offset : %x\n", trxoff); ++ if (part->size == 0) ++ return 0; ++ ++ if (mtd->read(mtd, part->offset, sizeof(buf), &len, buf) || len != sizeof(buf)) ++ return 0; ++ ++ /* Move the fs outside of the trx */ ++ part->size = 0; ++ ++ if (trx.len != part->offset + part->size - off) { ++ /* Update the trx offsets and length */ ++ trx.len = part->offset + part->size - off; ++ ++ /* Update the trx crc32 */ ++ for (i = (u32) &(((struct trx_header *)NULL)->flag_version); i <= trx.len; i += sizeof(buf)) { ++ if (mtd->read(mtd, off + i, sizeof(buf), &len, buf) || len != sizeof(buf)) ++ return 0; ++ crc = crc32_le(crc, buf, min(sizeof(buf), trx.len - i)); ++ } ++ trx.crc32 = crc; ++ ++ /* read first eraseblock from the trx */ ++ block = kmalloc(mtd->erasesize, GFP_KERNEL); ++ trx2 = (struct trx_header *) block; ++ if (mtd->read(mtd, off - trxoff, mtd->erasesize, &len, block) || len != mtd->erasesize) { ++ pr_err("Error accessing the first trx eraseblock\n"); ++ return 0; ++ } ++ ++ pr_notice("Updating TRX offsets and length:\n"); ++ pr_notice("old trx = [0x%08x, 0x%08x, 0x%08x], len=0x%08x crc32=0x%08x\n", trx2->offsets[0], trx2->offsets[1], trx2->offsets[2], trx2->len, trx2->crc32); ++ pr_notice("new trx = [0x%08x, 0x%08x, 0x%08x], len=0x%08x crc32=0x%08x\n", trx.offsets[0], trx.offsets[1], trx.offsets[2], trx.len, trx.crc32); ++ ++ /* Write updated trx header to the flash */ ++ memcpy(block + trxoff, &trx, sizeof(trx)); ++ if (mtd->unlock) ++ mtd->unlock(mtd, off - trxoff, mtd->erasesize); ++ erase_write(mtd, off - trxoff, mtd->erasesize, block); ++ if (mtd->sync) ++ mtd->sync(mtd); ++ kfree(block); ++ pr_notice("Done\n"); ++ } ++ ++ return part->size; ++} ++ ++static int get_router(void) ++{ ++ char buf[20]; ++ u32 boardnum = 0; ++ u16 boardtype = 0; ++ u16 boardrev = 0; ++ u32 boardflags = 0; ++ u16 sdram_init = 0; ++ u16 cardbus = 0; ++ u16 strev = 0; ++ ++ if (nvram_getenv("boardnum", buf, sizeof(buf)) >= 0) ++ boardnum = simple_strtoul(buf, NULL, 0); ++ if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0) ++ boardtype = simple_strtoul(buf, NULL, 0); ++ if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0) ++ boardrev = simple_strtoul(buf, NULL, 0); ++ if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0) ++ boardflags = simple_strtoul(buf, NULL, 0); ++ if (nvram_getenv("sdram_init", buf, sizeof(buf)) >= 0) ++ sdram_init = simple_strtoul(buf, NULL, 0); ++ if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0) ++ cardbus = simple_strtoul(buf, NULL, 0); ++ if (nvram_getenv("st_rev", buf, sizeof(buf)) >= 0) ++ strev = simple_strtoul(buf, NULL, 0); ++ ++ if ((boardnum == 8 || boardnum == 01) ++ && boardtype == 0x0472 && cardbus == 1) { ++ /* Netgear WNR834B, Netgear WNR834Bv2 */ ++ return ROUTER_NETGEAR_WNR834B; ++ } ++ ++ if (boardnum == 01 && boardtype == 0x0472 && boardrev == 0x23) { ++ /* Netgear WNDR-3300 */ ++ return ROUTER_NETGEAR_WNDR3300; ++ } ++ ++ if ((boardnum == 83258 || boardnum == 01) ++ && boardtype == 0x048e ++ && (boardrev == 0x11 || boardrev == 0x10) ++ && boardflags == 0x750 ++ && sdram_init == 0x000A) { ++ /* Netgear WGR614v8/L/WW 16MB ram, cfe v1.3 or v1.5 */ ++ return ROUTER_NETGEAR_WGR614L; ++ } ++ ++ if ((boardnum == 1 || boardnum == 3500) ++ && boardtype == 0x04CF ++ && (boardrev == 0x1213 || boardrev == 02)) { ++ /* Netgear WNR3500v2/U/L */ ++ return ROUTER_NETGEAR_WNR3500L; ++ } ++ ++ if (boardtype == 0x042f ++ && boardrev == 0x10 ++ && boardflags == 0 ++ && strev == 0x11) { ++ /* Simpletech Simpleshare */ ++ return ROUTER_SIMPLETECH_SIMPLESHARE; ++ } ++ ++ return 0; ++} ++ ++static int parse_bcm47xx_partitions(struct mtd_info *mtd, ++ struct mtd_partition **pparts, ++// struct mtd_part_parser_data *data) ++ unsigned long data) ++{ ++ int cfe_size; ++ int dual_image_offset = 0; ++ /* e.g Netgear 0x003e0000-0x003f0000 : "board_data", we exclude this ++ * part from our mapping to prevent overwriting len/checksum on e.g. ++ * Netgear WGR614v8/L/WW ++ */ ++ int custom_data_size = 0; ++ ++ cfe_size = find_cfe_size(mtd); ++ if (cfe_size < 0) ++ return 0; ++ ++ /* boot loader */ ++ bcm47xx_parts[0].offset = 0; ++ bcm47xx_parts[0].size = cfe_size; ++ ++ /* nvram */ ++ if (cfe_size != 384 * 1024) { ++ ++ switch (get_router()) { ++ case ROUTER_NETGEAR_WGR614L: ++ case ROUTER_NETGEAR_WNR834B: ++ case ROUTER_NETGEAR_WNDR3300: ++ case ROUTER_NETGEAR_WNR3500L: ++ /* Netgear: checksum is @ 0x003AFFF8 for 4M flash or checksum ++ * is @ 0x007AFFF8 for 8M flash ++ */ ++ custom_data_size = mtd->erasesize; ++ ++ bcm47xx_parts[3].offset = mtd->size - roundup(NVRAM_SPACE, mtd->erasesize); ++ bcm47xx_parts[3].size = roundup(NVRAM_SPACE, mtd->erasesize); ++ ++ /* Place CFE board_data into a partition */ ++ bcm47xx_parts[4].name = "board_data"; ++ bcm47xx_parts[4].offset = bcm47xx_parts[3].offset - custom_data_size; ++ bcm47xx_parts[4].size = custom_data_size; ++ break; ++ ++ case ROUTER_SIMPLETECH_SIMPLESHARE: ++ /* Fixup Simpletech Simple share nvram */ ++ ++ pr_notice("Setting up simpletech nvram\n"); ++ custom_data_size = mtd->erasesize; ++ ++ bcm47xx_parts[3].offset = mtd->size - roundup(NVRAM_SPACE, mtd->erasesize) * 2; ++ bcm47xx_parts[3].size = roundup(NVRAM_SPACE, mtd->erasesize); ++ ++ /* Place backup nvram into a partition */ ++ bcm47xx_parts[4].name = "nvram_copy"; ++ bcm47xx_parts[4].offset = mtd->size - roundup(NVRAM_SPACE, mtd->erasesize); ++ bcm47xx_parts[4].size = roundup(NVRAM_SPACE, mtd->erasesize); ++ break; ++ ++ default: ++ bcm47xx_parts[3].offset = mtd->size - roundup(NVRAM_SPACE, mtd->erasesize); ++ bcm47xx_parts[3].size = roundup(NVRAM_SPACE, mtd->erasesize); ++ } ++ ++ } else { ++ /* nvram (old 128kb config partition on netgear wgt634u) */ ++ bcm47xx_parts[3].offset = bcm47xx_parts[0].size; ++ bcm47xx_parts[3].size = roundup(NVRAM_SPACE, mtd->erasesize); ++ } ++ ++ /* dual image offset*/ ++ pr_notice("Looking for dual image\n"); ++ dual_image_offset = find_dual_image_off(mtd); ++ /* linux (kernel and rootfs) */ ++ if (cfe_size != 384 * 1024) { ++ if (get_router() == ROUTER_SIMPLETECH_SIMPLESHARE) { ++ bcm47xx_parts[1].offset = bcm47xx_parts[0].size; ++ bcm47xx_parts[1].size = bcm47xx_parts[4].offset - dual_image_offset - ++ bcm47xx_parts[1].offset - custom_data_size; ++ } else { ++ bcm47xx_parts[1].offset = bcm47xx_parts[0].size; ++ bcm47xx_parts[1].size = bcm47xx_parts[3].offset - dual_image_offset - ++ bcm47xx_parts[1].offset - custom_data_size; ++ } ++ } else { ++ /* do not count the elf loader, which is on one block */ ++ bcm47xx_parts[1].offset = bcm47xx_parts[0].size + ++ bcm47xx_parts[3].size + mtd->erasesize; ++ bcm47xx_parts[1].size = mtd->size - ++ bcm47xx_parts[0].size - ++ (2*bcm47xx_parts[3].size) - ++ mtd->erasesize - custom_data_size; ++ } ++ ++ /* find and size rootfs */ ++ find_root(mtd, &bcm47xx_parts[2]); ++ bcm47xx_parts[2].size = mtd->size - dual_image_offset - ++ bcm47xx_parts[2].offset - ++ bcm47xx_parts[3].size - custom_data_size; ++ *pparts = bcm47xx_parts; ++ return bcm47xx_parts[4].name == NULL ? 4 : 5; ++} ++ ++static struct mtd_part_parser bcm47xx_parser = { ++ .owner = THIS_MODULE, ++ .parse_fn = parse_bcm47xx_partitions, ++ .name = "bcm47xx", ++}; ++ ++static int __init bcm47xx_parser_init(void) ++{ ++ return register_mtd_parser(&bcm47xx_parser); ++} ++ ++static void __exit bcm47xx_parser_exit(void) ++{ ++ deregister_mtd_parser(&bcm47xx_parser); ++} ++ ++module_init(bcm47xx_parser_init); ++module_exit(bcm47xx_parser_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("Parsing code for flash partitions on bcm47xx SoCs"); diff --git a/target/linux/brcm47xx/patches-3.0/0018-mtd-bcm47xx-add-parallel-flash-driver.patch b/target/linux/brcm47xx/patches-3.0/0018-mtd-bcm47xx-add-parallel-flash-driver.patch new file mode 100644 index 0000000000..0ab81f33b8 --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0018-mtd-bcm47xx-add-parallel-flash-driver.patch @@ -0,0 +1,240 @@ +From fb261916ee9cd9eede57f6255ffd39e4145da48e Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sun, 17 Jul 2011 14:55:18 +0200 +Subject: [PATCH 18/26] mtd: bcm47xx: add parallel flash driver + + +Signed-off-by: Hauke Mehrtens +--- + drivers/mtd/maps/Kconfig | 9 ++ + drivers/mtd/maps/Makefile | 1 + + drivers/mtd/maps/bcm47xx-pflash.c | 198 +++++++++++++++++++++++++++++++++++++ + 3 files changed, 208 insertions(+), 0 deletions(-) + create mode 100644 drivers/mtd/maps/bcm47xx-pflash.c + +--- a/drivers/mtd/maps/Kconfig ++++ b/drivers/mtd/maps/Kconfig +@@ -264,6 +264,15 @@ config MTD_LANTIQ + help + Support for NOR flash attached to the Lantiq SoC's External Bus Unit. + ++config MTD_BCM47XX_PFLASH ++ tristate "bcm47xx parallel flash support" ++ default y ++ depends on BCM47XX ++ select MTD_PARTITIONS ++ select MTD_BCM47XX_PARTS ++ help ++ Support for bcm47xx parallel flash ++ + config MTD_DILNETPC + tristate "CFI Flash device mapped on DIL/Net PC" + depends on X86 && MTD_CFI_INTELEXT && BROKEN +--- a/drivers/mtd/maps/Makefile ++++ b/drivers/mtd/maps/Makefile +@@ -60,3 +60,4 @@ obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr + obj-$(CONFIG_MTD_BCM963XX) += bcm963xx-flash.o + obj-$(CONFIG_MTD_LATCH_ADDR) += latch-addr-flash.o + obj-$(CONFIG_MTD_LANTIQ) += lantiq-flash.o ++obj-$(CONFIG_MTD_BCM47XX_PFLASH)+= bcm47xx-pflash.o +--- /dev/null ++++ b/drivers/mtd/maps/bcm47xx-pflash.c +@@ -0,0 +1,198 @@ ++/* ++ * Copyright (C) 2006 Felix Fietkau ++ * Copyright (C) 2005 Waldemar Brodkorb ++ * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org) ++ * ++ * original functions for finding root filesystem from Mike Baker ++ * ++ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN ++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * 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., ++ * 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * Copyright 2001-2003, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * Flash mapping for BCM947XX boards ++ */ ++ ++#define pr_fmt(fmt) "bcm47xx_pflash: " fmt ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define WINDOW_ADDR 0x1fc00000 ++#define WINDOW_SIZE 0x400000 ++#define BUSWIDTH 2 ++ ++static struct mtd_info *bcm47xx_mtd; ++ ++static void bcm47xx_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) ++{ ++ if (len == 1) { ++ memcpy_fromio(to, map->virt + from, len); ++ } else { ++ int i; ++ u16 *dest = (u16 *) to; ++ u16 *src = (u16 *) (map->virt + from); ++ for (i = 0; i < (len / 2); i++) ++ dest[i] = src[i]; ++ if (len & 1) ++ *((u8 *)dest+len-1) = src[i] & 0xff; ++ } ++} ++ ++static struct map_info bcm47xx_map = { ++ name: "Physically mapped flash", ++ size : WINDOW_SIZE, ++ bankwidth : BUSWIDTH, ++ phys : WINDOW_ADDR, ++}; ++ ++static const char *probes[] = { "bcm47xx", NULL }; ++ ++static int bcm47xx_mtd_probe(struct platform_device *pdev) ++{ ++#ifdef CONFIG_BCM47XX_SSB ++ struct ssb_chipcommon *ssb_cc; ++#endif ++#ifdef CONFIG_BCM47XX_BCMA ++ struct bcma_drv_cc *bcma_cc; ++#endif ++ int ret = 0; ++ struct mtd_partition *partitions = NULL; ++ int num_partitions = 0; ++ ++ switch (bcm47xx_bus_type) { ++#ifdef CONFIG_BCM47XX_SSB ++ case BCM47XX_BUS_TYPE_SSB: ++ ssb_cc = &bcm47xx_bus.ssb.chipco; ++ if (ssb_cc->flash_type != SSB_PFLASH) ++ return -ENODEV; ++ ++ bcm47xx_map.phys = ssb_cc->pflash.window; ++ bcm47xx_map.size = ssb_cc->pflash.window_size; ++ bcm47xx_map.bankwidth = ssb_cc->pflash.buswidth; ++ break; ++#endif ++#ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++ bcma_cc = &bcm47xx_bus.bcma.bus.drv_cc; ++ if (bcma_cc->flash_type != BCMA_PFLASH) ++ return -ENODEV; ++ ++ bcm47xx_map.phys = bcma_cc->pflash.window; ++ bcm47xx_map.size = bcma_cc->pflash.window_size; ++ bcm47xx_map.bankwidth = bcma_cc->pflash.buswidth; ++ break; ++#endif ++ } ++ ++ pr_notice("flash init: 0x%08x 0x%08lx\n", bcm47xx_map.phys, bcm47xx_map.size); ++ bcm47xx_map.virt = ioremap_nocache(bcm47xx_map.phys, bcm47xx_map.size); ++ ++ if (!bcm47xx_map.virt) { ++ pr_err("Failed to ioremap\n"); ++ return -EIO; ++ } ++ ++ simple_map_init(&bcm47xx_map); ++ /* override copy_from routine */ ++ bcm47xx_map.copy_from = bcm47xx_map_copy_from; ++ ++ bcm47xx_mtd = do_map_probe("cfi_probe", &bcm47xx_map); ++ if (!bcm47xx_mtd) { ++ pr_err("Failed to do_map_probe\n"); ++ ret = -ENXIO; ++ goto err_unmap; ++ } ++ bcm47xx_mtd->owner = THIS_MODULE; ++ ++ pr_notice("Flash device: 0x%lx at 0x%x\n", bcm47xx_map.size, WINDOW_ADDR); ++ ++ num_partitions = parse_mtd_partitions(bcm47xx_mtd, probes, &partitions, 0); ++ if (num_partitions < 0) { ++ ret = num_partitions; ++ goto err_unmap; ++ } ++ ++ ret = mtd_device_register(bcm47xx_mtd, partitions, num_partitions); ++ ++// ret = mtd_device_parse_register(bcm47xx_mtd, "bcm47xx", NULL, NULL, 0); ++ ++ if (ret) { ++ pr_err("Flash: mtd_device_register failed\n"); ++ goto err_destroy; ++ } ++ return 0; ++ ++err_destroy: ++ map_destroy(bcm47xx_mtd); ++err_unmap: ++ iounmap(bcm47xx_map.virt); ++ return ret; ++} ++ ++static int __devexit bcm47xx_mtd_remove(struct platform_device *pdev) ++{ ++ mtd_device_unregister(bcm47xx_mtd); ++ map_destroy(bcm47xx_mtd); ++ iounmap(bcm47xx_map.virt); ++ return 0; ++} ++ ++static struct platform_driver bcm47xx_mtd_driver = { ++ .remove = __devexit_p(bcm47xx_mtd_remove), ++ .driver = { ++ .name = "bcm47xx_pflash", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init init_bcm47xx_mtd(void) ++{ ++ int ret = platform_driver_probe(&bcm47xx_mtd_driver, bcm47xx_mtd_probe); ++ ++ if (ret) ++ pr_err("error registering platform driver: %i\n", ret); ++ return ret; ++} ++ ++static void __exit exit_bcm47xx_mtd(void) ++{ ++ platform_driver_unregister(&bcm47xx_mtd_driver); ++} ++ ++module_init(init_bcm47xx_mtd); ++module_exit(exit_bcm47xx_mtd); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("BCM47XX parallel flash driver"); diff --git a/target/linux/brcm47xx/patches-3.0/0019-bcma-to-not-route-irqs-on-non-pci-devices.patch b/target/linux/brcm47xx/patches-3.0/0019-bcma-to-not-route-irqs-on-non-pci-devices.patch deleted file mode 100644 index 685dcdecfd..0000000000 --- a/target/linux/brcm47xx/patches-3.0/0019-bcma-to-not-route-irqs-on-non-pci-devices.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 1b23f310d4a7d24efe5dffbbde6b2b84252e2d7b Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens -Date: Fri, 22 Jul 2011 14:18:21 +0200 -Subject: [PATCH 19/22] bcma: to not route irqs on non pci devices - - -Signed-off-by: Hauke Mehrtens ---- - drivers/bcma/driver_pci.c | 9 ++++++++- - 1 files changed, 8 insertions(+), 1 deletions(-) - ---- a/drivers/bcma/driver_pci.c -+++ b/drivers/bcma/driver_pci.c -@@ -208,7 +208,14 @@ int bcma_core_pci_irq_ctl(struct bcma_dr - { - struct pci_dev *pdev = pc->core->bus->host_pci; - u32 coremask, tmp; -- int err; -+ int err = 0; -+ -+ if (core->bus->hosttype != BCMA_HOSTTYPE_PCI) { -+ /* This bcma device is not on a PCI host-bus. So the IRQs are -+ * not routed through the PCI core. -+ * So we must not enable routing through the PCI core. */ -+ goto out; -+ } - - err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp); - if (err) diff --git a/target/linux/brcm47xx/patches-3.0/0019-mtd-bcm47xx-add-serial-flash-driver.patch b/target/linux/brcm47xx/patches-3.0/0019-mtd-bcm47xx-add-serial-flash-driver.patch new file mode 100644 index 0000000000..d9f961081d --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0019-mtd-bcm47xx-add-serial-flash-driver.patch @@ -0,0 +1,330 @@ +From 6a615274708fff685952139fee00ebccc0cf3266 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sun, 17 Jul 2011 14:55:45 +0200 +Subject: [PATCH 19/26] mtd: bcm47xx: add serial flash driver + +sflash get the sflash ops from platform device + +Signed-off-by: Hauke Mehrtens +--- + arch/mips/include/asm/mach-bcm47xx/bus.h | 3 + + drivers/mtd/maps/Kconfig | 9 + + drivers/mtd/maps/Makefile | 1 + + drivers/mtd/maps/bcm47xx-sflash.c | 267 ++++++++++++++++++++++++++++++ + 4 files changed, 280 insertions(+), 0 deletions(-) + create mode 100644 drivers/mtd/maps/bcm47xx-sflash.c + +--- a/arch/mips/include/asm/mach-bcm47xx/bus.h ++++ b/arch/mips/include/asm/mach-bcm47xx/bus.h +@@ -11,6 +11,7 @@ + + #include + #include ++#include + #include + + struct bcm47xx_sflash { +@@ -29,6 +30,8 @@ struct bcm47xx_sflash { + u32 blocksize; /* Block size */ + u32 numblocks; /* Number of blocks */ + u32 size; /* Total size in bytes */ ++ ++ struct mtd_info *mtd; + }; + + void bcm47xx_sflash_struct_bcma_init(struct bcm47xx_sflash *sflash, struct bcma_drv_cc *bcc); +--- a/drivers/mtd/maps/Kconfig ++++ b/drivers/mtd/maps/Kconfig +@@ -273,6 +273,15 @@ config MTD_BCM47XX_PFLASH + help + Support for bcm47xx parallel flash + ++config MTD_BCM47XX_SFLASH ++ tristate "bcm47xx serial flash support" ++ default y ++ depends on BCM47XX ++ select MTD_PARTITIONS ++ select MTD_BCM47XX_PARTS ++ help ++ Support for bcm47xx parallel flash ++ + config MTD_DILNETPC + tristate "CFI Flash device mapped on DIL/Net PC" + depends on X86 && MTD_CFI_INTELEXT && BROKEN +--- a/drivers/mtd/maps/Makefile ++++ b/drivers/mtd/maps/Makefile +@@ -61,3 +61,4 @@ obj-$(CONFIG_MTD_BCM963XX) += bcm963xx-f + obj-$(CONFIG_MTD_LATCH_ADDR) += latch-addr-flash.o + obj-$(CONFIG_MTD_LANTIQ) += lantiq-flash.o + obj-$(CONFIG_MTD_BCM47XX_PFLASH)+= bcm47xx-pflash.o ++obj-$(CONFIG_MTD_BCM47XX_SFLASH)+= bcm47xx-sflash.o +--- /dev/null ++++ b/drivers/mtd/maps/bcm47xx-sflash.c +@@ -0,0 +1,267 @@ ++/* ++ * Broadcom SiliconBackplane chipcommon serial flash interface ++ * ++ * Copyright 2006, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY ++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM ++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS ++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. ++ * ++ * $Id$ ++ */ ++ ++#define pr_fmt(fmt) "bcm47xx_sflash: " fmt ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int ++sflash_mtd_poll(struct bcm47xx_sflash *sflash, unsigned int offset, int timeout) ++{ ++ unsigned long now = jiffies; ++ int ret = 0; ++ ++ for (;;) { ++ if (!sflash->poll(sflash, offset)) { ++ ret = 0; ++ break; ++ } ++ if (time_after(jiffies, now + timeout)) { ++ pr_err("timeout while polling\n"); ++ ret = -ETIMEDOUT; ++ break; ++ } ++ udelay(1); ++ } ++ ++ return ret; ++} ++ ++static int ++sflash_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) ++{ ++ struct bcm47xx_sflash *sflash = (struct bcm47xx_sflash *) mtd->priv; ++ ++ /* Check address range */ ++ if (!len) ++ return 0; ++ ++ if ((from + len) > mtd->size) ++ return -EINVAL; ++ ++ *retlen = 0; ++ ++ while (len) { ++ int ret = sflash->read(sflash, from, len, buf); ++ if (ret < 0) ++ return ret; ++ ++ from += (loff_t) ret; ++ len -= ret; ++ buf += ret; ++ *retlen += ret; ++ } ++ ++ return 0; ++} ++ ++static int ++sflash_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) ++{ ++ struct bcm47xx_sflash *sflash = (struct bcm47xx_sflash *) mtd->priv; ++ ++ /* Check address range */ ++ if (!len) ++ return 0; ++ ++ if ((to + len) > mtd->size) ++ return -EINVAL; ++ ++ *retlen = 0; ++ while (len) { ++ int bytes; ++ int ret = sflash->write(sflash, to, len, buf); ++ if (ret < 0) ++ return ret; ++ ++ bytes = ret; ++ ++ ret = sflash_mtd_poll(sflash, (unsigned int) to, HZ / 10); ++ if (ret) ++ return ret; ++ ++ to += (loff_t) bytes; ++ len -= bytes; ++ buf += bytes; ++ *retlen += bytes; ++ } ++ ++ return 0; ++} ++ ++static int ++sflash_mtd_erase(struct mtd_info *mtd, struct erase_info *erase) ++{ ++ struct bcm47xx_sflash *sflash = (struct bcm47xx_sflash *) mtd->priv; ++ int i, j, ret = 0; ++ unsigned int addr, len; ++ ++ /* Check address range */ ++ if (!erase->len) ++ return 0; ++ if ((erase->addr + erase->len) > mtd->size) ++ return -EINVAL; ++ ++ addr = erase->addr; ++ len = erase->len; ++ ++ /* Ensure that requested regions are aligned */ ++ for (i = 0; i < mtd->numeraseregions; i++) { ++ for (j = 0; j < mtd->eraseregions[i].numblocks; j++) { ++ if (addr == mtd->eraseregions[i].offset + ++ mtd->eraseregions[i].erasesize * j && ++ len >= mtd->eraseregions[i].erasesize) { ++ ret = sflash->erase(sflash, addr); ++ if (ret < 0) ++ break; ++ ret = sflash_mtd_poll(sflash, addr, 10 * HZ); ++ if (ret) ++ break; ++ addr += mtd->eraseregions[i].erasesize; ++ len -= mtd->eraseregions[i].erasesize; ++ } ++ } ++ if (ret) ++ break; ++ } ++ ++ /* Set erase status */ ++ if (ret) ++ erase->state = MTD_ERASE_FAILED; ++ else ++ erase->state = MTD_ERASE_DONE; ++ ++ /* Call erase callback */ ++ if (erase->callback) ++ erase->callback(erase); ++ ++ return ret; ++} ++ ++static const char *probes[] = { "bcm47xx", NULL }; ++ ++static int bcm47xx_sflash_probe(struct platform_device *pdev) ++{ ++ struct bcm47xx_sflash *sflash = dev_get_platdata(&pdev->dev); ++ struct mtd_info *mtd; ++ struct mtd_erase_region_info *regions; ++ int ret = 0; ++ ++ struct mtd_partition *parts; ++ int num_partitions = 0; ++ ++ mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); ++ if (!mtd) ++ return -ENOMEM; ++ ++ regions = kzalloc(sizeof(struct mtd_erase_region_info), GFP_KERNEL); ++ if (!mtd) ++ return -ENOMEM; ++ ++ pr_info("found serial flash: blocksize=%dKB, numblocks=%d, size=%dKB\n", ++ sflash->blocksize/1024, sflash->numblocks, sflash->size / 1024); ++ ++ /* Setup region info */ ++ regions->offset = 0; ++ regions->erasesize = sflash->blocksize; ++ regions->numblocks = sflash->numblocks; ++ if (regions->erasesize > mtd->erasesize) ++ mtd->erasesize = regions->erasesize; ++ mtd->size = sflash->size; ++ mtd->numeraseregions = 1; ++ ++ /* Register with MTD */ ++ mtd->name = "bcm47xx-sflash"; ++ mtd->type = MTD_NORFLASH; ++ mtd->flags = MTD_CAP_NORFLASH; ++ mtd->eraseregions = regions; ++ mtd->erase = sflash_mtd_erase; ++ mtd->read = sflash_mtd_read; ++ mtd->write = sflash_mtd_write; ++ mtd->writesize = 1; ++ mtd->priv = sflash; ++ mtd->owner = THIS_MODULE; ++ ++ num_partitions = parse_mtd_partitions(mtd, probes, &parts, 0); ++ if (num_partitions < 0) { ++ ret = num_partitions; ++ goto err_destroy; ++ } ++ ++ ret = mtd_device_register(mtd, parts, num_partitions); ++ ++// ret = mtd_device_parse_register(bcm47xx_mtd, "bcm47xx", NULL, NULL, 0); ++ ++ if (ret) { ++ pr_err("mtd_device_register failed\n"); ++ return ret; ++ } ++ sflash->mtd = mtd; ++ return 0; ++ ++err_destroy: ++ map_destroy(mtd); ++ return ret; ++} ++ ++static int __devexit bcm47xx_sflash_remove(struct platform_device *pdev) ++{ ++ struct bcm47xx_sflash *sflash = dev_get_platdata(&pdev->dev); ++ ++ if (sflash) { ++ mtd_device_unregister(sflash->mtd); ++ map_destroy(sflash->mtd); ++ kfree(sflash->mtd->eraseregions); ++ kfree(sflash->mtd); ++ } ++ return 0; ++} ++ ++static struct platform_driver bcm47xx_sflash_driver = { ++ .remove = __devexit_p(bcm47xx_sflash_remove), ++ .driver = { ++ .name = "bcm47xx_sflash", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init init_bcm47xx_sflash(void) ++{ ++ int ret = platform_driver_probe(&bcm47xx_sflash_driver, bcm47xx_sflash_probe); ++ ++ if (ret) ++ pr_err("error registering platform driver: %i\n", ret); ++ return ret; ++} ++ ++static void __exit exit_bcm47xx_sflash(void) ++{ ++ platform_driver_unregister(&bcm47xx_sflash_driver); ++} ++ ++module_init(init_bcm47xx_sflash); ++module_exit(exit_bcm47xx_sflash); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("BCM47XX parallel flash driver"); diff --git a/target/linux/brcm47xx/patches-3.0/0020-bcm47xx-register-flash-drivers.patch b/target/linux/brcm47xx/patches-3.0/0020-bcm47xx-register-flash-drivers.patch new file mode 100644 index 0000000000..9c57a62c36 --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0020-bcm47xx-register-flash-drivers.patch @@ -0,0 +1,100 @@ +From 64f3d068654589d6114048ac5933cd4498706cfc Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sun, 17 Jul 2011 15:02:10 +0200 +Subject: [PATCH 20/26] bcm47xx: register flash drivers + + +Signed-off-by: Hauke Mehrtens +--- + arch/mips/bcm47xx/setup.c | 72 +++++++++++++++++++++++++++++++++++++++++++++ + 1 files changed, 72 insertions(+), 0 deletions(-) + +--- a/arch/mips/bcm47xx/setup.c ++++ b/arch/mips/bcm47xx/setup.c +@@ -30,10 +30,12 @@ + #include + #include + #include ++#include + #include + #include + #include + #include ++#include + #include + + union bcm47xx_bus bcm47xx_bus; +@@ -365,3 +367,73 @@ static int __init bcm47xx_register_bus_c + return 0; + } + device_initcall(bcm47xx_register_bus_complete); ++ ++static struct resource bcm47xx_pflash_resource = { ++ .name = "bcm47xx_pflash", ++ .start = 0, ++ .end = 0, ++ .flags = 0, ++}; ++ ++static struct platform_device bcm47xx_pflash_dev = { ++ .name = "bcm47xx_pflash", ++ .resource = &bcm47xx_pflash_resource, ++ .num_resources = 1, ++}; ++ ++static struct resource bcm47xx_sflash_resource = { ++ .name = "bcm47xx_sflash", ++ .start = 0, ++ .end = 0, ++ .flags = 0, ++}; ++ ++static struct platform_device bcm47xx_sflash_dev = { ++ .name = "bcm47xx_sflash", ++ .resource = &bcm47xx_sflash_resource, ++ .num_resources = 1, ++}; ++ ++static int __init bcm47xx_register_flash(void) ++{ ++#ifdef CONFIG_BCM47XX_SSB ++ struct ssb_chipcommon *chipco; ++#endif ++#ifdef CONFIG_BCM47XX_BCMA ++ struct bcma_drv_cc *drv_cc; ++#endif ++ switch (bcm47xx_bus_type) { ++#ifdef CONFIG_BCM47XX_SSB ++ case BCM47XX_BUS_TYPE_SSB: ++ chipco = &bcm47xx_bus.ssb.chipco; ++ if (chipco->flash_type == SSB_PFLASH) { ++ bcm47xx_pflash_resource.start = chipco->pflash.window; ++ bcm47xx_pflash_resource.end = chipco->pflash.window + chipco->pflash.window_size; ++ return platform_device_register(&bcm47xx_pflash_dev); ++ } else if (chipco->flash_type == SSB_SFLASH) { ++ bcm47xx_sflash_dev.dev.platform_data = &bcm47xx_sflash; ++ return platform_device_register(&bcm47xx_sflash_dev); ++ } else { ++ printk(KERN_ERR "No flash device found\n"); ++ return -1; ++ } ++#endif ++#ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++ drv_cc = &bcm47xx_bus.bcma.bus.drv_cc; ++ if (drv_cc->flash_type == BCMA_PFLASH) { ++ bcm47xx_pflash_resource.start = drv_cc->pflash.window; ++ bcm47xx_pflash_resource.end = drv_cc->pflash.window + drv_cc->pflash.window_size; ++ return platform_device_register(&bcm47xx_pflash_dev); ++ } else if (drv_cc->flash_type == BCMA_SFLASH) { ++ bcm47xx_sflash_dev.dev.platform_data = &bcm47xx_sflash; ++ return platform_device_register(&bcm47xx_sflash_dev); ++ } else { ++ printk(KERN_ERR "No flash device found\n"); ++ return -1; ++ } ++#endif ++ } ++ return -1; ++} ++fs_initcall(bcm47xx_register_flash); diff --git a/target/linux/brcm47xx/patches-3.0/0020-bcma-small-fixes-needed-to-get-b43-up-with-SoC.patch b/target/linux/brcm47xx/patches-3.0/0020-bcma-small-fixes-needed-to-get-b43-up-with-SoC.patch deleted file mode 100644 index eea114cab1..0000000000 --- a/target/linux/brcm47xx/patches-3.0/0020-bcma-small-fixes-needed-to-get-b43-up-with-SoC.patch +++ /dev/null @@ -1,37 +0,0 @@ -From f3007275d7706afb1381adb0003f3ba69d359c8f Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens -Date: Fri, 22 Jul 2011 17:09:36 +0200 -Subject: [PATCH 20/22] bcma: small fixes needed to get b43 up with SoC - -When using an SoC these small cahnges are neede to get it up - -Signed-off-by: Hauke Mehrtens ---- - drivers/bcma/core.c | 2 ++ - drivers/bcma/main.c | 3 +++ - 2 files changed, 5 insertions(+), 0 deletions(-) - ---- a/drivers/bcma/core.c -+++ b/drivers/bcma/core.c -@@ -110,6 +110,8 @@ EXPORT_SYMBOL_GPL(bcma_core_pll_ctl); - u32 bcma_core_dma_translation(struct bcma_device *core) - { - switch (core->bus->hosttype) { -+ case BCMA_HOSTTYPE_SOC: -+ return 0; - case BCMA_HOSTTYPE_PCI: - if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64) - return BCMA_DMA_TRANSLATION_DMA64_CMT; ---- a/drivers/bcma/main.c -+++ b/drivers/bcma/main.c -@@ -99,7 +99,10 @@ static int bcma_register_cores(struct bc - core->irq = bus->host_pci->irq; - break; - case BCMA_HOSTTYPE_SDIO: -+ break; - case BCMA_HOSTTYPE_SOC: -+ core->dev.dma_mask = &core->dev.coherent_dma_mask; -+ core->dma_dev = &core->dev; - break; - } - diff --git a/target/linux/brcm47xx/patches-3.0/0021-add-workarround-for-wndr3400.patch b/target/linux/brcm47xx/patches-3.0/0021-add-workarround-for-wndr3400.patch new file mode 100644 index 0000000000..2cce8b97b9 --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0021-add-workarround-for-wndr3400.patch @@ -0,0 +1,51 @@ +From 3e889f1cf928c6d87229761a0bc4c18c775a988b Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sun, 17 Jul 2011 21:13:32 +0200 +Subject: [PATCH 21/26] add workarround for wndr3400 + + +Signed-off-by: Hauke Mehrtens +--- + drivers/mtd/bcm47xxpart.c | 17 ++++++++++++----- + 1 files changed, 12 insertions(+), 5 deletions(-) + +--- a/drivers/mtd/bcm47xxpart.c ++++ b/drivers/mtd/bcm47xxpart.c +@@ -78,11 +78,12 @@ struct trx_header { + + #define NVRAM_SPACE 0x8000 + +-#define ROUTER_NETGEAR_WGR614L 1 +-#define ROUTER_NETGEAR_WNR834B 2 +-#define ROUTER_NETGEAR_WNDR3300 3 +-#define ROUTER_NETGEAR_WNR3500L 4 +-#define ROUTER_SIMPLETECH_SIMPLESHARE 5 ++#define ROUTER_NETGEAR_WGR614L 1 ++#define ROUTER_NETGEAR_WNR834B 2 ++#define ROUTER_NETGEAR_WNDR3300 3 ++#define ROUTER_NETGEAR_WNR3500L 4 ++#define ROUTER_SIMPLETECH_SIMPLESHARE 5 ++#define ROUTER_NETGEAR_WNDR3400 6 + + static struct mtd_partition bcm47xx_parts[] = { + { name: "cfe", offset:0, size:0, mask_flags:MTD_WRITEABLE, }, +@@ -400,6 +401,11 @@ static int get_router(void) + return ROUTER_NETGEAR_WNR3500L; + } + ++ if (boardnum == 1 && boardtype == 0xb4cf && boardrev == 0x1100) { ++ /* Netgear WNDR3400 */ ++ return ROUTER_NETGEAR_WNDR3400; ++ } ++ + if (boardtype == 0x042f + && boardrev == 0x10 + && boardflags == 0 +@@ -440,6 +446,7 @@ static int parse_bcm47xx_partitions(stru + case ROUTER_NETGEAR_WNR834B: + case ROUTER_NETGEAR_WNDR3300: + case ROUTER_NETGEAR_WNR3500L: ++ case ROUTER_NETGEAR_WNDR3400: + /* Netgear: checksum is @ 0x003AFFF8 for 4M flash or checksum + * is @ 0x007AFFF8 for 8M flash + */ diff --git a/target/linux/brcm47xx/patches-3.0/0022-bcma-use-randoom-mac-address-as-long-as-reading-it-o.patch b/target/linux/brcm47xx/patches-3.0/0022-bcma-use-randoom-mac-address-as-long-as-reading-it-o.patch deleted file mode 100644 index ca57a3c1b2..0000000000 --- a/target/linux/brcm47xx/patches-3.0/0022-bcma-use-randoom-mac-address-as-long-as-reading-it-o.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 6dd27601bee9b3c26cdb67246b6da51dd696ac34 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens -Date: Fri, 22 Jul 2011 17:11:51 +0200 -Subject: [PATCH 22/22] bcma: use randoom mac address as long as reading it out does not work - - -Signed-off-by: Hauke Mehrtens ---- - drivers/bcma/sprom.c | 5 ++++- - 1 files changed, 4 insertions(+), 1 deletions(-) - ---- a/drivers/bcma/sprom.c -+++ b/drivers/bcma/sprom.c -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - - #define SPOFF(offset) ((offset) / sizeof(u16)) - -@@ -144,8 +145,10 @@ int bcma_sprom_get(struct bcma_bus *bus) - if (!bus->drv_cc.core) - return -EOPNOTSUPP; - -- if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM)) -+ if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM)) { -+ random_ether_addr(bus->sprom.il0mac); - return -ENOENT; -+ } - - sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), - GFP_KERNEL); diff --git a/target/linux/brcm47xx/patches-3.0/0023-bcma-use-randoom-mac-address-as-long-as-reading-it-o.patch b/target/linux/brcm47xx/patches-3.0/0023-bcma-use-randoom-mac-address-as-long-as-reading-it-o.patch new file mode 100644 index 0000000000..d83ad5326e --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0023-bcma-use-randoom-mac-address-as-long-as-reading-it-o.patch @@ -0,0 +1,33 @@ +From e6730c06cfc827d715f43e9bd276ae939bb86af9 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Fri, 22 Jul 2011 17:11:51 +0200 +Subject: [PATCH 23/26] bcma: use randoom mac address as long as reading it out does not work + + +Signed-off-by: Hauke Mehrtens +--- + drivers/bcma/sprom.c | 5 ++++- + 1 files changed, 4 insertions(+), 1 deletions(-) + +--- a/drivers/bcma/sprom.c ++++ b/drivers/bcma/sprom.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + + #define SPOFF(offset) ((offset) / sizeof(u16)) + +@@ -144,8 +145,10 @@ int bcma_sprom_get(struct bcma_bus *bus) + if (!bus->drv_cc.core) + return -EOPNOTSUPP; + +- if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM)) ++ if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM)) { ++ random_ether_addr(bus->sprom.il0mac); + return -ENOENT; ++ } + + sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), + GFP_KERNEL); diff --git a/target/linux/brcm47xx/patches-3.0/0025-bcm47xx-read-nvram-from-sflash.patch b/target/linux/brcm47xx/patches-3.0/0025-bcm47xx-read-nvram-from-sflash.patch new file mode 100644 index 0000000000..d3781b8fe5 --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0025-bcm47xx-read-nvram-from-sflash.patch @@ -0,0 +1,118 @@ +From 1d693b2c9d5943cbe938f879041b837cd004737f Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sat, 23 Jul 2011 18:29:38 +0200 +Subject: [PATCH 25/26] bcm47xx: read nvram from sflash + +bcm47xx: add sflash support to nvram + +Signed-off-by: Hauke Mehrtens +--- + arch/mips/bcm47xx/nvram.c | 86 +++++++++++++++++++++++++++++++++++++++++++- + 1 files changed, 84 insertions(+), 2 deletions(-) + +--- a/arch/mips/bcm47xx/nvram.c ++++ b/arch/mips/bcm47xx/nvram.c +@@ -20,11 +20,12 @@ + #include + #include + #include ++#include + + static char nvram_buf[NVRAM_SPACE]; + + /* Probe for NVRAM header */ +-static void early_nvram_init(void) ++static void early_nvram_init_pflash(void) + { + #ifdef CONFIG_BCM47XX_SSB + struct ssb_chipcommon *ssb_cc; +@@ -86,7 +87,88 @@ found: + for (i = 0; i < sizeof(struct nvram_header); i += 4) + *dst++ = *src++; + for (; i < header->len && i < NVRAM_SPACE; i += 4) +- *dst++ = le32_to_cpu(*src++); ++ *dst++ = *src++; ++} ++ ++static int early_nvram_init_sflash(void) ++{ ++ struct nvram_header header; ++ u32 off; ++ int ret; ++ char *dst; ++ int len; ++ ++ /* check if the struct is already initilized */ ++ if (!bcm47xx_sflash.size) ++ return -1; ++ ++ off = FLASH_MIN; ++ while (off <= bcm47xx_sflash.size) { ++ ret = bcm47xx_sflash.read(&bcm47xx_sflash, off - NVRAM_SPACE, sizeof(header), (u8 *)&header); ++ if (ret != sizeof(header)) ++ return ret; ++ if (header.magic == NVRAM_HEADER) ++ goto found; ++ off <<= 1; ++ } ++ ++ off = FLASH_MIN; ++ while (off <= bcm47xx_sflash.size) { ++ ret = bcm47xx_sflash.read(&bcm47xx_sflash, off - (2 * NVRAM_SPACE), sizeof(header), (u8 *)&header); ++ if (ret != sizeof(header)) ++ return ret; ++ if (header.magic == NVRAM_HEADER) ++ goto found; ++ off <<= 1; ++ } ++ return -1; ++ ++found: ++ len = NVRAM_SPACE; ++ dst = nvram_buf; ++ while (len) { ++ ret = bcm47xx_sflash.read(&bcm47xx_sflash, off - (2 * NVRAM_SPACE), len, dst); ++ if (ret < 0) ++ return ret; ++ off += ret; ++ len -= ret; ++ dst += ret; ++ } ++ return 0; ++} ++ ++static void early_nvram_init(void) ++{ ++ int err = 0; ++ ++ switch (bcm47xx_bus_type) { ++#ifdef CONFIG_BCM47XX_SSB ++ case BCM47XX_BUS_TYPE_SSB: ++ if (bcm47xx_bus.ssb.chipco.flash_type == SSB_PFLASH) { ++ early_nvram_init_pflash(); ++ } else if (bcm47xx_bus.ssb.chipco.flash_type == SSB_SFLASH) { ++ err = early_nvram_init_sflash(); ++ if (err < 0) ++ printk(KERN_WARNING "can not read from flash: %i\n", err); ++ } else { ++ printk(KERN_WARNING "unknow flash type\n"); ++ } ++ break; ++#endif ++#ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++ if (bcm47xx_bus.bcma.bus.drv_cc.flash_type == BCMA_PFLASH) { ++ early_nvram_init_pflash(); ++ } else if (bcm47xx_bus.bcma.bus.drv_cc.flash_type == BCMA_SFLASH) { ++ err = early_nvram_init_sflash(); ++ if (err < 0) ++ printk(KERN_WARNING "can not read from flash: %i\n", err); ++ } else { ++ printk(KERN_WARNING "unknow flash type\n"); ++ } ++ break; ++#endif ++ } + } + + int nvram_getenv(char *name, char *val, size_t val_len) diff --git a/target/linux/brcm47xx/patches-3.0/0026-bcma-export-needed-gpio-functions.patch b/target/linux/brcm47xx/patches-3.0/0026-bcma-export-needed-gpio-functions.patch new file mode 100644 index 0000000000..7c8cd79635 --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0026-bcma-export-needed-gpio-functions.patch @@ -0,0 +1,47 @@ +From f6e41db3ee7ead99e1398def222c14893fc265de Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Thu, 4 Aug 2011 21:09:48 +0200 +Subject: [PATCH 26/26] bcma: export needed gpio functions + + +Signed-off-by: Hauke Mehrtens +--- + drivers/bcma/driver_chipcommon.c | 5 +++++ + 1 files changed, 5 insertions(+), 0 deletions(-) + +--- a/drivers/bcma/driver_chipcommon.c ++++ b/drivers/bcma/driver_chipcommon.c +@@ -80,16 +80,19 @@ u32 bcma_chipco_gpio_in(struct bcma_drv_ + { + return bcma_cc_read32(cc, BCMA_CC_GPIOIN) & mask; + } ++EXPORT_SYMBOL_GPL(bcma_chipco_gpio_in); + + u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value) + { + return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value); + } ++EXPORT_SYMBOL_GPL(bcma_chipco_gpio_out); + + u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value) + { + return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value); + } ++EXPORT_SYMBOL_GPL(bcma_chipco_gpio_outen); + + u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value) + { +@@ -101,11 +104,13 @@ u32 bcma_chipco_gpio_intmask(struct bcma + { + return bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value); + } ++EXPORT_SYMBOL_GPL(bcma_chipco_gpio_intmask); + + u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value) + { + return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value); + } ++EXPORT_SYMBOL_GPL(bcma_chipco_gpio_polarity); + + #ifdef CONFIG_BCMA_DRIVER_MIPS + void bcma_chipco_serial_init(struct bcma_drv_cc *cc) diff --git a/target/linux/brcm47xx/patches-3.0/014-MIPS-BCM47xx-Setup-and-register-serial-early.patch b/target/linux/brcm47xx/patches-3.0/014-MIPS-BCM47xx-Setup-and-register-serial-early.patch index 428582891e..0951644412 100644 --- a/target/linux/brcm47xx/patches-3.0/014-MIPS-BCM47xx-Setup-and-register-serial-early.patch +++ b/target/linux/brcm47xx/patches-3.0/014-MIPS-BCM47xx-Setup-and-register-serial-early.patch @@ -24,7 +24,7 @@ Signed-off-by: Hauke Mehrtens #include #include #include -@@ -275,6 +277,31 @@ static int bcm47xx_get_invariants(struct +@@ -278,6 +280,31 @@ static int bcm47xx_get_invariants(struct return 0; } @@ -56,7 +56,7 @@ Signed-off-by: Hauke Mehrtens static void __init bcm47xx_register_ssb(void) { int err; -@@ -304,6 +331,10 @@ static void __init bcm47xx_register_ssb( +@@ -310,6 +337,10 @@ static void __init bcm47xx_register_ssb( memcpy(&mcore->serial_ports[1], &port, sizeof(port)); } } diff --git a/target/linux/brcm47xx/patches-3.0/220-bcm5354.patch b/target/linux/brcm47xx/patches-3.0/220-bcm5354.patch index d68534fb65..7d7ca8e969 100644 --- a/target/linux/brcm47xx/patches-3.0/220-bcm5354.patch +++ b/target/linux/brcm47xx/patches-3.0/220-bcm5354.patch @@ -20,7 +20,7 @@ switch (*plltype) { --- a/drivers/ssb/driver_mipscore.c +++ b/drivers/ssb/driver_mipscore.c -@@ -217,6 +217,8 @@ u32 ssb_cpu_clock(struct ssb_mipscore *m +@@ -234,6 +234,8 @@ u32 ssb_cpu_clock(struct ssb_mipscore *m if ((pll_type == SSB_PLLTYPE_5) || (bus->chip_id == 0x5365)) { rate = 200000000; diff --git a/target/linux/brcm47xx/patches-3.0/280-activate_ssb_support_in_usb.patch b/target/linux/brcm47xx/patches-3.0/280-activate_ssb_support_in_usb.patch index 1a50c1a9dc..d3a8817bac 100644 --- a/target/linux/brcm47xx/patches-3.0/280-activate_ssb_support_in_usb.patch +++ b/target/linux/brcm47xx/patches-3.0/280-activate_ssb_support_in_usb.patch @@ -5,7 +5,7 @@ This prevents the options from being delete with make kernel_oldconfig. --- a/drivers/ssb/Kconfig +++ b/drivers/ssb/Kconfig -@@ -141,6 +141,8 @@ config SSB_DRIVER_MIPS +@@ -147,6 +147,8 @@ config SSB_SFLASH config SSB_EMBEDDED bool depends on SSB_DRIVER_MIPS diff --git a/target/linux/brcm47xx/patches-3.0/400-arch-bcm47xx.patch b/target/linux/brcm47xx/patches-3.0/400-arch-bcm47xx.patch index fe23dc61cd..46d47e3d01 100644 --- a/target/linux/brcm47xx/patches-3.0/400-arch-bcm47xx.patch +++ b/target/linux/brcm47xx/patches-3.0/400-arch-bcm47xx.patch @@ -1,6 +1,6 @@ --- a/arch/mips/bcm47xx/nvram.c +++ b/arch/mips/bcm47xx/nvram.c -@@ -117,3 +117,30 @@ int nvram_getenv(char *name, char *val, +@@ -199,3 +199,30 @@ int nvram_getenv(char *name, char *val, return NVRAM_ERR_ENVNOTFOUND; } EXPORT_SYMBOL(nvram_getenv); @@ -33,8 +33,8 @@ +EXPORT_SYMBOL(nvram_get); --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c -@@ -438,3 +438,20 @@ static int __init bcm47xx_register_flash - return 0; +@@ -468,3 +468,20 @@ static int __init bcm47xx_register_flash + return -1; } fs_initcall(bcm47xx_register_flash); + diff --git a/target/linux/brcm47xx/patches-3.0/812-disable_wgt634u_crap.patch b/target/linux/brcm47xx/patches-3.0/812-disable_wgt634u_crap.patch index 39a765b5fe..6bc34549fe 100644 --- a/target/linux/brcm47xx/patches-3.0/812-disable_wgt634u_crap.patch +++ b/target/linux/brcm47xx/patches-3.0/812-disable_wgt634u_crap.patch @@ -3,7 +3,7 @@ @@ -4,4 +4,3 @@ # - obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o + obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o bus.o -obj-$(CONFIG_BCM47XX_SSB) += wgt634u.o --- a/arch/mips/bcm47xx/wgt634u.c +++ /dev/null @@ -144,7 +144,7 @@ - */ - u8 *et0mac; - -- if (bcm47xx_active_bus_type != BCM47XX_BUS_TYPE_SSB) +- if (bcm47xx_bus_type != BCM47XX_BUS_TYPE_SSB) - return -ENODEV; - - et0mac = bcm47xx_bus.ssb.sprom.et0mac; @@ -166,10 +166,10 @@ - SSB_CHIPCO_IRQ_GPIO); - } - -- wgt634u_flash_data.width = mcore->flash_buswidth; -- wgt634u_flash_resource.start = mcore->flash_window; -- wgt634u_flash_resource.end = mcore->flash_window -- + mcore->flash_window_size +- wgt634u_flash_data.width = mcore->pflash.buswidth; +- wgt634u_flash_resource.start = mcore->pflash.window; +- wgt634u_flash_resource.end = mcore->pflash.window +- + mcore->pflash.window_size - - 1; - return platform_add_devices(wgt634u_devices, - ARRAY_SIZE(wgt634u_devices)); diff --git a/target/linux/brcm47xx/patches-3.0/820-wgt634u-nvram-fix.patch b/target/linux/brcm47xx/patches-3.0/820-wgt634u-nvram-fix.patch index 8fc2e0205c..88a40e2bc3 100644 --- a/target/linux/brcm47xx/patches-3.0/820-wgt634u-nvram-fix.patch +++ b/target/linux/brcm47xx/patches-3.0/820-wgt634u-nvram-fix.patch @@ -9,8 +9,8 @@ out the configuration than the in kernel cfe config reader. # under Linux. # --obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o -+obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o cfe_env.o +-obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o bus.o ++obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o bus.o cfe_env.o --- /dev/null +++ b/arch/mips/bcm47xx/cfe_env.c @@ -0,0 +1,229 @@ @@ -245,16 +245,16 @@ out the configuration than the in kernel cfe config reader. + --- a/arch/mips/bcm47xx/nvram.c +++ b/arch/mips/bcm47xx/nvram.c -@@ -22,6 +22,8 @@ - #include +@@ -23,6 +23,8 @@ + #include static char nvram_buf[NVRAM_SPACE]; +static int cfe_env; +extern char *cfe_env_get(char *nv_buf, const char *name); /* Probe for NVRAM header */ - static void early_nvram_init(void) -@@ -58,6 +60,25 @@ static void early_nvram_init(void) + static void early_nvram_init_pflash(void) +@@ -59,6 +61,25 @@ static void early_nvram_init_pflash(void break; #endif } @@ -280,7 +280,7 @@ out the configuration than the in kernel cfe config reader. off = FLASH_MIN; while (off <= lim) { -@@ -99,6 +120,12 @@ int nvram_getenv(char *name, char *val, +@@ -181,6 +202,12 @@ int nvram_getenv(char *name, char *val, if (!nvram_buf[0]) early_nvram_init(); @@ -293,7 +293,7 @@ out the configuration than the in kernel cfe config reader. /* Look for name=value and return value */ var = &nvram_buf[sizeof(struct nvram_header)]; end = nvram_buf + sizeof(nvram_buf) - 2; -@@ -128,6 +155,9 @@ char *nvram_get(const char *name) +@@ -210,6 +237,9 @@ char *nvram_get(const char *name) if (!nvram_buf[0]) early_nvram_init(); diff --git a/target/linux/brcm47xx/patches-3.0/900-bcm47xx_wdt-noprescale.patch b/target/linux/brcm47xx/patches-3.0/900-bcm47xx_wdt-noprescale.patch index d259dcf160..d60247e91a 100644 --- a/target/linux/brcm47xx/patches-3.0/900-bcm47xx_wdt-noprescale.patch +++ b/target/linux/brcm47xx/patches-3.0/900-bcm47xx_wdt-noprescale.patch @@ -18,7 +18,7 @@ +static inline void bcm47xx_wdt_hw_start(u32 ticks) { - /* this is 2,5s on 100Mhz clock and 2s on 133 Mhz */ - switch (bcm47xx_active_bus_type) { + switch (bcm47xx_bus_type) { #ifdef CONFIG_BCM47XX_SSB case BCM47XX_BUS_TYPE_SSB: - ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0xfffffff); @@ -87,7 +87,7 @@ - setup_timer(&wdt_timer, bcm47xx_timer_tick, 0L); + /* FIXME Other cores */ +#ifdef BCM47XX_BUS_TYPE_BCMA -+ if(bcm47xx_active_bus_type == BCM47XX_BUS_TYPE_BCMA && ++ if(bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA && + bcm47xx_bus.ssb.chip_id == 0x5354) { + /* Slow WDT clock, no pre-scaling */ + needs_sw_scale = 0; diff --git a/target/linux/brcm47xx/patches-3.0/980-wnr834b_no_cardbus_invariant.patch b/target/linux/brcm47xx/patches-3.0/980-wnr834b_no_cardbus_invariant.patch index 75b59944de..019b9932bd 100644 --- a/target/linux/brcm47xx/patches-3.0/980-wnr834b_no_cardbus_invariant.patch +++ b/target/linux/brcm47xx/patches-3.0/980-wnr834b_no_cardbus_invariant.patch @@ -1,6 +1,6 @@ --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c -@@ -274,6 +274,10 @@ static int bcm47xx_get_invariants(struct +@@ -277,6 +277,10 @@ static int bcm47xx_get_invariants(struct if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0) iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10); diff --git a/target/linux/brcm47xx/patches-3.0/999-wl_exports.patch b/target/linux/brcm47xx/patches-3.0/999-wl_exports.patch index e93dcce4f9..b3aa126753 100644 --- a/target/linux/brcm47xx/patches-3.0/999-wl_exports.patch +++ b/target/linux/brcm47xx/patches-3.0/999-wl_exports.patch @@ -1,8 +1,8 @@ --- a/arch/mips/bcm47xx/nvram.c +++ b/arch/mips/bcm47xx/nvram.c -@@ -21,7 +21,8 @@ - #include +@@ -22,7 +22,8 @@ #include + #include -static char nvram_buf[NVRAM_SPACE]; +char nvram_buf[NVRAM_SPACE]; -- cgit v1.2.3