brcm47xx: update patches

* this adds sflash support for ssb devices
* the flash is now a platform device
* minor updates

SVN-Revision: 27902
v19.07.3_mercusys_ac12_duma
Hauke Mehrtens 13 years ago
parent 85b858fae6
commit 8428ebd8e8

@ -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;
}

@ -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:

@ -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 <hauke@hauke-m.de>
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

@ -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 <hauke@hauke-m.de>
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

@ -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 <hauke@hauke-m.de>
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

@ -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 <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
---
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 <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
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

@ -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 <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
/* 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);
}

@ -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 <hauke@hauke-m.de>
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.

@ -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 <hauke@hauke-m.de>
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.

@ -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 <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
- 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 <hauke@hauke-m.de>
- 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 <hauke@hauke-m.de>
- 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 <hauke@hauke-m.de>
- 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 <hauke@hauke-m.de>
+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 <hauke@hauke-m.de>
+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 <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
/* 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 <hauke@hauke-m.de>
+{
+ struct cpuinfo_mips *c = &current_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 <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
+ 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 <hauke@hauke-m.de>
+};
+
+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 <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
{
- 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 <hauke@hauke-m.de>
- /* 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 <hauke@hauke-m.de>
- 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 <hauke@hauke-m.de>
- 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 <hauke@hauke-m.de>
{
/* 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 <hauke@hauke-m.de>
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);
+ }

@ -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 <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
@ -82,7 +82,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
@@ -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 <hauke@hauke-m.de>
@@ -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 <hauke@hauke-m.de>
@@ -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 <hauke@hauke-m.de>
@@ -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 <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
@@ -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 <hauke@hauke-m.de>
@@ -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 <hauke@hauke-m.de>
struct cpuinfo_mips *c = &current_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 <hauke@hauke-m.de>
@@ -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 <hauke@hauke-m.de>
@@ -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 <hauke@hauke-m.de>
@@ -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 <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
@@ -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 <hauke@hauke-m.de>
@@ -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 <hauke@hauke-m.de>
@@ -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 <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
@@ -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 <hauke@hauke-m.de>
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);

@ -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 <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
+
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 <hauke@hauke-m.de>
+ 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 <hauke@hauke-m.de>
+
+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 */

@ -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 <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
---
@ -23,7 +23,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
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);
+ /*

@ -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 <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
---
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 <hauke@hauke-m.de>
/* 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 <hauke@hauke-m.de>
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];

@ -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 <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
@ -9,10 +9,10 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
+{
+ 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 <hauke@hauke-m.de>
+{
+ 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 <hauke@hauke-m.de>
+ 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 <hauke@hauke-m.de>
+ * 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 <hauke@hauke-m.de>
+ /* 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 <hauke@hauke-m.de>
+ /* 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 <hauke@hauke-m.de>
+ 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 <hauke@hauke-m.de>
+ 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 <hauke@hauke-m.de>
+/* 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 <hauke@hauke-m.de>
+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 <hauke@hauke-m.de>
+ 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 <hauke@hauke-m.de>
+{
+ 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 <hauke@hauke-m.de>
+ 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 <hauke@hauke-m.de>
+ 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 <hauke@hauke-m.de>
};
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 <hauke@hauke-m.de>
+};
+#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);

@ -0,0 +1,143 @@
From be495ba9c365a31cf6a9fa0f67df9a9a9e0f1a1f Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sat, 23 Jul 2011 23:57:06 +0200
Subject: [PATCH 14/26] ssb: move flash to chipcommon
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
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);

@ -0,0 +1,697 @@
From 980da78179592a3f5f99168bc5af415835aa8c13 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 24 Jul 2011 20:20:36 +0200
Subject: [PATCH 15/26] ssb: add serial flash support
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
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 <jonas.gorski@gmail.com>
+ * Copyright 2010, Broadcom Corporation
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include <linux/ssb/ssb.h>
+#include <linux/ssb/ssb_driver_chipcommon.h>
+#include <linux/delay.h>
+
+#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);

@ -0,0 +1,193 @@
From 4f314ac9edbc80897f158fdb4e1b1de8a2d0d432 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 24 Jul 2011 21:10:49 +0200
Subject: [PATCH 16/26] brcm47xx: add common interface for sflash
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
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 <hauke@hauke-m.de>
+ *
+ * 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 <bus.h>
+
+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 <hauke@hauke-m.de>
+ *
+ * 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 <linux/ssb/ssb.h>
+#include <linux/bcma/bcma.h>
+#include <bcm47xx.h>
+
+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;

@ -1,74 +0,0 @@
From 89b904335338c86ef2c40e7cc51e19673feb62c1 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 17 Jul 2011 15:02:10 +0200
Subject: [PATCH 17/22] bcm47xx: register flash drivers
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
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 <linux/ssb/ssb.h>
#include <linux/ssb/ssb_embedded.h>
#include <linux/bcma/bcma_soc.h>
+#include <linux/platform_device.h>
#include <asm/bootinfo.h>
#include <asm/reboot.h>
#include <asm/time.h>
@@ -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);

@ -1,7 +1,7 @@
From 4b449ce15d74e5973cde18381c2a3fa0616b2b3d Mon Sep 17 00:00:00 2001
From 1934b89b42976a083c2ad8d8fdc526ab5b05c5e4 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 17 Jul 2011 14:54:11 +0200
Subject: [PATCH 14/18] mtd: bcm47xx: add bcm47xx part parser
Subject: [PATCH 17/26] mtd: bcm47xx: add bcm47xx part parser
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
@ -46,7 +46,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ * Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
+ * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
+ *
+ * original functions for finding root filesystem from Mike Baker
+ * 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
@ -67,10 +67,10 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ * 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
@ -89,7 +89,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/crc32.h>
+#include <asm/io.h>
+#include <linux/io.h>
+#include <asm/mach-bcm47xx/nvram.h>
+#include <asm/mach-bcm47xx/bcm47xx.h>
+#include <asm/fw/cfe/cfe_api.h>
@ -98,7 +98,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+#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_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
+
@ -128,10 +128,10 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+#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: "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, },
+};
@ -155,7 +155,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ memset(buf, 0xe5, sizeof(buf));
+
+ /*
+ * Read into buffer
+ * Read into buffer
+ */
+ if (mtd->read(mtd, off, sizeof(buf), &len, buf) ||
+ len != sizeof(buf))
@ -171,9 +171,8 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ }
+
+ /* found a TRX header */
+ if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
+ if (le32_to_cpu(trx->magic) == TRX_MAGIC)
+ goto found;
+ }
+ }
+
+ pr_notice("%s: Couldn't find bootloader size\n", mtd->name);
@ -189,7 +188,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ * 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
@ -203,7 +202,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ wake_up(wait_q);
+}
+
+static int erase_write (struct mtd_info *mtd, unsigned long pos,
+static int erase_write(struct mtd_info *mtd, unsigned long pos,
+ int len, const char *buf)
+{
+ struct erase_info erase;
@ -242,7 +241,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ * Next, write data to flash.
+ */
+
+ ret = mtd->write (mtd, pos, len, &retlen, buf);
+ ret = mtd->write(mtd, pos, len, &retlen, buf);
+ if (ret)
+ return ret;
+ if (retlen != len)
@ -252,7 +251,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+
+
+static int
+find_dual_image_off (struct mtd_info *mtd)
+find_dual_image_off(struct mtd_info *mtd)
+{
+ struct trx_header trx;
+ int off, blocksize;
@ -265,14 +264,14 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ for (off = (128*1024); off < mtd->size; off += blocksize) {
+ memset(&trx, 0xe5, sizeof(trx));
+ /*
+ * Read into buffer
+ * 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){
+ 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 {
@ -302,7 +301,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ memset(&trx, 0xe5, sizeof(trx));
+
+ /*
+ * Read into buffer
+ * Read into buffer
+ */
+ if (mtd->read(mtd, off, sizeof(trx), &len, (char *) &trx) ||
+ len != sizeof(trx))
@ -323,9 +322,9 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+
+ /* found a TRX header */
+ if (le32_to_cpu(trx.magic) == TRX_MAGIC) {
+ part->offset = le32_to_cpu(trx.offsets[2]) ? :
+ part->offset = le32_to_cpu(trx.offsets[2]) ? :
+ le32_to_cpu(trx.offsets[1]);
+ part->size = le32_to_cpu(trx.len);
+ part->size = le32_to_cpu(trx.len);
+
+ part->size -= part->offset;
+ part->offset += off;
@ -346,7 +345,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ 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;
+
@ -356,7 +355,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ 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))
@ -372,7 +371,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ 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);
@ -387,7 +386,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ kfree(block);
+ pr_notice("Done\n");
+ }
+
+
+ return part->size;
+}
+
@ -446,8 +445,8 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+
+ if (boardtype == 0x042f
+ && boardrev == 0x10
+ && boardflags == 0
+ && strev == 0x11) {
+ && boardflags == 0
+ && strev == 0x11) {
+ /* Simpletech Simpleshare */
+ return ROUTER_SIMPLETECH_SIMPLESHARE;
+ }
@ -468,7 +467,8 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ */
+ int custom_data_size = 0;
+
+ if ((cfe_size = find_cfe_size(mtd)) < 0)
+ cfe_size = find_cfe_size(mtd);
+ if (cfe_size < 0)
+ return 0;
+
+ /* boot loader */
@ -525,7 +525,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+
+ /* dual image offset*/
+ pr_notice("Looking for dual image\n");
+ dual_image_offset=find_dual_image_off(mtd);
+ dual_image_offset = find_dual_image_off(mtd);
+ /* linux (kernel and rootfs) */
+ if (cfe_size != 384 * 1024) {
+ if (get_router() == ROUTER_SIMPLETECH_SIMPLESHARE) {
@ -539,11 +539,11 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ }
+ } else {
+ /* do not count the elf loader, which is on one block */
+ bcm47xx_parts[1].offset = bcm47xx_parts[0].size +
+ 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) -
+ bcm47xx_parts[1].size = mtd->size -
+ bcm47xx_parts[0].size -
+ (2*bcm47xx_parts[3].size) -
+ mtd->erasesize - custom_data_size;
+ }
+

@ -1,15 +1,15 @@
From 941c7a12af5d985c9dabc6813db3b75908bd619c Mon Sep 17 00:00:00 2001
From fb261916ee9cd9eede57f6255ffd39e4145da48e Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 17 Jul 2011 14:55:18 +0200
Subject: [PATCH 15/22] mtd: bcm47xx: add parallel flash driver
Subject: [PATCH 18/26] mtd: bcm47xx: add parallel flash driver
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
drivers/mtd/maps/Kconfig | 9 ++
drivers/mtd/maps/Makefile | 1 +
drivers/mtd/maps/bcm47xx-pflash.c | 196 +++++++++++++++++++++++++++++++++++++
3 files changed, 206 insertions(+), 0 deletions(-)
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
@ -39,13 +39,13 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+obj-$(CONFIG_MTD_BCM47XX_PFLASH)+= bcm47xx-pflash.o
--- /dev/null
+++ b/drivers/mtd/maps/bcm47xx-pflash.c
@@ -0,0 +1,196 @@
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
+ * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
+ *
+ * original functions for finding root filesystem from Mike Baker
+ * 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
@ -66,10 +66,10 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ * 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
@ -87,7 +87,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <asm/io.h>
+#include <linux/io.h>
+#include <asm/mach-bcm47xx/bcm47xx.h>
+#include <linux/platform_device.h>
+
@ -99,15 +99,14 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+
+static void bcm47xx_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
+{
+ if (len==1) {
+ 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++) {
+ for (i = 0; i < (len / 2); i++)
+ dest[i] = src[i];
+ }
+ if (len & 1)
+ *((u8 *)dest+len-1) = src[i] & 0xff;
+ }
@ -115,9 +114,9 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+
+static struct map_info bcm47xx_map = {
+ name: "Physically mapped flash",
+ size: WINDOW_SIZE,
+ bankwidth: BUSWIDTH,
+ phys: WINDOW_ADDR,
+ size : WINDOW_SIZE,
+ bankwidth : BUSWIDTH,
+ phys : WINDOW_ADDR,
+};
+
+static const char *probes[] = { "bcm47xx", NULL };
@ -125,7 +124,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+static int bcm47xx_mtd_probe(struct platform_device *pdev)
+{
+#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;
@ -134,13 +133,16 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ struct mtd_partition *partitions = NULL;
+ int num_partitions = 0;
+
+ switch (bcm47xx_active_bus_type) {
+ switch (bcm47xx_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;
+ 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
@ -149,9 +151,9 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ 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;
+ bcm47xx_map.phys = bcma_cc->pflash.window;
+ bcm47xx_map.size = bcma_cc->pflash.window_size;
+ bcm47xx_map.bankwidth = bcma_cc->pflash.buswidth;
+ break;
+#endif
+ }
@ -166,7 +168,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+
+ simple_map_init(&bcm47xx_map);
+ /* override copy_from routine */
+ bcm47xx_map.copy_from = bcm47xx_map_copy_from;
+ bcm47xx_map.copy_from = bcm47xx_map_copy_from;
+
+ bcm47xx_mtd = do_map_probe("cfi_probe", &bcm47xx_map);
+ if (!bcm47xx_mtd) {

@ -1,29 +0,0 @@
From 1b23f310d4a7d24efe5dffbbde6b2b84252e2d7b Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
---
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)

@ -1,17 +1,38 @@
From 8a6398687998886c451c6df381c2320b6dddb3fe Mon Sep 17 00:00:00 2001
From 6a615274708fff685952139fee00ebccc0cf3266 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 17 Jul 2011 14:55:45 +0200
Subject: [PATCH 16/22] mtd: bcm47xx: add serial flash driver
Subject: [PATCH 19/26] mtd: bcm47xx: add serial flash driver
sflash get the sflash ops from platform device
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
drivers/mtd/maps/Kconfig | 9 ++
drivers/mtd/maps/Makefile | 1 +
drivers/mtd/maps/bcm47xx-sflash.c | 270 +++++++++++++++++++++++++++++++++++++
3 files changed, 280 insertions(+), 0 deletions(-)
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 <linux/ssb/ssb.h>
#include <linux/bcma/bcma.h>
+#include <linux/mtd/mtd.h>
#include <bcm47xx.h>
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
@ -39,17 +60,17 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+obj-$(CONFIG_MTD_BCM47XX_SFLASH)+= bcm47xx-sflash.o
--- /dev/null
+++ b/drivers/mtd/maps/bcm47xx-sflash.c
@@ -0,0 +1,270 @@
@@ -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.
+ * 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$
+ */
@ -64,29 +85,18 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+#include <linux/mtd/partitions.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+
+#include <bcm47xx.h>
+
+#include <linux/bcma/bcma.h>
+#include <linux/bcma/bcma_driver_chipcommon.h>
+#include <linux/platform_device.h>
+
+struct sflash_mtd {
+ struct bcma_drv_cc *cc;
+ struct mtd_info mtd;
+ struct mtd_erase_region_info region;
+};
+
+static struct sflash_mtd *sflash;
+#include <bcm47xx.h>
+#include <bus.h>
+
+static int
+sflash_mtd_poll(struct sflash_mtd *sflash, unsigned int offset, int timeout)
+sflash_mtd_poll(struct bcm47xx_sflash *sflash, unsigned int offset, int timeout)
+{
+ unsigned long now = jiffies;
+ int ret = 0;
+
+ for (;;) {
+ if (!bcma_sflash_poll(sflash->cc, offset)) {
+ if (!sflash->poll(sflash, offset)) {
+ ret = 0;
+ break;
+ }
@ -104,7 +114,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+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;
+ struct bcm47xx_sflash *sflash = (struct bcm47xx_sflash *) mtd->priv;
+
+ /* Check address range */
+ if (!len)
@ -112,11 +122,11 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+
+ if ((from + len) > mtd->size)
+ return -EINVAL;
+
+
+ *retlen = 0;
+
+ while (len) {
+ int ret = bcma_sflash_read(sflash->cc, from, len, buf);
+ int ret = sflash->read(sflash, from, len, buf);
+ if (ret < 0)
+ return ret;
+
@ -132,7 +142,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+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;
+ struct bcm47xx_sflash *sflash = (struct bcm47xx_sflash *) mtd->priv;
+
+ /* Check address range */
+ if (!len)
@ -144,7 +154,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ *retlen = 0;
+ while (len) {
+ int bytes;
+ int ret = bcma_sflash_write(sflash->cc, to, len, buf);
+ int ret = sflash->write(sflash, to, len, buf);
+ if (ret < 0)
+ return ret;
+
@ -166,7 +176,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+static int
+sflash_mtd_erase(struct mtd_info *mtd, struct erase_info *erase)
+{
+ struct sflash_mtd *sflash = (struct sflash_mtd *) mtd->priv;
+ struct bcm47xx_sflash *sflash = (struct bcm47xx_sflash *) mtd->priv;
+ int i, j, ret = 0;
+ unsigned int addr, len;
+
@ -185,9 +195,11 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ 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)
+ ret = sflash->erase(sflash, addr);
+ if (ret < 0)
+ break;
+ if ((ret = sflash_mtd_poll(sflash, addr, 10 * HZ)))
+ ret = sflash_mtd_poll(sflash, addr, 10 * HZ);
+ if (ret)
+ break;
+ addr += mtd->eraseregions[i].erasesize;
+ len -= mtd->eraseregions[i].erasesize;
@ -200,7 +212,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ /* Set erase status */
+ if (ret)
+ erase->state = MTD_ERASE_FAILED;
+ else
+ else
+ erase->state = MTD_ERASE_DONE;
+
+ /* Call erase callback */
@ -214,52 +226,53 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+
+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;
+
+ sflash = kzalloc(sizeof(struct sflash_mtd), GFP_KERNEL);
+ if (!sflash)
+ mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
+ if (!mtd)
+ return -ENOMEM;
+
+ sflash->cc = &bcm47xx_bus.bcma.bus.drv_cc;
+ if (sflash->cc->flash_type != BCMA_SFLASH)
+ return -ENODEV;
+ 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->cc->flash.sflash.blocksize/1024,
+ sflash->cc->flash.sflash.numblocks,
+ sflash->cc->flash.sflash.size/1024);
+ sflash->blocksize/1024, sflash->numblocks, 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;
+ 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 */
+ 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);
+ 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(&sflash->mtd, parts, num_partitions);
+ ret = mtd_device_register(mtd, parts, num_partitions);
+
+// ret = mtd_device_parse_register(bcm47xx_mtd, "bcm47xx", NULL, NULL, 0);
+
@ -267,18 +280,23 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ pr_err("mtd_device_register failed\n");
+ return ret;
+ }
+ sflash->mtd = mtd;
+ return 0;
+
+err_destroy:
+ map_destroy(&sflash->mtd);
+ 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);
+ mtd_device_unregister(sflash->mtd);
+ map_destroy(sflash->mtd);
+ kfree(sflash->mtd->eraseregions);
+ kfree(sflash->mtd);
+ }
+ return 0;
+}

@ -0,0 +1,100 @@
From 64f3d068654589d6114048ac5933cd4498706cfc Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 17 Jul 2011 15:02:10 +0200
Subject: [PATCH 20/26] bcm47xx: register flash drivers
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
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 <linux/ssb/ssb.h>
#include <linux/ssb/ssb_embedded.h>
#include <linux/bcma/bcma_soc.h>
+#include <linux/platform_device.h>
#include <asm/bootinfo.h>
#include <asm/reboot.h>
#include <asm/time.h>
#include <bcm47xx.h>
+#include <bus.h>
#include <asm/mach-bcm47xx/nvram.h>
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);

@ -1,37 +0,0 @@
From f3007275d7706afb1381adb0003f3ba69d359c8f Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
---
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;
}

@ -0,0 +1,51 @@
From 3e889f1cf928c6d87229761a0bc4c18c775a988b Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 17 Jul 2011 21:13:32 +0200
Subject: [PATCH 21/26] add workarround for wndr3400
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
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
*/

@ -1,7 +1,7 @@
From 6dd27601bee9b3c26cdb67246b6da51dd696ac34 Mon Sep 17 00:00:00 2001
From e6730c06cfc827d715f43e9bd276ae939bb86af9 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
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
Subject: [PATCH 23/26] bcma: use randoom mac address as long as reading it out does not work
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>

@ -0,0 +1,118 @@
From 1d693b2c9d5943cbe938f879041b837cd004737f Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
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 <hauke@hauke-m.de>
---
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 <asm/addrspace.h>
#include <asm/mach-bcm47xx/nvram.h>
#include <asm/mach-bcm47xx/bcm47xx.h>
+#include <asm/mach-bcm47xx/bus.h>
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)

@ -0,0 +1,47 @@
From f6e41db3ee7ead99e1398def222c14893fc265de Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Thu, 4 Aug 2011 21:09:48 +0200
Subject: [PATCH 26/26] bcma: export needed gpio functions
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
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)

@ -24,7 +24,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
#include <asm/bootinfo.h>
#include <asm/reboot.h>
#include <asm/time.h>
@@ -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 <hauke@hauke-m.de>
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));
}
}

@ -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;

@ -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

@ -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);
+

@ -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));

@ -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 <asm/mach-bcm47xx/bcm47xx.h>
@@ -23,6 +23,8 @@
#include <asm/mach-bcm47xx/bus.h>
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();

@ -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;

@ -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);

@ -1,8 +1,8 @@
--- a/arch/mips/bcm47xx/nvram.c
+++ b/arch/mips/bcm47xx/nvram.c
@@ -21,7 +21,8 @@
#include <asm/mach-bcm47xx/nvram.h>
@@ -22,7 +22,8 @@
#include <asm/mach-bcm47xx/bcm47xx.h>
#include <asm/mach-bcm47xx/bus.h>
-static char nvram_buf[NVRAM_SPACE];
+char nvram_buf[NVRAM_SPACE];

Loading…
Cancel
Save