From 6c4398bc6add362d5b399ba361720cf1afd7176b Mon Sep 17 00:00:00 2001 From: hauke Date: Tue, 28 Jun 2011 22:21:57 +0000 Subject: [PATCH] brcm47xx: add initial support for devices with bcma bus. Ethernet and wifi are not working and this is highly experimental. git-svn-id: svn://svn.openwrt.org/openwrt/trunk@27301 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/broadcom-diag/src/diag.c | 73 +-- package/broadcom-diag/src/gpio.h | 115 +---- target/linux/brcm47xx/config-3.0 | 11 + ...-parsing-of-EEPROM-into-own-function.patch | 274 +++++++++++ ...lizing-of-struct-bcma_bus-to-own-fun.patch | 48 ++ ...nctions-to-scan-cores-needed-on-SoCs.patch | 307 ++++++++++++ .../patches-3.0/0004-bcma-add-SOC-bus.patch | 323 +++++++++++++ .../0005-bcma-add-mips-driver.patch | 402 ++++++++++++++++ ...0006-bcma-add-serial-console-support.patch | 151 ++++++ .../patches-3.0/0007-bcma-get-CPU-clock.patch | 204 ++++++++ .../0008-bcma-add-pci-e-host-mode.patch | 140 ++++++ ...f-sprom-is-available-before-accessin.patch | 37 ++ ...x-prepare-to-support-different-buses.patch | 439 ++++++++++++++++++ ...possible-to-build-bcm47xx-without-ss.patch | 395 ++++++++++++++++ ...012-bcm47xx-add-support-for-bcma-bus.patch | 410 ++++++++++++++++ ...47xx-fix-irq-assignment-for-new-SoCs.patch | 37 ++ ...47xx-Setup-and-register-serial-early.patch | 20 +- .../016-MIPS-BCM47xx-Remove-CFE-console.patch | 6 +- .../040-bcm47xx-add-gpio_set_debounce.patch | 4 +- .../brcm47xx/patches-3.0/250-bcma-flash.patch | 78 ++++ .../patches-3.0/400-arch-bcm47xx.patch | 8 +- .../812-disable_wgt634u_crap.patch | 22 +- .../patches-3.0/820-wgt634u-nvram-fix.patch | 16 +- .../900-bcm47xx_wdt-noprescale.patch | 33 +- .../980-wnr834b_no_cardbus_invariant.patch | 2 +- 25 files changed, 3366 insertions(+), 189 deletions(-) create mode 100644 target/linux/brcm47xx/patches-3.0/0001-bcma-move-parsing-of-EEPROM-into-own-function.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0002-bcma-move-initializing-of-struct-bcma_bus-to-own-fun.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0003-bcma-add-functions-to-scan-cores-needed-on-SoCs.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0004-bcma-add-SOC-bus.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0005-bcma-add-mips-driver.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0006-bcma-add-serial-console-support.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0007-bcma-get-CPU-clock.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0008-bcma-add-pci-e-host-mode.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0009-bcma-add-check-if-sprom-is-available-before-accessin.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0010-bcm47xx-prepare-to-support-different-buses.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0011-bcm47xx-make-it-possible-to-build-bcm47xx-without-ss.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0012-bcm47xx-add-support-for-bcma-bus.patch create mode 100644 target/linux/brcm47xx/patches-3.0/0013-bcm47xx-fix-irq-assignment-for-new-SoCs.patch create mode 100644 target/linux/brcm47xx/patches-3.0/250-bcma-flash.patch diff --git a/package/broadcom-diag/src/diag.c b/package/broadcom-diag/src/diag.c index 00a72e907..8e7ffa6cc 100644 --- a/package/broadcom-diag/src/diag.c +++ b/package/broadcom-diag/src/diag.c @@ -149,9 +149,9 @@ static void __init bcm4780_init(void) { /* Enables GPIO 3 that controls HDD and led power on ASUS WL-700gE */ printk(MODULE_NAME ": Spinning up HDD and enabling leds\n"); - gpio_outen(pin, pin); - gpio_control(pin, 0); - gpio_out(pin, pin); + ssb_gpio_outen(&ssb_bcm47xx, pin, pin); + ssb_gpio_control(&ssb_bcm47xx, pin, 0); + ssb_gpio_out(&ssb_bcm47xx, pin, pin); /* Wait 5s, so the HDD can spin up */ set_current_state(TASK_INTERRUPTIBLE); @@ -161,14 +161,14 @@ static void __init bcm4780_init(void) { static void __init NetCenter_init(void) { /* unset pin 6 (+12V) */ int pin = 1 << 6; - gpio_outen(pin, pin); - gpio_control(pin, 0); - gpio_out(pin, pin); + ssb_gpio_outen(&ssb_bcm47xx, pin, pin); + ssb_gpio_control(&ssb_bcm47xx, pin, 0); + ssb_gpio_out(&ssb_bcm47xx, pin, pin); /* unset pin 1 (turn off red led, blue will light alone if +5V comes up) */ pin = 1 << 1; - gpio_outen(pin, pin); - gpio_control(pin, 0); - gpio_out(pin, pin); + ssb_gpio_outen(&ssb_bcm47xx, pin, pin); + ssb_gpio_control(&ssb_bcm47xx, pin, 0); + ssb_gpio_out(&ssb_bcm47xx, pin, pin); /* unset pin 3 (+5V) and wait 5 seconds (harddisk spin up) */ bcm4780_init(); } @@ -177,9 +177,9 @@ static void __init bcm57xx_init(void) { int pin = 1 << 2; /* FIXME: switch comes up, but port mappings/vlans not right */ - gpio_outen(pin, pin); - gpio_control(pin, 0); - gpio_out(pin, pin); + ssb_gpio_outen(&ssb_bcm47xx, pin, pin); + ssb_gpio_control(&ssb_bcm47xx, pin, 0); + ssb_gpio_out(&ssb_bcm47xx, pin, pin); } static struct platform_t __initdata platforms[] = { @@ -1166,18 +1166,18 @@ static void register_buttons(struct button_t *b) platform.button_mask &= ~gpiomask; - gpio_outen(platform.button_mask, 0); - gpio_control(platform.button_mask, 0); - platform.button_polarity = gpio_in() & platform.button_mask; - gpio_intpolarity(platform.button_mask, platform.button_polarity); - gpio_setintmask(platform.button_mask, platform.button_mask); + ssb_gpio_outen(&ssb_bcm47xx, platform.button_mask, 0); + ssb_gpio_control(&ssb_bcm47xx, platform.button_mask, 0); + platform.button_polarity = ssb_gpio_in(&ssb_bcm47xx, ~0) & platform.button_mask; + ssb_gpio_polarity(&ssb_bcm47xx, platform.button_mask, platform.button_polarity); + ssb_gpio_intmask(&ssb_bcm47xx, platform.button_mask, platform.button_mask); gpio_set_irqenable(1, button_handler); } static void unregister_buttons(struct button_t *b) { - gpio_setintmask(platform.button_mask, 0); + ssb_gpio_intmask(&ssb_bcm47xx, platform.button_mask, 0); gpio_set_irqenable(0, button_handler); } @@ -1237,12 +1237,12 @@ static irqreturn_t button_handler(int irq, void *dev_id) struct button_t *b; u32 in, changed; - in = gpio_in() & platform.button_mask; - gpio_intpolarity(platform.button_mask, in); + in = ssb_gpio_in(&ssb_bcm47xx, ~0) & platform.button_mask; + ssb_gpio_polarity(&ssb_bcm47xx, platform.button_mask, in); changed = platform.button_polarity ^ in; platform.button_polarity = in; - changed &= ~gpio_outen(0, 0); + changed &= ~ssb_gpio_outen(&ssb_bcm47xx, 0, 0); for (b = platform.buttons; b->name; b++) { struct event_t *event; @@ -1298,10 +1298,10 @@ static void register_leds(struct led_t *l) } } - gpio_outen(mask, oe_mask); - gpio_control(mask, 0); - gpio_out(mask, val); - gpio_setintmask(mask, 0); + ssb_gpio_outen(&ssb_bcm47xx, mask, oe_mask); + ssb_gpio_control(&ssb_bcm47xx, mask, 0); + ssb_gpio_out(&ssb_bcm47xx, mask, val); + ssb_gpio_intmask(&ssb_bcm47xx, mask, 0); } static void unregister_leds(struct led_t *l) @@ -1336,11 +1336,11 @@ static void led_flash(unsigned long dummy) { mask &= ~gpiomask; if (mask) { - u32 val = ~gpio_in(); + u32 val = ~ssb_gpio_in(&ssb_bcm47xx, ~0); - gpio_outen(mask, mask); - gpio_control(mask, 0); - gpio_out(mask, val); + ssb_gpio_outen(&ssb_bcm47xx, mask, mask); + ssb_gpio_control(&ssb_bcm47xx, mask, 0); + ssb_gpio_out(&ssb_bcm47xx, mask, val); } if (mask || extif_blink) { mod_timer(&led_timer, jiffies + FLASH_TIME); @@ -1367,7 +1367,7 @@ static ssize_t diag_proc_read(struct file *file, char *buf, size_t count, loff_t if (led->gpio & GPIO_TYPE_EXTIF) { len = sprintf(page, "%d\n", led->state); } else { - u32 in = (gpio_in() & led->gpio ? 1 : 0); + u32 in = (ssb_gpio_in(&ssb_bcm47xx, ~0) & led->gpio ? 1 : 0); u8 p = (led->polarity == NORMAL ? 0 : 1); len = sprintf(page, "%d\n", ((in ^ p) ? 1 : 0)); } @@ -1431,9 +1431,9 @@ static ssize_t diag_proc_write(struct file *file, const char *buf, size_t count, led->state = p ^ ((page[0] == '1') ? 1 : 0); set_led_extif(led); } else { - gpio_outen(led->gpio, led->gpio); - gpio_control(led->gpio, 0); - gpio_out(led->gpio, ((p ^ (page[0] == '1')) ? led->gpio : 0)); + ssb_gpio_outen(&ssb_bcm47xx, led->gpio, led->gpio); + ssb_gpio_control(&ssb_bcm47xx, led->gpio, 0); + ssb_gpio_out(&ssb_bcm47xx, led->gpio, ((p ^ (page[0] == '1')) ? led->gpio : 0)); } } break; @@ -1464,6 +1464,13 @@ static int __init diag_init(void) static struct proc_dir_entry *p; static struct platform_t *detected; +#ifdef CONFIG_BCM47XX_SSB + if (bcm47xx_active_bus_type != BCM47XX_BUS_TYPE_SSB) { + printk(MODULE_NAME ": bcma bus is not supported.\n"); + return -ENODEV; + } +#endif + detected = platform_detect(); if (!detected) { printk(MODULE_NAME ": Router model not detected.\n"); diff --git a/package/broadcom-diag/src/gpio.h b/package/broadcom-diag/src/gpio.h index cd48637b2..575fd8c47 100644 --- a/package/broadcom-diag/src/gpio.h +++ b/package/broadcom-diag/src/gpio.h @@ -1,46 +1,12 @@ #ifndef __DIAG_GPIO_H #define __DIAG_GPIO_H #include - -#ifndef BCMDRIVER -#include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) #include -#define ssb ssb_bcm47xx +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) +#define ssb_bcm47xx bcm47xx_bus.ssb #endif -extern struct ssb_bus ssb; - - -static inline u32 gpio_in(void) -{ - return ssb_gpio_in(&ssb, ~0); -} - -static inline u32 gpio_out(u32 mask, u32 value) -{ - return ssb_gpio_out(&ssb, mask, value); -} - -static inline u32 gpio_outen(u32 mask, u32 value) -{ - return ssb_gpio_outen(&ssb, mask, value); -} - -static inline u32 gpio_control(u32 mask, u32 value) -{ - return ssb_gpio_control(&ssb, mask, value); -} - -static inline u32 gpio_setintmask(u32 mask, u32 value) -{ - return ssb_gpio_intmask(&ssb, mask, value); -} - -static inline u32 gpio_intpolarity(u32 mask, u32 value) -{ - return ssb_gpio_polarity(&ssb, mask, value); -} static inline u32 __ssb_write32_masked(struct ssb_device *dev, u16 offset, u32 mask, u32 value) @@ -55,16 +21,8 @@ static void gpio_set_irqenable(int enabled, irqreturn_t (*handler)(int, void *)) { int irq; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) irq = gpio_to_irq(0); if (irq == -EINVAL) return; -#else - if (ssb.chipco.dev) - irq = ssb_mips_irq(ssb.chipco.dev) + 2; - else if (ssb.extif.dev) - irq = ssb_mips_irq(ssb.extif.dev) + 2; - else return; -#endif if (enabled) { if (request_irq(irq, handler, IRQF_SHARED | IRQF_SAMPLE_RANDOM, "gpio", handler)) @@ -73,71 +31,10 @@ static void gpio_set_irqenable(int enabled, irqreturn_t (*handler)(int, void *)) free_irq(irq, handler); } - if (ssb.chipco.dev) - __ssb_write32_masked(ssb.chipco.dev, SSB_CHIPCO_IRQMASK, SSB_CHIPCO_IRQ_GPIO, (enabled ? SSB_CHIPCO_IRQ_GPIO : 0)); + if (ssb_bcm47xx.chipco.dev) + __ssb_write32_masked(ssb_bcm47xx.chipco.dev, SSB_CHIPCO_IRQMASK, SSB_CHIPCO_IRQ_GPIO, (enabled ? SSB_CHIPCO_IRQ_GPIO : 0)); } -#else - -#include -#include -#include -#include -#include -#include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -#include -#else -#include -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -#define sbh bcm947xx_sbh -#define sbh_lock bcm947xx_sbh_lock -#endif - -extern void *sbh; -extern spinlock_t sbh_lock; - -#define gpio_in() sb_gpioin(sbh) -#define gpio_out(mask, value) sb_gpioout(sbh, mask, ((value) & (mask)), GPIO_DRV_PRIORITY) -#define gpio_outen(mask, value) sb_gpioouten(sbh, mask, value, GPIO_DRV_PRIORITY) -#define gpio_control(mask, value) sb_gpiocontrol(sbh, mask, value, GPIO_DRV_PRIORITY) -#define gpio_setintmask(mask, value) sb_gpiointmask(sbh, mask, value, GPIO_DRV_PRIORITY) -#define gpio_intpolarity(mask, value) sb_gpiointpolarity(sbh, mask, value, GPIO_DRV_PRIORITY) - -static void gpio_set_irqenable(int enabled, irqreturn_t (*handler)(int, void *, struct pt_regs *)) -{ - unsigned int coreidx; - unsigned long flags; - chipcregs_t *cc; - int irq; - - spin_lock_irqsave(sbh_lock, flags); - coreidx = sb_coreidx(sbh); - - irq = sb_irq(sbh) + 2; - if (enabled) - request_irq(irq, handler, SA_SHIRQ | SA_SAMPLE_RANDOM, "gpio", handler); - else - free_irq(irq, handler); - - if ((cc = sb_setcore(sbh, SB_CC, 0))) { - int intmask; - - intmask = readl(&cc->intmask); - if (enabled) - intmask |= CI_GPIO; - else - intmask &= ~CI_GPIO; - writel(intmask, &cc->intmask); - } - sb_setcoreidx(sbh, coreidx); - spin_unlock_irqrestore(sbh_lock, flags); -} - -#endif /* BCMDRIVER */ - #define EXTIF_ADDR 0x1f000000 #define EXTIF_UART (EXTIF_ADDR + 0x00800000) diff --git a/target/linux/brcm47xx/config-3.0 b/target/linux/brcm47xx/config-3.0 index 2a3e743f1..4c2b62c6b 100644 --- a/target/linux/brcm47xx/config-3.0 +++ b/target/linux/brcm47xx/config-3.0 @@ -14,7 +14,16 @@ CONFIG_B44_PCI=y CONFIG_B44_PCICORE_AUTOSELECT=y CONFIG_B44_PCI_AUTOSELECT=y CONFIG_BCM47XX=y +CONFIG_BCM47XX_BCMA=y +CONFIG_BCM47XX_SSB=y CONFIG_BCM47XX_WDT=y +CONFIG_BCMA=y +CONFIG_BCMA_DEBUG=y +CONFIG_BCMA_DRIVER_MIPS=y +CONFIG_BCMA_DRIVER_PCI_HOSTMODE=y +CONFIG_BCMA_HOST_PCI=y +CONFIG_BCMA_HOST_PCI_POSSIBLE=y +CONFIG_BCMA_HOST_SOC=y CONFIG_BCMA_POSSIBLE=y # CONFIG_BRCMUTIL is not set # CONFIG_BSD_PROCESS_ACCT is not set @@ -31,6 +40,7 @@ CONFIG_CPU_HAS_SYNC=y CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_CPU_MIPS32=y CONFIG_CPU_MIPS32_R1=y +# CONFIG_CPU_MIPS32_R2 is not set CONFIG_CPU_MIPSR1=y CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y CONFIG_CPU_SUPPORTS_HIGHMEM=y @@ -118,6 +128,7 @@ CONFIG_SSB_PCIHOST_POSSIBLE=y CONFIG_SSB_SERIAL=y CONFIG_SSB_SPROM=y CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_SYS_HAS_CPU_MIPS32_R2=y CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y CONFIG_SYS_SUPPORTS_ARBIT_HZ=y CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y diff --git a/target/linux/brcm47xx/patches-3.0/0001-bcma-move-parsing-of-EEPROM-into-own-function.patch b/target/linux/brcm47xx/patches-3.0/0001-bcma-move-parsing-of-EEPROM-into-own-function.patch new file mode 100644 index 000000000..e535617c7 --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0001-bcma-move-parsing-of-EEPROM-into-own-function.patch @@ -0,0 +1,274 @@ +From c4fb5adbe45b3a1cfc509a64bb92429ab0d6fc37 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sat, 11 Jun 2011 16:47:38 +0200 +Subject: [PATCH 01/14] bcma: move parsing of EEPROM into own function. + +Move the parsing of the EEPROM data in scan function for one core into +an own function. Now we are able to use it in some other scan function +as well. + +Signed-off-by: Hauke Mehrtens +--- + drivers/bcma/scan.c | 230 ++++++++++++++++++++++++++------------------------- + 1 files changed, 118 insertions(+), 112 deletions(-) + +--- a/drivers/bcma/scan.c ++++ b/drivers/bcma/scan.c +@@ -200,16 +200,124 @@ static s32 bcma_erom_get_addr_desc(struc + return addrl; + } + ++static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, ++ struct bcma_device *core) ++{ ++ s32 tmp; ++ u8 i, j; ++ s32 cia, cib; ++ u8 ports[2], wrappers[2]; ++ ++ /* get CIs */ ++ cia = bcma_erom_get_ci(bus, eromptr); ++ if (cia < 0) { ++ bcma_erom_push_ent(eromptr); ++ if (bcma_erom_is_end(bus, eromptr)) ++ return -ESPIPE; ++ return -EILSEQ; ++ } ++ cib = bcma_erom_get_ci(bus, eromptr); ++ if (cib < 0) ++ return -EILSEQ; ++ ++ /* parse CIs */ ++ core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT; ++ core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT; ++ core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT; ++ ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT; ++ ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT; ++ wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT; ++ wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT; ++ core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT; ++ ++ if (((core->id.manuf == BCMA_MANUF_ARM) && ++ (core->id.id == 0xFFF)) || ++ (ports[1] == 0)) { ++ bcma_erom_skip_component(bus, eromptr); ++ return -ENXIO; ++ } ++ ++ /* check if component is a core at all */ ++ if (wrappers[0] + wrappers[1] == 0) { ++ /* we could save addrl of the router ++ if (cid == BCMA_CORE_OOB_ROUTER) ++ */ ++ bcma_erom_skip_component(bus, eromptr); ++ return -ENXIO; ++ } ++ ++ if (bcma_erom_is_bridge(bus, eromptr)) { ++ bcma_erom_skip_component(bus, eromptr); ++ return -ENXIO; ++ } ++ ++ /* get & parse master ports */ ++ for (i = 0; i < ports[0]; i++) { ++ u32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr); ++ if (mst_port_d < 0) ++ return -EILSEQ; ++ } ++ ++ /* get & parse slave ports */ ++ for (i = 0; i < ports[1]; i++) { ++ for (j = 0; ; j++) { ++ tmp = bcma_erom_get_addr_desc(bus, eromptr, ++ SCAN_ADDR_TYPE_SLAVE, i); ++ if (tmp < 0) { ++ /* no more entries for port _i_ */ ++ /* pr_debug("erom: slave port %d " ++ * "has %d descriptors\n", i, j); */ ++ break; ++ } else { ++ if (i == 0 && j == 0) ++ core->addr = tmp; ++ } ++ } ++ } ++ ++ /* get & parse master wrappers */ ++ for (i = 0; i < wrappers[0]; i++) { ++ for (j = 0; ; j++) { ++ tmp = bcma_erom_get_addr_desc(bus, eromptr, ++ SCAN_ADDR_TYPE_MWRAP, i); ++ if (tmp < 0) { ++ /* no more entries for port _i_ */ ++ /* pr_debug("erom: master wrapper %d " ++ * "has %d descriptors\n", i, j); */ ++ break; ++ } else { ++ if (i == 0 && j == 0) ++ core->wrap = tmp; ++ } ++ } ++ } ++ ++ /* get & parse slave wrappers */ ++ for (i = 0; i < wrappers[1]; i++) { ++ u8 hack = (ports[1] == 1) ? 0 : 1; ++ for (j = 0; ; j++) { ++ tmp = bcma_erom_get_addr_desc(bus, eromptr, ++ SCAN_ADDR_TYPE_SWRAP, i + hack); ++ if (tmp < 0) { ++ /* no more entries for port _i_ */ ++ /* pr_debug("erom: master wrapper %d " ++ * has %d descriptors\n", i, j); */ ++ break; ++ } else { ++ if (wrappers[0] == 0 && !i && !j) ++ core->wrap = tmp; ++ } ++ } ++ } ++ return 0; ++} ++ + int bcma_bus_scan(struct bcma_bus *bus) + { + u32 erombase; + u32 __iomem *eromptr, *eromend; + +- s32 cia, cib; +- u8 ports[2], wrappers[2]; +- + s32 tmp; +- u8 i, j; + + int err; + +@@ -236,112 +344,13 @@ int bcma_bus_scan(struct bcma_bus *bus) + INIT_LIST_HEAD(&core->list); + core->bus = bus; + +- /* get CIs */ +- cia = bcma_erom_get_ci(bus, &eromptr); +- if (cia < 0) { +- bcma_erom_push_ent(&eromptr); +- if (bcma_erom_is_end(bus, &eromptr)) +- break; +- err= -EILSEQ; +- goto out; +- } +- cib = bcma_erom_get_ci(bus, &eromptr); +- if (cib < 0) { +- err= -EILSEQ; +- goto out; +- } +- +- /* parse CIs */ +- core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT; +- core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT; +- core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT; +- ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT; +- ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT; +- wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT; +- wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT; +- core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT; +- +- if (((core->id.manuf == BCMA_MANUF_ARM) && +- (core->id.id == 0xFFF)) || +- (ports[1] == 0)) { +- bcma_erom_skip_component(bus, &eromptr); ++ err = bcma_get_next_core(bus, &eromptr, core); ++ if (err == -ENXIO) + continue; +- } +- +- /* check if component is a core at all */ +- if (wrappers[0] + wrappers[1] == 0) { +- /* we could save addrl of the router +- if (cid == BCMA_CORE_OOB_ROUTER) +- */ +- bcma_erom_skip_component(bus, &eromptr); +- continue; +- } +- +- if (bcma_erom_is_bridge(bus, &eromptr)) { +- bcma_erom_skip_component(bus, &eromptr); +- continue; +- } +- +- /* get & parse master ports */ +- for (i = 0; i < ports[0]; i++) { +- u32 mst_port_d = bcma_erom_get_mst_port(bus, &eromptr); +- if (mst_port_d < 0) { +- err= -EILSEQ; +- goto out; +- } +- } +- +- /* get & parse slave ports */ +- for (i = 0; i < ports[1]; i++) { +- for (j = 0; ; j++) { +- tmp = bcma_erom_get_addr_desc(bus, &eromptr, +- SCAN_ADDR_TYPE_SLAVE, i); +- if (tmp < 0) { +- /* no more entries for port _i_ */ +- /* pr_debug("erom: slave port %d " +- * "has %d descriptors\n", i, j); */ +- break; +- } else { +- if (i == 0 && j == 0) +- core->addr = tmp; +- } +- } +- } +- +- /* get & parse master wrappers */ +- for (i = 0; i < wrappers[0]; i++) { +- for (j = 0; ; j++) { +- tmp = bcma_erom_get_addr_desc(bus, &eromptr, +- SCAN_ADDR_TYPE_MWRAP, i); +- if (tmp < 0) { +- /* no more entries for port _i_ */ +- /* pr_debug("erom: master wrapper %d " +- * "has %d descriptors\n", i, j); */ +- break; +- } else { +- if (i == 0 && j == 0) +- core->wrap = tmp; +- } +- } +- } +- +- /* get & parse slave wrappers */ +- for (i = 0; i < wrappers[1]; i++) { +- u8 hack = (ports[1] == 1) ? 0 : 1; +- for (j = 0; ; j++) { +- tmp = bcma_erom_get_addr_desc(bus, &eromptr, +- SCAN_ADDR_TYPE_SWRAP, i + hack); +- if (tmp < 0) { +- /* no more entries for port _i_ */ +- /* pr_debug("erom: master wrapper %d " +- * has %d descriptors\n", i, j); */ +- break; +- } else { +- if (wrappers[0] == 0 && !i && !j) +- core->wrap = tmp; +- } +- } +- } ++ else if (err == -ESPIPE) ++ break; ++ else if (err < 0) ++ return err; + + pr_info("Core %d found: %s " + "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", +@@ -351,9 +360,6 @@ int bcma_bus_scan(struct bcma_bus *bus) + + core->core_index = bus->nr_cores++; + list_add(&core->list, &bus->cores); +- continue; +-out: +- return err; + } + + return 0; diff --git a/target/linux/brcm47xx/patches-3.0/0002-bcma-move-initializing-of-struct-bcma_bus-to-own-fun.patch b/target/linux/brcm47xx/patches-3.0/0002-bcma-move-initializing-of-struct-bcma_bus-to-own-fun.patch new file mode 100644 index 000000000..8a2de51c4 --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0002-bcma-move-initializing-of-struct-bcma_bus-to-own-fun.patch @@ -0,0 +1,48 @@ +From dd6cbe9b9e2ae563659b34184f4cd9d905dc90d5 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sat, 18 Jun 2011 11:55:47 +0200 +Subject: [PATCH 02/14] bcma: move initializing of struct bcma_bus to own function. + +This makes it possible to use this code in some other method. + +Signed-off-by: Hauke Mehrtens +--- + drivers/bcma/scan.c | 17 +++++++++++------ + 1 files changed, 11 insertions(+), 6 deletions(-) + +--- a/drivers/bcma/scan.c ++++ b/drivers/bcma/scan.c +@@ -312,15 +312,10 @@ static int bcma_get_next_core(struct bcm + return 0; + } + +-int bcma_bus_scan(struct bcma_bus *bus) ++static void bcma_init_bus(struct bcma_bus *bus) + { +- u32 erombase; +- u32 __iomem *eromptr, *eromend; +- + s32 tmp; + +- int err; +- + INIT_LIST_HEAD(&bus->cores); + bus->nr_cores = 0; + +@@ -330,6 +325,16 @@ int bcma_bus_scan(struct bcma_bus *bus) + bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT; + bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT; + bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT; ++} ++ ++int bcma_bus_scan(struct bcma_bus *bus) ++{ ++ u32 erombase; ++ u32 __iomem *eromptr, *eromend; ++ ++ int err; ++ ++ bcma_init_bus(bus); + + erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); + eromptr = bus->mmio; diff --git a/target/linux/brcm47xx/patches-3.0/0003-bcma-add-functions-to-scan-cores-needed-on-SoCs.patch b/target/linux/brcm47xx/patches-3.0/0003-bcma-add-functions-to-scan-cores-needed-on-SoCs.patch new file mode 100644 index 000000000..c18249d1d --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0003-bcma-add-functions-to-scan-cores-needed-on-SoCs.patch @@ -0,0 +1,307 @@ +From 9a920f4d8eed485f7b73e9b13dab0e49c64d3ff8 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sat, 18 Jun 2011 14:30:55 +0200 +Subject: [PATCH 03/14] bcma: add functions to scan cores needed on SoCs + +The chip common and mips core have to be setup early in the boot +process to get the cpu clock. +bcma_bus_early_register() gets pointers to some space to store the core +data and searches for the chip common and mips core and initializes +chip common. After that was done and the kernel is out of early boot we +just have to run bcma_bus_register() and it will search for the other +cores, initialize and register them. + +Signed-off-by: Hauke Mehrtens +--- + drivers/bcma/bcma_private.h | 7 ++ + drivers/bcma/driver_chipcommon.c | 5 ++ + drivers/bcma/driver_pci.c | 3 + + drivers/bcma/main.c | 45 +++++++++++++ + drivers/bcma/scan.c | 95 +++++++++++++++++++++++++-- + include/linux/bcma/bcma.h | 1 + + include/linux/bcma/bcma_driver_chipcommon.h | 1 + + 7 files changed, 151 insertions(+), 6 deletions(-) + +--- a/drivers/bcma/bcma_private.h ++++ b/drivers/bcma/bcma_private.h +@@ -15,9 +15,16 @@ struct bcma_bus; + /* main.c */ + int bcma_bus_register(struct bcma_bus *bus); + void bcma_bus_unregister(struct bcma_bus *bus); ++int __init bcma_bus_early_register(struct bcma_bus *bus, ++ struct bcma_device *core_cc, ++ struct bcma_device *core_mips); + + /* scan.c */ + int bcma_bus_scan(struct bcma_bus *bus); ++int __init bcma_bus_scan_early(struct bcma_bus *bus, ++ struct bcma_device_id *match, ++ struct bcma_device *core); ++void bcma_init_bus(struct bcma_bus *bus); + + /* sprom.c */ + int bcma_sprom_get(struct bcma_bus *bus); +--- a/drivers/bcma/driver_chipcommon.c ++++ b/drivers/bcma/driver_chipcommon.c +@@ -23,6 +23,9 @@ static inline u32 bcma_cc_write32_masked + + void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) + { ++ if (cc->setup_done) ++ return; ++ + if (cc->core->id.rev >= 11) + cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); + cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP); +@@ -38,6 +41,8 @@ void bcma_core_chipcommon_init(struct bc + bcma_pmu_init(cc); + if (cc->capabilities & BCMA_CC_CAP_PCTL) + pr_err("Power control not implemented!\n"); ++ ++ cc->setup_done = true; + } + + /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */ +--- a/drivers/bcma/driver_pci.c ++++ b/drivers/bcma/driver_pci.c +@@ -159,7 +159,10 @@ static void bcma_pcicore_serdes_workarou + + void bcma_core_pci_init(struct bcma_drv_pci *pc) + { ++ if (pc->setup_done) ++ return; + bcma_pcicore_serdes_workaround(pc); ++ pc->setup_done = true; + } + + int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core, +--- a/drivers/bcma/main.c ++++ b/drivers/bcma/main.c +@@ -167,6 +167,51 @@ void bcma_bus_unregister(struct bcma_bus + bcma_unregister_cores(bus); + } + ++int __init bcma_bus_early_register(struct bcma_bus *bus, ++ struct bcma_device *core_cc, ++ struct bcma_device *core_mips) ++{ ++ int err; ++ struct bcma_device *core; ++ struct bcma_device_id match; ++ ++ bcma_init_bus(bus); ++ ++ match.manuf = BCMA_MANUF_BCM; ++ match.id = BCMA_CORE_CHIPCOMMON; ++ match.class = BCMA_CL_SIM; ++ match.rev = BCMA_ANY_REV; ++ ++ /* Scan for devices (cores) */ ++ err = bcma_bus_scan_early(bus, &match, core_cc); ++ if (err) { ++ pr_err("Failed to scan for common core: %d\n", err); ++ return -1; ++ } ++ ++ match.manuf = BCMA_MANUF_MIPS; ++ match.id = BCMA_CORE_MIPS_74K; ++ match.class = BCMA_CL_SIM; ++ match.rev = BCMA_ANY_REV; ++ ++ err = bcma_bus_scan_early(bus, &match, core_mips); ++ if (err) { ++ pr_err("Failed to scan for mips core: %d\n", err); ++ return -1; ++ } ++ ++ /* Init CC core */ ++ core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON); ++ if (core) { ++ bus->drv_cc.core = core; ++ bcma_core_chipcommon_init(&bus->drv_cc); ++ } ++ ++ pr_info("Early bus registered\n"); ++ ++ return 0; ++} ++ + int __bcma_driver_register(struct bcma_driver *drv, struct module *owner) + { + drv->drv.name = drv->name; +--- a/drivers/bcma/scan.c ++++ b/drivers/bcma/scan.c +@@ -200,7 +200,20 @@ static s32 bcma_erom_get_addr_desc(struc + return addrl; + } + ++static struct bcma_device *bcma_find_core_by_index(struct bcma_bus *bus, ++ u16 index) ++{ ++ struct bcma_device *core; ++ ++ list_for_each_entry(core, &bus->cores, list) { ++ if (core->core_index == index) ++ return core; ++ } ++ return NULL; ++} ++ + static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, ++ struct bcma_device_id *match, int core_num, + struct bcma_device *core) + { + s32 tmp; +@@ -251,6 +264,21 @@ static int bcma_get_next_core(struct bcm + return -ENXIO; + } + ++ if (bcma_find_core_by_index(bus, core_num)) { ++ bcma_erom_skip_component(bus, eromptr); ++ return -ENODEV; ++ } ++ ++ if (match && ((match->manuf != BCMA_ANY_MANUF && ++ match->manuf != core->id.manuf) || ++ (match->id != BCMA_ANY_ID && match->id != core->id.id) || ++ (match->rev != BCMA_ANY_REV && match->rev != core->id.rev) || ++ (match->class != BCMA_ANY_CLASS && match->class != core->id.class) ++ )) { ++ bcma_erom_skip_component(bus, eromptr); ++ return -ENODEV; ++ } ++ + /* get & parse master ports */ + for (i = 0; i < ports[0]; i++) { + u32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr); +@@ -312,10 +340,13 @@ static int bcma_get_next_core(struct bcm + return 0; + } + +-static void bcma_init_bus(struct bcma_bus *bus) ++void bcma_init_bus(struct bcma_bus *bus) + { + s32 tmp; + ++ if (bus->init_done) ++ return; ++ + INIT_LIST_HEAD(&bus->cores); + bus->nr_cores = 0; + +@@ -325,6 +356,7 @@ static void bcma_init_bus(struct bcma_bu + bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT; + bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT; + bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT; ++ bus->init_done = true; + } + + int bcma_bus_scan(struct bcma_bus *bus) +@@ -332,7 +364,7 @@ int bcma_bus_scan(struct bcma_bus *bus) + u32 erombase; + u32 __iomem *eromptr, *eromend; + +- int err; ++ int err, core_num = 0; + + bcma_init_bus(bus); + +@@ -349,23 +381,74 @@ int bcma_bus_scan(struct bcma_bus *bus) + INIT_LIST_HEAD(&core->list); + core->bus = bus; + +- err = bcma_get_next_core(bus, &eromptr, core); +- if (err == -ENXIO) ++ err = bcma_get_next_core(bus, &eromptr, NULL, core_num, core); ++ if (err == -ENODEV) { ++ core_num++; ++ continue; ++ } else if (err == -ENXIO) + continue; + else if (err == -ESPIPE) + break; + else if (err < 0) + return err; + ++ core->core_index = core_num++; ++ bus->nr_cores++; ++ + pr_info("Core %d found: %s " + "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", +- bus->nr_cores, bcma_device_name(&core->id), ++ core->core_index, bcma_device_name(&core->id), + core->id.manuf, core->id.id, core->id.rev, + core->id.class); + +- core->core_index = bus->nr_cores++; + list_add(&core->list, &bus->cores); + } + + return 0; + } ++ ++int __init bcma_bus_scan_early(struct bcma_bus *bus, ++ struct bcma_device_id *match, ++ struct bcma_device *core) ++{ ++ u32 erombase; ++ u32 __iomem *eromptr, *eromend; ++ ++ int err, core_num = 0; ++ ++ erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); ++ eromptr = bus->mmio; ++ eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32); ++ ++ bcma_scan_switch_core(bus, erombase); ++ ++ while (eromptr < eromend) { ++ memset(core, 0, sizeof(*core)); ++ INIT_LIST_HEAD(&core->list); ++ core->bus = bus; ++ ++ err = bcma_get_next_core(bus, &eromptr, match, core_num, core); ++ if (err == -ENODEV) { ++ core_num++; ++ continue; ++ } else if (err == -ENXIO) ++ continue; ++ else if (err == -ESPIPE) ++ break; ++ else if (err < 0) ++ return err; ++ ++ core->core_index = core_num++; ++ bus->nr_cores++; ++ pr_info("Core %d found: %s " ++ "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", ++ core->core_index, bcma_device_name(&core->id), ++ core->id.manuf, core->id.id, core->id.rev, ++ core->id.class); ++ ++ list_add(&core->list, &bus->cores); ++ return 0; ++ } ++ ++ return -ENODEV; ++} +--- a/include/linux/bcma/bcma.h ++++ b/include/linux/bcma/bcma.h +@@ -185,6 +185,7 @@ struct bcma_bus { + struct bcma_device *mapped_core; + struct list_head cores; + u8 nr_cores; ++ u8 init_done:1; + + struct bcma_drv_cc drv_cc; + struct bcma_drv_pci drv_pci; +--- a/include/linux/bcma/bcma_driver_chipcommon.h ++++ b/include/linux/bcma/bcma_driver_chipcommon.h +@@ -259,6 +259,7 @@ struct bcma_drv_cc { + u32 status; + u32 capabilities; + u32 capabilities_ext; ++ u8 setup_done:1; + /* Fast Powerup Delay constant */ + u16 fast_pwrup_delay; + struct bcma_chipcommon_pmu pmu; diff --git a/target/linux/brcm47xx/patches-3.0/0004-bcma-add-SOC-bus.patch b/target/linux/brcm47xx/patches-3.0/0004-bcma-add-SOC-bus.patch new file mode 100644 index 000000000..10099d103 --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0004-bcma-add-SOC-bus.patch @@ -0,0 +1,323 @@ +From a807b2fb233af60028ed38ba237953bcffdf33e9 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sat, 18 Jun 2011 14:31:53 +0200 +Subject: [PATCH 04/14] bcma: add SOC bus + +This patch adds support for using bcma on an embedded bus. An embedded +system like the bcm4716 could register this bus and it searches for the +bcma cores then. + +Signed-off-by: Hauke Mehrtens +--- + drivers/bcma/Kconfig | 5 + + drivers/bcma/Makefile | 1 + + drivers/bcma/host_soc.c | 178 +++++++++++++++++++++++++++++++++++++++++ + drivers/bcma/main.c | 1 + + drivers/bcma/scan.c | 24 +++++- + include/linux/bcma/bcma.h | 4 + + include/linux/bcma/bcma_soc.h | 16 ++++ + 7 files changed, 227 insertions(+), 2 deletions(-) + create mode 100644 drivers/bcma/host_soc.c + create mode 100644 include/linux/bcma/bcma_soc.h + +--- a/drivers/bcma/Kconfig ++++ b/drivers/bcma/Kconfig +@@ -27,6 +27,11 @@ config BCMA_HOST_PCI + bool "Support for BCMA on PCI-host bus" + depends on BCMA_HOST_PCI_POSSIBLE + ++config BCMA_HOST_SOC ++ bool ++ depends on BCMA && MIPS ++ default n ++ + config BCMA_DEBUG + bool "BCMA debugging" + depends on BCMA +--- a/drivers/bcma/Makefile ++++ b/drivers/bcma/Makefile +@@ -2,6 +2,7 @@ bcma-y += main.o scan.o core.o sprom + bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o + bcma-y += driver_pci.o + bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o ++bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o + obj-$(CONFIG_BCMA) += bcma.o + + ccflags-$(CONFIG_BCMA_DEBUG) := -DDEBUG +--- /dev/null ++++ b/drivers/bcma/host_soc.c +@@ -0,0 +1,178 @@ ++/* ++ * Broadcom specific AMBA ++ * System on Chip (SoC) Host ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++#include "bcma_private.h" ++#include "scan.h" ++#include ++#include ++ ++static u8 bcma_host_soc_read8(struct bcma_device *core, u16 offset) ++{ ++ return readb(core->io_addr + offset); ++} ++ ++static u16 bcma_host_soc_read16(struct bcma_device *core, u16 offset) ++{ ++ return readw(core->io_addr + offset); ++} ++ ++static u32 bcma_host_soc_read32(struct bcma_device *core, u16 offset) ++{ ++ return readl(core->io_addr + offset); ++} ++ ++static void bcma_host_soc_write8(struct bcma_device *core, u16 offset, ++ u8 value) ++{ ++ writeb(value, core->io_addr + offset); ++} ++ ++static void bcma_host_soc_write16(struct bcma_device *core, u16 offset, ++ u16 value) ++{ ++ writew(value, core->io_addr + offset); ++} ++ ++static void bcma_host_soc_write32(struct bcma_device *core, u16 offset, ++ u32 value) ++{ ++ writel(value, core->io_addr + offset); ++} ++ ++#ifdef CONFIG_BCMA_BLOCKIO ++static void bcma_host_soc_block_read(struct bcma_device *core, void *buffer, ++ size_t count, u16 offset, u8 reg_width) ++{ ++ void __iomem *addr = core->io_addr + offset; ++ ++ switch (reg_width) { ++ case sizeof(u8): { ++ u8 *buf = buffer; ++ ++ while (count) { ++ *buf = __raw_readb(addr); ++ buf++; ++ count--; ++ } ++ break; ++ } ++ case sizeof(u16): { ++ __le16 *buf = buffer; ++ ++ WARN_ON(count & 1); ++ while (count) { ++ *buf = (__force __le16)__raw_readw(addr); ++ buf++; ++ count -= 2; ++ } ++ break; ++ } ++ case sizeof(u32): { ++ __le32 *buf = buffer; ++ ++ WARN_ON(count & 3); ++ while (count) { ++ *buf = (__force __le32)__raw_readl(addr); ++ buf++; ++ count -= 4; ++ } ++ break; ++ } ++ default: ++ WARN_ON(1); ++ } ++} ++ ++static void bcma_host_soc_block_write(struct bcma_device *core, ++ const void *buffer, ++ size_t count, u16 offset, u8 reg_width) ++{ ++ void __iomem *addr = core->io_addr + offset; ++ ++ switch (reg_width) { ++ case sizeof(u8): { ++ const u8 *buf = buffer; ++ ++ while (count) { ++ __raw_writeb(*buf, addr); ++ buf++; ++ count--; ++ } ++ break; ++ } ++ case sizeof(u16): { ++ const __le16 *buf = buffer; ++ ++ WARN_ON(count & 1); ++ while (count) { ++ __raw_writew((__force u16)(*buf), addr); ++ buf++; ++ count -= 2; ++ } ++ break; ++ } ++ case sizeof(u32): { ++ const __le32 *buf = buffer; ++ ++ WARN_ON(count & 3); ++ while (count) { ++ __raw_writel((__force u32)(*buf), addr); ++ buf++; ++ count -= 4; ++ } ++ break; ++ } ++ default: ++ WARN_ON(1); ++ } ++} ++#endif /* CONFIG_BCMA_BLOCKIO */ ++ ++static u32 bcma_host_soc_aread32(struct bcma_device *core, u16 offset) ++{ ++ return readl(core->io_wrap + offset); ++} ++ ++static void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset, ++ u32 value) ++{ ++ writel(value, core->io_wrap + offset); ++} ++ ++const struct bcma_host_ops bcma_host_soc_ops = { ++ .read8 = bcma_host_soc_read8, ++ .read16 = bcma_host_soc_read16, ++ .read32 = bcma_host_soc_read32, ++ .write8 = bcma_host_soc_write8, ++ .write16 = bcma_host_soc_write16, ++ .write32 = bcma_host_soc_write32, ++#ifdef CONFIG_BCMA_BLOCKIO ++ .block_read = bcma_host_soc_block_read, ++ .block_write = bcma_host_soc_block_write, ++#endif ++ .aread32 = bcma_host_soc_aread32, ++ .awrite32 = bcma_host_soc_awrite32, ++}; ++ ++int __init bcma_host_soc_register(struct bcma_soc *soc) ++{ ++ struct bcma_bus *bus = &soc->bus; ++ ++ /* iomap only first core. We have to read some register on this core ++ * to scan the bus. ++ */ ++ bus->mmio = ioremap(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1); ++ if (!bus->mmio) ++ return -ENOMEM; ++ ++ /* Host specific */ ++ bus->hosttype = BCMA_HOSTTYPE_SOC; ++ bus->ops = &bcma_host_soc_ops; ++ ++ /* Register */ ++ return bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips); ++} +--- a/drivers/bcma/main.c ++++ b/drivers/bcma/main.c +@@ -95,6 +95,7 @@ static int bcma_register_cores(struct bc + break; + case BCMA_HOSTTYPE_NONE: + case BCMA_HOSTTYPE_SDIO: ++ case BCMA_HOSTTYPE_SOC: + break; + } + +--- a/drivers/bcma/scan.c ++++ b/drivers/bcma/scan.c +@@ -337,6 +337,14 @@ static int bcma_get_next_core(struct bcm + } + } + } ++ if (bus->hosttype == BCMA_HOSTTYPE_SOC) { ++ core->io_addr = ioremap(core->addr, BCMA_CORE_SIZE); ++ if (!core->io_addr) ++ return -ENOMEM; ++ core->io_wrap = ioremap(core->wrap, BCMA_CORE_SIZE); ++ if (!core->io_wrap) ++ return -ENOMEM; ++ } + return 0; + } + +@@ -369,7 +377,13 @@ int bcma_bus_scan(struct bcma_bus *bus) + bcma_init_bus(bus); + + erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); +- eromptr = bus->mmio; ++ if (bus->hosttype == BCMA_HOSTTYPE_SOC) { ++ eromptr = ioremap(erombase, BCMA_CORE_SIZE); ++ if (!eromptr) ++ return -ENOMEM; ++ } else ++ eromptr = bus->mmio; ++ + eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32); + + bcma_scan_switch_core(bus, erombase); +@@ -417,7 +431,13 @@ int __init bcma_bus_scan_early(struct bc + int err, core_num = 0; + + erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); +- eromptr = bus->mmio; ++ if (bus->hosttype == BCMA_HOSTTYPE_SOC) { ++ eromptr = ioremap(erombase, BCMA_CORE_SIZE); ++ if (!eromptr) ++ return -ENOMEM; ++ } else ++ eromptr = bus->mmio; ++ + eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32); + + bcma_scan_switch_core(bus, erombase); +--- a/include/linux/bcma/bcma.h ++++ b/include/linux/bcma/bcma.h +@@ -17,6 +17,7 @@ enum bcma_hosttype { + BCMA_HOSTTYPE_NONE, + BCMA_HOSTTYPE_PCI, + BCMA_HOSTTYPE_SDIO, ++ BCMA_HOSTTYPE_SOC, + }; + + struct bcma_chipinfo { +@@ -133,6 +134,9 @@ struct bcma_device { + u32 addr; + u32 wrap; + ++ void __iomem *io_addr; ++ void __iomem *io_wrap; ++ + void *drvdata; + struct list_head list; + }; +--- /dev/null ++++ b/include/linux/bcma/bcma_soc.h +@@ -0,0 +1,16 @@ ++#ifndef LINUX_BCMA_SOC_H_ ++#define LINUX_BCMA_SOC_H_ ++ ++#include ++ ++struct bcma_soc { ++ struct bcma_bus bus; ++ struct bcma_device core_cc; ++ struct bcma_device core_mips; ++}; ++ ++int __init bcma_host_soc_register(struct bcma_soc *soc); ++ ++int bcma_bus_register(struct bcma_bus *bus); ++ ++#endif /* LINUX_BCMA_SOC_H_ */ diff --git a/target/linux/brcm47xx/patches-3.0/0005-bcma-add-mips-driver.patch b/target/linux/brcm47xx/patches-3.0/0005-bcma-add-mips-driver.patch new file mode 100644 index 000000000..62cd10290 --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0005-bcma-add-mips-driver.patch @@ -0,0 +1,402 @@ +From 0a1a5fd8aab864e7b531ab88fd317ff7278d884d Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Mon, 6 Jun 2011 00:07:32 +0200 +Subject: [PATCH 05/14] 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 +system. + +Signed-off-by: Hauke Mehrtens +--- + drivers/bcma/Kconfig | 11 ++- + drivers/bcma/Makefile | 1 + + drivers/bcma/driver_mips.c | 234 +++++++++++++++++++++++++++++++++ + drivers/bcma/main.c | 19 +++ + include/linux/bcma/bcma.h | 2 + + include/linux/bcma/bcma_driver_mips.h | 49 +++++++ + 6 files changed, 315 insertions(+), 1 deletions(-) + create mode 100644 drivers/bcma/driver_mips.c + create mode 100644 include/linux/bcma/bcma_driver_mips.h + +--- a/drivers/bcma/Kconfig ++++ b/drivers/bcma/Kconfig +@@ -29,9 +29,18 @@ config BCMA_HOST_PCI + + config BCMA_HOST_SOC + bool +- depends on BCMA && MIPS ++ depends on BCMA_DRIVER_MIPS + default n + ++config BCMA_DRIVER_MIPS ++ bool "BCMA Broadcom MIPS core driver" ++ depends on BCMA && MIPS ++ help ++ Driver for the Broadcom MIPS core attached to Broadcom specific ++ Advanced Microcontroller Bus. ++ ++ If unsure, say N ++ + config BCMA_DEBUG + bool "BCMA debugging" + depends on BCMA +--- a/drivers/bcma/Makefile ++++ b/drivers/bcma/Makefile +@@ -1,6 +1,7 @@ + bcma-y += main.o scan.o core.o sprom.o + bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o + bcma-y += driver_pci.o ++bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o + bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o + bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o + obj-$(CONFIG_BCMA) += bcma.o +--- /dev/null ++++ b/drivers/bcma/driver_mips.c +@@ -0,0 +1,234 @@ ++/* ++ * Broadcom specific AMBA ++ * Broadcom MIPS32 74K core driver ++ * ++ * Copyright 2009, Broadcom Corporation ++ * Copyright 2006, 2007, Michael Buesch ++ * Copyright 2010, Bernhard Loos ++ * Copyright 2011, Hauke Mehrtens ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++#include "bcma_private.h" ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++/* The 47162a0 hangs when reading its registers */ ++static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev) ++{ ++ return dev->bus->chipinfo.id == 47162 && dev->bus->chipinfo.rev == 0 && ++ dev->id.id == BCMA_CORE_MIPS_74K; ++} ++ ++static inline u32 mips_read32(struct bcma_drv_mips *mcore, ++ u16 offset) ++{ ++ return bcma_read32(mcore->core, offset); ++} ++ ++static inline void mips_write32(struct bcma_drv_mips *mcore, ++ u16 offset, ++ u32 value) ++{ ++ bcma_write32(mcore->core, offset, value); ++} ++ ++static const u32 ipsflag_irq_mask[] = { ++ 0, ++ BCMA_MIPS_IPSFLAG_IRQ1, ++ BCMA_MIPS_IPSFLAG_IRQ2, ++ BCMA_MIPS_IPSFLAG_IRQ3, ++ BCMA_MIPS_IPSFLAG_IRQ4, ++}; ++ ++static const u32 ipsflag_irq_shift[] = { ++ 0, ++ BCMA_MIPS_IPSFLAG_IRQ1_SHIFT, ++ BCMA_MIPS_IPSFLAG_IRQ2_SHIFT, ++ BCMA_MIPS_IPSFLAG_IRQ3_SHIFT, ++ BCMA_MIPS_IPSFLAG_IRQ4_SHIFT, ++}; ++ ++static u32 bcma_core_mips_irqflag(struct bcma_device *dev) ++{ ++ u32 flag; ++ ++ if (bcma_core_mips_bcm47162a0_quirk(dev)) ++ return dev->core_index; ++ flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30); ++ ++ return flag & 0x1F; ++} ++ ++ ++/* Get the MIPS IRQ assignment for a specified device. ++ * If unassigned, 0 is returned. ++ * If disabled, 5 is returned. ++ */ ++unsigned int bcma_core_mips_irq(struct bcma_device *dev) ++{ ++ struct bcma_device *mdev = dev->bus->drv_mips.core; ++ u32 irqflag; ++ unsigned int irq; ++ ++ irqflag = bcma_core_mips_irqflag(dev); ++ ++ for (irq = 1; irq <= 4; irq++) ++ if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) & ++ (1 << irqflag)) ++ return irq; ++ ++ return 0; ++} ++EXPORT_SYMBOL(bcma_core_mips_irq); ++ ++static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq) ++{ ++ unsigned int oldirq = bcma_core_mips_irq(dev); ++ struct bcma_bus *bus = dev->bus; ++ struct bcma_device *mdev = bus->drv_mips.core; ++ u32 irqflag; ++ ++ irqflag = bcma_core_mips_irqflag(dev); ++ BUG_ON(oldirq == 6); ++ ++ dev->irq = irq + 2; ++ ++ /* clear the old irq */ ++ if (oldirq == 0) ++ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0), ++ bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) & ++ ~(1 << irqflag)); ++ else ++ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq), 0); ++ ++ /* assign the new one */ ++ if (irq == 0) { ++ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0), ++ bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) | ++ (1 << irqflag)); ++ } else { ++ u32 oldirqflag = bcma_read32(mdev, ++ BCMA_MIPS_MIPS74K_INTMASK(irq)); ++ if (oldirqflag) { ++ struct bcma_device *core; ++ ++ /* backplane irq line is in use, find out who uses ++ * it and set user to irq 0 ++ */ ++ list_for_each_entry_reverse(core, &bus->cores, list) { ++ if ((1 << bcma_core_mips_irqflag(core)) == ++ oldirqflag) { ++ bcma_core_mips_set_irq(core, 0); ++ break; ++ } ++ } ++ } ++ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq), ++ 1 << irqflag); ++ } ++ ++ pr_info("set_irq: core 0x%04x, irq %d => %d\n", ++ dev->id.id, oldirq + 2, irq + 2); ++} ++ ++static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq) ++{ ++ int i; ++ static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; ++ printk(KERN_INFO KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id); ++ for (i = 0; i <= 6; i++) ++ printk(" %s%s", irq_name[i], i == irq ? "*" : " "); ++ printk("\n"); ++} ++ ++static void bcma_core_mips_dump_irq(struct bcma_bus *bus) ++{ ++ struct bcma_device *core; ++ ++ list_for_each_entry_reverse(core, &bus->cores, list) { ++ bcma_core_mips_print_irq(core, bcma_core_mips_irq(core)); ++ } ++} ++ ++static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore) ++{ ++ struct bcma_bus *bus = mcore->core->bus; ++ ++ mcore->flash_buswidth = 2; ++ if (bus->drv_cc.core) { ++ mcore->flash_window = 0x1c000000; ++ mcore->flash_window_size = 0x02000000; ++ switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) { ++ case BCMA_CC_FLASHT_STSER: ++ case BCMA_CC_FLASHT_ATSER: ++ pr_err("Serial flash not supported.\n"); ++ break; ++ case BCMA_CC_FLASHT_PARA: ++ if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) & ++ BCMA_CC_OTPS) == 0) ++ mcore->flash_buswidth = 1; ++ break; ++ } ++ } else { ++ mcore->flash_window = 0x1fc00000; ++ mcore->flash_window_size = 0x00400000; ++ } ++} ++ ++void bcma_core_mips_init(struct bcma_drv_mips *mcore) ++{ ++ struct bcma_bus *bus; ++ struct bcma_device *core; ++ bus = mcore->core->bus; ++ ++ pr_info("Initializing MIPS core...\n"); ++ ++ if (!mcore->setup_done) ++ mcore->assigned_irqs = 1; ++ ++ /* Assign IRQs to all cores on the bus */ ++ list_for_each_entry_reverse(core, &bus->cores, list) { ++ int mips_irq; ++ if (core->irq) ++ continue; ++ ++ mips_irq = bcma_core_mips_irq(core); ++ if (mips_irq > 4) ++ core->irq = 0; ++ else ++ core->irq = mips_irq + 2; ++ if (core->irq > 5) ++ continue; ++ switch (core->id.id) { ++ case BCMA_CORE_PCI: ++ case BCMA_CORE_PCIE: ++ case BCMA_CORE_ETHERNET: ++ case BCMA_CORE_ETHERNET_GBIT: ++ case BCMA_CORE_MAC_GBIT: ++ case BCMA_CORE_80211: ++ case BCMA_CORE_USB20_HOST: ++ /* These devices get their own IRQ line if available, ++ * the rest goes on IRQ0 ++ */ ++ if (mcore->assigned_irqs <= 4) ++ bcma_core_mips_set_irq(core, ++ mcore->assigned_irqs++); ++ break; ++ } ++ } ++ pr_info("IRQ reconfiguration done\n"); ++ bcma_core_mips_dump_irq(bus); ++ ++ if (mcore->setup_done) ++ return; ++ ++ bcma_core_mips_flash_detect(mcore); ++ mcore->setup_done = true; ++} +--- a/drivers/bcma/main.c ++++ b/drivers/bcma/main.c +@@ -80,6 +80,7 @@ static int bcma_register_cores(struct bc + case BCMA_CORE_CHIPCOMMON: + case BCMA_CORE_PCI: + case BCMA_CORE_PCIE: ++ case BCMA_CORE_MIPS_74K: + continue; + } + +@@ -141,6 +142,15 @@ int bcma_bus_register(struct bcma_bus *b + bcma_core_chipcommon_init(&bus->drv_cc); + } + ++#ifdef CONFIG_BCMA_DRIVER_MIPS ++ /* Init MIPS core */ ++ core = bcma_find_core(bus, BCMA_CORE_MIPS_74K); ++ if (core) { ++ bus->drv_mips.core = core; ++ bcma_core_mips_init(&bus->drv_mips); ++ } ++#endif ++ + /* Init PCIE core */ + core = bcma_find_core(bus, BCMA_CORE_PCIE); + if (core) { +@@ -208,6 +218,15 @@ int __init bcma_bus_early_register(struc + bcma_core_chipcommon_init(&bus->drv_cc); + } + ++#ifdef CONFIG_BCMA_DRIVER_MIPS ++ /* Init MIPS core */ ++ core = bcma_find_core(bus, BCMA_CORE_MIPS_74K); ++ if (core) { ++ bus->drv_mips.core = core; ++ bcma_core_mips_init(&bus->drv_mips); ++ } ++#endif ++ + pr_info("Early bus registered\n"); + + return 0; +--- a/include/linux/bcma/bcma.h ++++ b/include/linux/bcma/bcma.h +@@ -6,6 +6,7 @@ + + #include + #include ++#include + #include /* SPROM sharing */ + + #include "bcma_regs.h" +@@ -193,6 +194,7 @@ struct bcma_bus { + + struct bcma_drv_cc drv_cc; + struct bcma_drv_pci drv_pci; ++ struct bcma_drv_mips drv_mips; + + /* We decided to share SPROM struct with SSB as long as we do not need + * any hacks for BCMA. This simplifies drivers code. */ +--- /dev/null ++++ b/include/linux/bcma/bcma_driver_mips.h +@@ -0,0 +1,49 @@ ++#ifndef LINUX_BCMA_DRIVER_MIPS_H_ ++#define LINUX_BCMA_DRIVER_MIPS_H_ ++ ++#define BCMA_MIPS_IPSFLAG 0x0F08 ++/* which sbflags get routed to mips interrupt 1 */ ++#define BCMA_MIPS_IPSFLAG_IRQ1 0x0000003F ++#define BCMA_MIPS_IPSFLAG_IRQ1_SHIFT 0 ++/* which sbflags get routed to mips interrupt 2 */ ++#define BCMA_MIPS_IPSFLAG_IRQ2 0x00003F00 ++#define BCMA_MIPS_IPSFLAG_IRQ2_SHIFT 8 ++/* which sbflags get routed to mips interrupt 3 */ ++#define BCMA_MIPS_IPSFLAG_IRQ3 0x003F0000 ++#define BCMA_MIPS_IPSFLAG_IRQ3_SHIFT 16 ++/* which sbflags get routed to mips interrupt 4 */ ++#define BCMA_MIPS_IPSFLAG_IRQ4 0x3F000000 ++#define BCMA_MIPS_IPSFLAG_IRQ4_SHIFT 24 ++ ++/* MIPS 74K core registers */ ++#define BCMA_MIPS_MIPS74K_CORECTL 0x0000 ++#define BCMA_MIPS_MIPS74K_EXCEPTBASE 0x0004 ++#define BCMA_MIPS_MIPS74K_BIST 0x000C ++#define BCMA_MIPS_MIPS74K_INTMASK_INT0 0x0014 ++#define BCMA_MIPS_MIPS74K_INTMASK(int) \ ++ ((int) * 4 + BCMA_MIPS_MIPS74K_INTMASK_INT0) ++#define BCMA_MIPS_MIPS74K_NMIMASK 0x002C ++#define BCMA_MIPS_MIPS74K_GPIOSEL 0x0040 ++#define BCMA_MIPS_MIPS74K_GPIOOUT 0x0044 ++#define BCMA_MIPS_MIPS74K_GPIOEN 0x0048 ++#define BCMA_MIPS_MIPS74K_CLKCTLST 0x01E0 ++ ++#define BCMA_MIPS_OOBSELOUTA30 0x100 ++ ++struct bcma_device; ++ ++struct bcma_drv_mips { ++ struct bcma_device *core; ++ u8 setup_done:1; ++ unsigned int assigned_irqs; ++ ++ u8 flash_buswidth; ++ u32 flash_window; ++ u32 flash_window_size; ++}; ++ ++extern void bcma_core_mips_init(struct bcma_drv_mips *mcore); ++ ++extern unsigned int bcma_core_mips_irq(struct bcma_device *dev); ++ ++#endif /* LINUX_BCMA_DRIVER_MIPS_H_ */ diff --git a/target/linux/brcm47xx/patches-3.0/0006-bcma-add-serial-console-support.patch b/target/linux/brcm47xx/patches-3.0/0006-bcma-add-serial-console-support.patch new file mode 100644 index 000000000..78724ee69 --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0006-bcma-add-serial-console-support.patch @@ -0,0 +1,151 @@ +From b7c100827012ba588089807475affe0c69a3f817 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Mon, 6 Jun 2011 00:07:33 +0200 +Subject: [PATCH 06/14] bcma: add serial console support + +This adds support for serial console to bcma, when operating on an +embedded device. + +Signed-off-by: Hauke Mehrtens +--- + drivers/bcma/bcma_private.h | 6 +++ + drivers/bcma/driver_chipcommon.c | 64 +++++++++++++++++++++++++++++++++ + drivers/bcma/driver_mips.c | 9 +++++ + include/linux/bcma/bcma_driver_mips.h | 11 ++++++ + 4 files changed, 90 insertions(+), 0 deletions(-) + +--- a/drivers/bcma/bcma_private.h ++++ b/drivers/bcma/bcma_private.h +@@ -29,6 +29,12 @@ void bcma_init_bus(struct bcma_bus *bus) + /* sprom.c */ + int bcma_sprom_get(struct bcma_bus *bus); + ++/* driver_chipcommon.c */ ++#ifdef CONFIG_BCMA_DRIVER_MIPS ++extern int bcma_chipco_serial_init(struct bcma_drv_cc *cc, ++ struct bcma_drv_mips_serial_port *ports); ++#endif /* CONFIG_BCMA_DRIVER_MIPS */ ++ + #ifdef CONFIG_BCMA_HOST_PCI + /* host_pci.c */ + extern int __init bcma_host_pci_init(void); +--- a/drivers/bcma/driver_chipcommon.c ++++ b/drivers/bcma/driver_chipcommon.c +@@ -92,3 +92,67 @@ u32 bcma_chipco_gpio_polarity(struct bcm + { + return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value); + } ++ ++#ifdef CONFIG_BCMA_DRIVER_MIPS ++int bcma_chipco_serial_init(struct bcma_drv_cc *cc, ++ struct bcma_drv_mips_serial_port *ports) ++{ ++ int nr_ports = 0; ++ u32 plltype; ++ unsigned int irq; ++ u32 baud_base, div; ++ u32 i, n; ++ unsigned int ccrev = cc->core->id.rev; ++ ++ plltype = (cc->capabilities & BCMA_CC_CAP_PLLT); ++ irq = bcma_core_mips_irq(cc->core); ++ ++ if ((ccrev >= 11) && (ccrev != 15) && (ccrev != 20)) { ++ /* Fixed ALP clock */ ++ baud_base = 20000000; ++ if (cc->capabilities & BCMA_CC_CAP_PMU) { ++ /* FIXME: baud_base is different for devices with a PMU */ ++ WARN_ON(1); ++ } ++ div = 1; ++ if (ccrev >= 21) { ++ /* Turn off UART clock before switching clocksource. */ ++ bcma_cc_write32(cc, BCMA_CC_CORECTL, ++ bcma_cc_read32(cc, BCMA_CC_CORECTL) ++ & ~BCMA_CC_CORECTL_UARTCLKEN); ++ } ++ /* Set the override bit so we don't divide it */ ++ bcma_cc_write32(cc, BCMA_CC_CORECTL, ++ bcma_cc_read32(cc, BCMA_CC_CORECTL) ++ | BCMA_CC_CORECTL_UARTCLK0); ++ if (ccrev >= 21) { ++ /* Re-enable the UART clock. */ ++ bcma_cc_write32(cc, BCMA_CC_CORECTL, ++ bcma_cc_read32(cc, BCMA_CC_CORECTL) ++ | BCMA_CC_CORECTL_UARTCLKEN); ++ } ++ } else ++ pr_err("serial not supported on this device ccrev: 0x%x\n", ++ ccrev); ++ ++ /* Determine the registers of the UARTs */ ++ n = (cc->capabilities & BCMA_CC_CAP_NRUART); ++ for (i = 0; i < n; i++) { ++ void __iomem *cc_mmio; ++ void __iomem *uart_regs; ++ ++ cc_mmio = cc->core->bus->mmio + ++ (cc->core->core_index * BCMA_CORE_SIZE); ++ uart_regs = cc_mmio + BCMA_CC_UART0_DATA; ++ uart_regs += (i * 256); ++ ++ nr_ports++; ++ ports[i].regs = uart_regs; ++ ports[i].irq = irq; ++ ports[i].baud_base = baud_base; ++ ports[i].reg_shift = 0; ++ } ++ ++ return nr_ports; ++} ++#endif /* CONFIG_BCMA_DRIVER_MIPS */ +--- a/drivers/bcma/driver_mips.c ++++ b/drivers/bcma/driver_mips.c +@@ -157,6 +157,14 @@ static void bcma_core_mips_dump_irq(stru + } + } + ++static void bcma_core_mips_serial_init(struct bcma_drv_mips *mcore) ++{ ++ struct bcma_bus *bus = mcore->core->bus; ++ ++ mcore->nr_serial_ports = bcma_chipco_serial_init(&bus->drv_cc, ++ mcore->serial_ports); ++} ++ + static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore) + { + struct bcma_bus *bus = mcore->core->bus; +@@ -229,6 +237,7 @@ void bcma_core_mips_init(struct bcma_drv + if (mcore->setup_done) + return; + ++ bcma_core_mips_serial_init(mcore); + bcma_core_mips_flash_detect(mcore); + mcore->setup_done = true; + } +--- a/include/linux/bcma/bcma_driver_mips.h ++++ b/include/linux/bcma/bcma_driver_mips.h +@@ -32,11 +32,22 @@ + + struct bcma_device; + ++struct bcma_drv_mips_serial_port { ++ void *regs; ++ unsigned long clockspeed; ++ unsigned int irq; ++ unsigned int baud_base; ++ unsigned int reg_shift; ++}; ++ + struct bcma_drv_mips { + struct bcma_device *core; + u8 setup_done:1; + unsigned int assigned_irqs; + ++ int nr_serial_ports; ++ struct bcma_drv_mips_serial_port serial_ports[4]; ++ + u8 flash_buswidth; + u32 flash_window; + u32 flash_window_size; diff --git a/target/linux/brcm47xx/patches-3.0/0007-bcma-get-CPU-clock.patch b/target/linux/brcm47xx/patches-3.0/0007-bcma-get-CPU-clock.patch new file mode 100644 index 000000000..7acdb7430 --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0007-bcma-get-CPU-clock.patch @@ -0,0 +1,204 @@ +From 257d5fe12600f08df764cac0abc17bef7b6fae9b Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sun, 19 Jun 2011 17:51:30 +0200 +Subject: [PATCH 07/14] 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. + +Signed-off-by: Hauke Mehrtens +--- + drivers/bcma/bcma_private.h | 3 + + drivers/bcma/driver_chipcommon_pmu.c | 87 +++++++++++++++++++++++++++ + drivers/bcma/driver_mips.c | 12 ++++ + include/linux/bcma/bcma_driver_chipcommon.h | 35 +++++++++++ + include/linux/bcma/bcma_driver_mips.h | 1 + + 5 files changed, 138 insertions(+), 0 deletions(-) + +--- a/drivers/bcma/bcma_private.h ++++ b/drivers/bcma/bcma_private.h +@@ -29,6 +29,9 @@ void bcma_init_bus(struct bcma_bus *bus) + /* sprom.c */ + int bcma_sprom_get(struct bcma_bus *bus); + ++/* driver_chipcommon_pmu.c */ ++extern u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc); ++ + /* driver_chipcommon.c */ + #ifdef CONFIG_BCMA_DRIVER_MIPS + extern int bcma_chipco_serial_init(struct bcma_drv_cc *cc, +--- a/drivers/bcma/driver_chipcommon_pmu.c ++++ b/drivers/bcma/driver_chipcommon_pmu.c +@@ -11,6 +11,13 @@ + #include "bcma_private.h" + #include + ++static u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset) ++{ ++ bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); ++ bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); ++ return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); ++} ++ + static void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, + u32 offset, u32 mask, u32 set) + { +@@ -136,3 +143,83 @@ void bcma_pmu_init(struct bcma_drv_cc *c + bcma_pmu_swreg_init(cc); + bcma_pmu_workarounds(cc); + } ++ ++static u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc) ++{ ++ struct bcma_bus *bus = cc->core->bus; ++ ++ switch (bus->chipinfo.id) { ++ case 0x4716: ++ case 0x4748: ++ case 47162: ++ /* always 20Mhz */ ++ return 20000 * 1000; ++ default: ++ pr_warn("No ALP clock specified for %04X device, " ++ "pmu rev. %d, using default %d Hz\n", ++ bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK); ++ } ++ return BCMA_CC_PMU_ALP_CLOCK; ++} ++ ++/* Find the output of the "m" pll divider given pll controls that start with ++ * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc. ++ */ ++static u32 bcma_pmu_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m) ++{ ++ u32 tmp, div, ndiv, p1, p2, fc; ++ ++ BUG_ON(!m || m > 4); ++ ++ BUG_ON((pll0 & 3) || (pll0 > BCMA_CC_PMU4716_MAINPLL_PLL0)); ++ ++ tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_P1P2_OFF); ++ p1 = (tmp & BCMA_CC_PPL_P1_MASK) >> BCMA_CC_PPL_P1_SHIFT; ++ p2 = (tmp & BCMA_CC_PPL_P2_MASK) >> BCMA_CC_PPL_P2_SHIFT; ++ ++ tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_M14_OFF); ++ div = (tmp >> ((m - 1) * BCMA_CC_PPL_MDIV_WIDTH)) & ++ BCMA_CC_PPL_MDIV_MASK; ++ ++ tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_NM5_OFF); ++ ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT; ++ ++ /* Do calculation in Mhz */ ++ fc = bcma_pmu_alp_clock(cc) / 1000000; ++ fc = (p1 * ndiv * fc) / p2; ++ ++ /* Return clock in Hertz */ ++ return (fc / div) * 1000000; ++} ++ ++/* query bus clock frequency for PMU-enabled chipcommon */ ++u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc) ++{ ++ struct bcma_bus *bus = cc->core->bus; ++ ++ switch (bus->chipinfo.id) { ++ case 0x4716: ++ case 0x4748: ++ case 47162: ++ return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0, ++ BCMA_CC_PMU5_MAINPLL_SSB); ++ default: ++ pr_warn("No backplane clock specified for %04X device, " ++ "pmu rev. %d, using default %d Hz\n", ++ bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK); ++ } ++ return BCMA_CC_PMU_HT_CLOCK; ++} ++ ++/* query cpu clock frequency for PMU-enabled chipcommon */ ++u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc) ++{ ++ struct bcma_bus *bus = cc->core->bus; ++ ++ if ((cc->pmu.rev == 5 || cc->pmu.rev == 6 || cc->pmu.rev == 7) && ++ (bus->chipinfo.id != 0x4319)) ++ return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0, ++ BCMA_CC_PMU5_MAINPLL_CPU); ++ ++ return bcma_pmu_get_clockcontrol(cc); ++} +--- a/drivers/bcma/driver_mips.c ++++ b/drivers/bcma/driver_mips.c +@@ -157,6 +157,18 @@ static void bcma_core_mips_dump_irq(stru + } + } + ++u32 bcma_cpu_clock(struct bcma_drv_mips *mcore) ++{ ++ struct bcma_bus *bus = mcore->core->bus; ++ ++ if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU) ++ return bcma_pmu_get_clockcpu(&bus->drv_cc); ++ ++ pr_err("No PMU available, need this to get the cpu clock\n"); ++ return 0; ++} ++EXPORT_SYMBOL(bcma_cpu_clock); ++ + static void bcma_core_mips_serial_init(struct bcma_drv_mips *mcore) + { + struct bcma_bus *bus = mcore->core->bus; +--- a/include/linux/bcma/bcma_driver_chipcommon.h ++++ b/include/linux/bcma/bcma_driver_chipcommon.h +@@ -246,6 +246,41 @@ + #define BCMA_CC_PLLCTL_DATA 0x0664 + #define BCMA_CC_SPROM 0x0830 /* SPROM beginning */ + ++/* Divider allocation in 4716/47162/5356 */ ++#define BCMA_CC_PMU5_MAINPLL_CPU 1 ++#define BCMA_CC_PMU5_MAINPLL_MEM 2 ++#define BCMA_CC_PMU5_MAINPLL_SSB 3 ++ ++/* PLL usage in 4716/47162 */ ++#define BCMA_CC_PMU4716_MAINPLL_PLL0 12 ++ ++/* ALP clock on pre-PMU chips */ ++#define BCMA_CC_PMU_ALP_CLOCK 20000000 ++/* HT clock for systems with PMU-enabled chipcommon */ ++#define BCMA_CC_PMU_HT_CLOCK 80000000 ++ ++/* PMU rev 5 (& 6) */ ++#define BCMA_CC_PPL_P1P2_OFF 0 ++#define BCMA_CC_PPL_P1_MASK 0x0f000000 ++#define BCMA_CC_PPL_P1_SHIFT 24 ++#define BCMA_CC_PPL_P2_MASK 0x00f00000 ++#define BCMA_CC_PPL_P2_SHIFT 20 ++#define BCMA_CC_PPL_M14_OFF 1 ++#define BCMA_CC_PPL_MDIV_MASK 0x000000ff ++#define BCMA_CC_PPL_MDIV_WIDTH 8 ++#define BCMA_CC_PPL_NM5_OFF 2 ++#define BCMA_CC_PPL_NDIV_MASK 0xfff00000 ++#define BCMA_CC_PPL_NDIV_SHIFT 20 ++#define BCMA_CC_PPL_FMAB_OFF 3 ++#define BCMA_CC_PPL_MRAT_MASK 0xf0000000 ++#define BCMA_CC_PPL_MRAT_SHIFT 28 ++#define BCMA_CC_PPL_ABRAT_MASK 0x08000000 ++#define BCMA_CC_PPL_ABRAT_SHIFT 27 ++#define BCMA_CC_PPL_FDIV_MASK 0x07ffffff ++#define BCMA_CC_PPL_PLLCTL_OFF 4 ++#define BCMA_CC_PPL_PCHI_OFF 5 ++#define BCMA_CC_PPL_PCHI_MASK 0x0000003f ++ + /* Data for the PMU, if available. + * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU) + */ +--- a/include/linux/bcma/bcma_driver_mips.h ++++ b/include/linux/bcma/bcma_driver_mips.h +@@ -54,6 +54,7 @@ struct bcma_drv_mips { + }; + + extern void bcma_core_mips_init(struct bcma_drv_mips *mcore); ++extern u32 bcma_cpu_clock(struct bcma_drv_mips *mcore); + + extern unsigned int bcma_core_mips_irq(struct bcma_device *dev); + diff --git a/target/linux/brcm47xx/patches-3.0/0008-bcma-add-pci-e-host-mode.patch b/target/linux/brcm47xx/patches-3.0/0008-bcma-add-pci-e-host-mode.patch new file mode 100644 index 000000000..48c18bb0b --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0008-bcma-add-pci-e-host-mode.patch @@ -0,0 +1,140 @@ +From f93062e72447b4a4a51afbe33ea086ce8c922587 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sun, 19 Jun 2011 17:52:09 +0200 +Subject: [PATCH 08/14] bcma: add pci(e) host mode + +This adds some stub for a pci(e) host controller. This controller is +found on some embedded devices to attach other chips. + +Signed-off-by: Hauke Mehrtens +--- + drivers/bcma/Kconfig | 6 ++++ + drivers/bcma/Makefile | 1 + + drivers/bcma/bcma_private.h | 6 ++++ + drivers/bcma/driver_pci.c | 14 ++++++++++- + drivers/bcma/driver_pci_host.c | 43 ++++++++++++++++++++++++++++++++++ + include/linux/bcma/bcma_driver_pci.h | 1 + + 6 files changed, 70 insertions(+), 1 deletions(-) + create mode 100644 drivers/bcma/driver_pci_host.c + +--- a/drivers/bcma/Kconfig ++++ b/drivers/bcma/Kconfig +@@ -32,6 +32,12 @@ config BCMA_HOST_SOC + depends on BCMA_DRIVER_MIPS + default n + ++config BCMA_DRIVER_PCI_HOSTMODE ++ bool "Hostmode support for BCMA PCI core" ++ depends on BCMA_DRIVER_MIPS ++ help ++ PCIcore hostmode operation (external PCI bus). ++ + config BCMA_DRIVER_MIPS + bool "BCMA Broadcom MIPS core driver" + depends on BCMA && MIPS +--- a/drivers/bcma/Makefile ++++ b/drivers/bcma/Makefile +@@ -1,6 +1,7 @@ + bcma-y += main.o scan.o core.o sprom.o + bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o + bcma-y += driver_pci.o ++bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o + bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o + bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o + bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o +--- a/drivers/bcma/bcma_private.h ++++ b/drivers/bcma/bcma_private.h +@@ -38,6 +38,12 @@ extern int bcma_chipco_serial_init(struc + struct bcma_drv_mips_serial_port *ports); + #endif /* CONFIG_BCMA_DRIVER_MIPS */ + ++#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE ++/* driver_pci_host.c */ ++int bcma_core_pci_in_hostmode(struct bcma_drv_pci *pc); ++void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); ++#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ ++ + #ifdef CONFIG_BCMA_HOST_PCI + /* host_pci.c */ + extern int __init bcma_host_pci_init(void); +--- a/drivers/bcma/driver_pci.c ++++ b/drivers/bcma/driver_pci.c +@@ -159,9 +159,21 @@ static void bcma_pcicore_serdes_workarou + + void bcma_core_pci_init(struct bcma_drv_pci *pc) + { ++ struct bcma_device *core = pc->core; ++ + if (pc->setup_done) + return; +- bcma_pcicore_serdes_workaround(pc); ++ ++ if (!bcma_core_is_enabled(core)) ++ bcma_core_enable(core, 0); ++#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE ++ pc->hostmode = bcma_core_pci_in_hostmode(pc); ++ if (pc->hostmode) ++ bcma_core_pci_hostmode_init(pc); ++#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ ++ if (!pc->hostmode) ++ bcma_pcicore_serdes_workaround(pc); ++ + pc->setup_done = true; + } + +--- /dev/null ++++ b/drivers/bcma/driver_pci_host.c +@@ -0,0 +1,43 @@ ++/* ++ * Broadcom specific AMBA ++ * PCI Host mode ++ * ++ * Copyright 2005, Broadcom Corporation ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++#include "bcma_private.h" ++#include ++ ++#include ++/* Probe a 32bit value on the bus and catch bus exceptions. ++ * Returns nonzero on a bus exception. ++ * This is MIPS specific */ ++#define mips_busprobe32(val, addr) get_dbe((val), ((u32 *)(addr))) ++ ++ ++void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) ++{ ++ /* TODO: implement PCI host mode */ ++} ++ ++int bcma_core_pci_in_hostmode(struct bcma_drv_pci *pc) ++{ ++ struct bcma_bus *bus = pc->core->bus; ++ u16 chipid_top; ++ u32 tmp; ++ ++ chipid_top = (bus->chipinfo.id & 0xFF00); ++ if (chipid_top != 0x4700 && ++ chipid_top != 0x5300) ++ return 0; ++ ++/* TODO: add when sprom is available ++ * if (bus->sprom.boardflags_lo & SSB_PCICORE_BFL_NOPCI) ++ * return 0; ++ */ ++ ++ return !mips_busprobe32(tmp, (bus->mmio + (pc->core->core_index * ++ BCMA_CORE_SIZE))); ++} +--- a/include/linux/bcma/bcma_driver_pci.h ++++ b/include/linux/bcma/bcma_driver_pci.h +@@ -78,6 +78,7 @@ struct pci_dev; + struct bcma_drv_pci { + struct bcma_device *core; + u8 setup_done:1; ++ u8 hostmode:1; + }; + + /* Register access */ diff --git a/target/linux/brcm47xx/patches-3.0/0009-bcma-add-check-if-sprom-is-available-before-accessin.patch b/target/linux/brcm47xx/patches-3.0/0009-bcma-add-check-if-sprom-is-available-before-accessin.patch new file mode 100644 index 000000000..931b6e3d0 --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0009-bcma-add-check-if-sprom-is-available-before-accessin.patch @@ -0,0 +1,37 @@ +From 5972feafaa3c71c1497b4ef4101b3c6855b7b64e Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sun, 19 Jun 2011 19:14:11 +0200 +Subject: [PATCH 09/14] bcma: add check if sprom is available before accessing it. + + +Signed-off-by: Hauke Mehrtens +--- + drivers/bcma/main.c | 4 +++- + drivers/bcma/sprom.c | 3 +++ + 2 files changed, 6 insertions(+), 1 deletions(-) + +--- a/drivers/bcma/main.c ++++ b/drivers/bcma/main.c +@@ -160,7 +160,9 @@ int bcma_bus_register(struct bcma_bus *b + + /* Try to get SPROM */ + err = bcma_sprom_get(bus); +- if (err) { ++ if (err == -ENOENT) { ++ pr_err("No SPROM available\n"); ++ } else if (err) { + pr_err("Failed to get SPROM: %d\n", err); + return -ENOENT; + } +--- a/drivers/bcma/sprom.c ++++ b/drivers/bcma/sprom.c +@@ -143,6 +143,9 @@ int bcma_sprom_get(struct bcma_bus *bus) + if (!bus->drv_cc.core) + return -EOPNOTSUPP; + ++ if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM)) ++ return -ENOENT; ++ + sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), + GFP_KERNEL); + if (!sprom) diff --git a/target/linux/brcm47xx/patches-3.0/0010-bcm47xx-prepare-to-support-different-buses.patch b/target/linux/brcm47xx/patches-3.0/0010-bcm47xx-prepare-to-support-different-buses.patch new file mode 100644 index 000000000..4363a5bd9 --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0010-bcm47xx-prepare-to-support-different-buses.patch @@ -0,0 +1,439 @@ +From c0886db6357de20fba4f7c0602eceefba3ad343b Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Mon, 6 Jun 2011 00:07:36 +0200 +Subject: [PATCH 10/14] bcm47xx: prepare to support different buses + +The ssb bus is not hod directly any more. there is now a union which +contains all the supported buses, now just ssb. As just one system bus +can be used at a time the union does not cause any problems. + +Signed-off-by: Hauke Mehrtens +--- + arch/mips/bcm47xx/gpio.c | 56 ++++++++++++++++---------- + arch/mips/bcm47xx/nvram.c | 15 +++++-- + arch/mips/bcm47xx/serial.c | 13 +++++- + arch/mips/bcm47xx/setup.c | 32 +++++++++++--- + arch/mips/bcm47xx/time.c | 9 +++- + arch/mips/bcm47xx/wgt634u.c | 13 ++++-- + arch/mips/include/asm/mach-bcm47xx/bcm47xx.h | 14 ++++++- + arch/mips/include/asm/mach-bcm47xx/gpio.h | 55 ++++++++++++++++++------- + drivers/watchdog/bcm47xx_wdt.c | 12 +++++- + 9 files changed, 158 insertions(+), 61 deletions(-) + +--- a/arch/mips/bcm47xx/gpio.c ++++ b/arch/mips/bcm47xx/gpio.c +@@ -20,42 +20,54 @@ static DECLARE_BITMAP(gpio_in_use, BCM47 + + int gpio_request(unsigned gpio, const char *tag) + { +- if (ssb_chipco_available(&ssb_bcm47xx.chipco) && +- ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES)) +- return -EINVAL; +- +- if (ssb_extif_available(&ssb_bcm47xx.extif) && +- ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES)) +- return -EINVAL; +- +- if (test_and_set_bit(gpio, gpio_in_use)) +- return -EBUSY; +- +- return 0; ++ switch (bcm47xx_active_bus_type) { ++ case BCM47XX_BUS_TYPE_SSB: ++ if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) && ++ ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES)) ++ return -EINVAL; ++ ++ if (ssb_extif_available(&bcm47xx_bus.ssb.extif) && ++ ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES)) ++ return -EINVAL; ++ ++ if (test_and_set_bit(gpio, gpio_in_use)) ++ return -EBUSY; ++ ++ return 0; ++ } ++ return -EINVAL; + } + EXPORT_SYMBOL(gpio_request); + + void gpio_free(unsigned gpio) + { +- if (ssb_chipco_available(&ssb_bcm47xx.chipco) && +- ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES)) +- return; ++ switch (bcm47xx_active_bus_type) { ++ case BCM47XX_BUS_TYPE_SSB: ++ if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) && ++ ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES)) ++ return; ++ ++ if (ssb_extif_available(&bcm47xx_bus.ssb.extif) && ++ ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES)) ++ return; + +- if (ssb_extif_available(&ssb_bcm47xx.extif) && +- ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES)) ++ clear_bit(gpio, gpio_in_use); + return; +- +- clear_bit(gpio, gpio_in_use); ++ } + } + EXPORT_SYMBOL(gpio_free); + + int gpio_to_irq(unsigned gpio) + { +- if (ssb_chipco_available(&ssb_bcm47xx.chipco)) +- return ssb_mips_irq(ssb_bcm47xx.chipco.dev) + 2; +- else if (ssb_extif_available(&ssb_bcm47xx.extif)) +- return ssb_mips_irq(ssb_bcm47xx.extif.dev) + 2; +- else +- return -EINVAL; ++ switch (bcm47xx_active_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; ++ else if (ssb_extif_available(&bcm47xx_bus.ssb.extif)) ++ return ssb_mips_irq(bcm47xx_bus.ssb.extif.dev) + 2; ++ else ++ return -EINVAL; ++ } ++ return -EINVAL; + } + EXPORT_SYMBOL_GPL(gpio_to_irq); +--- a/arch/mips/bcm47xx/nvram.c ++++ b/arch/mips/bcm47xx/nvram.c +@@ -26,14 +26,21 @@ static char nvram_buf[NVRAM_SPACE]; + /* Probe for NVRAM header */ + static void early_nvram_init(void) + { +- struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore; ++ struct ssb_mipscore *mcore_ssb; + struct nvram_header *header; + int i; +- u32 base, lim, off; ++ u32 base = 0; ++ u32 lim = 0; ++ u32 off; + u32 *src, *dst; + +- base = mcore->flash_window; +- lim = mcore->flash_window_size; ++ switch (bcm47xx_active_bus_type) { ++ case BCM47XX_BUS_TYPE_SSB: ++ mcore_ssb = &bcm47xx_bus.ssb.mipscore; ++ base = mcore_ssb->flash_window; ++ lim = mcore_ssb->flash_window_size; ++ break; ++ } + + off = FLASH_MIN; + while (off <= lim) { +--- a/arch/mips/bcm47xx/serial.c ++++ b/arch/mips/bcm47xx/serial.c +@@ -23,10 +23,10 @@ static struct platform_device uart8250_d + }, + }; + +-static int __init uart8250_init(void) ++static int __init uart8250_init_ssb(void) + { + int i; +- struct ssb_mipscore *mcore = &(ssb_bcm47xx.mipscore); ++ struct ssb_mipscore *mcore = &(bcm47xx_bus.ssb.mipscore); + + memset(&uart8250_data, 0, sizeof(uart8250_data)); + +@@ -45,6 +45,15 @@ static int __init uart8250_init(void) + return platform_device_register(&uart8250_device); + } + ++static int __init uart8250_init(void) ++{ ++ switch (bcm47xx_active_bus_type) { ++ case BCM47XX_BUS_TYPE_SSB: ++ return uart8250_init_ssb(); ++ } ++ return -EINVAL; ++} ++ + module_init(uart8250_init); + + MODULE_AUTHOR("Aurelien Jarno "); +--- a/arch/mips/bcm47xx/setup.c ++++ b/arch/mips/bcm47xx/setup.c +@@ -35,15 +35,22 @@ + #include + #include + +-struct ssb_bus ssb_bcm47xx; +-EXPORT_SYMBOL(ssb_bcm47xx); ++union bcm47xx_bus bcm47xx_bus; ++EXPORT_SYMBOL(bcm47xx_bus); ++ ++enum bcm47xx_bus_type bcm47xx_active_bus_type; ++EXPORT_SYMBOL(bcm47xx_active_bus_type); + + static void bcm47xx_machine_restart(char *command) + { + printk(KERN_ALERT "Please stand by while rebooting the system...\n"); + local_irq_disable(); + /* Set the watchdog timer to reset immediately */ +- ssb_watchdog_timer_set(&ssb_bcm47xx, 1); ++ switch (bcm47xx_active_bus_type) { ++ case BCM47XX_BUS_TYPE_SSB: ++ ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1); ++ break; ++ } + while (1) + cpu_relax(); + } +@@ -52,7 +59,11 @@ static void bcm47xx_machine_halt(void) + { + /* Disable interrupts and watchdog and spin forever */ + local_irq_disable(); +- ssb_watchdog_timer_set(&ssb_bcm47xx, 0); ++ switch (bcm47xx_active_bus_type) { ++ case BCM47XX_BUS_TYPE_SSB: ++ ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0); ++ break; ++ } + while (1) + cpu_relax(); + } +@@ -247,7 +258,7 @@ static int bcm47xx_get_invariants(struct + return 0; + } + +-void __init plat_mem_setup(void) ++static void __init bcm47xx_register_ssb(void) + { + int err; + char buf[100]; +@@ -258,12 +269,12 @@ void __init plat_mem_setup(void) + printk(KERN_WARNING "bcm47xx: someone else already registered" + " a ssb SPROM callback handler (err %d)\n", err); + +- err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE, ++ err = ssb_bus_ssbbus_register(&(bcm47xx_bus.ssb), SSB_ENUM_BASE, + bcm47xx_get_invariants); + if (err) + panic("Failed to initialize SSB bus (err %d)\n", err); + +- mcore = &ssb_bcm47xx.mipscore; ++ mcore = &bcm47xx_bus.ssb.mipscore; + if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) { + if (strstr(buf, "console=ttyS1")) { + struct ssb_serial_port port; +@@ -276,6 +287,14 @@ void __init plat_mem_setup(void) + memcpy(&mcore->serial_ports[1], &port, sizeof(port)); + } + } ++} ++ ++void __init plat_mem_setup(void) ++{ ++ struct cpuinfo_mips *c = ¤t_cpu_data; ++ ++ bcm47xx_active_bus_type = BCM47XX_BUS_TYPE_SSB; ++ bcm47xx_register_ssb(); + + _machine_restart = bcm47xx_machine_restart; + _machine_halt = bcm47xx_machine_halt; +--- a/arch/mips/bcm47xx/time.c ++++ b/arch/mips/bcm47xx/time.c +@@ -30,7 +30,7 @@ + + void __init plat_time_init(void) + { +- unsigned long hz; ++ unsigned long hz = 0; + + /* + * Use deterministic values for initial counter interrupt +@@ -39,7 +39,12 @@ void __init plat_time_init(void) + write_c0_count(0); + write_c0_compare(0xffff); + +- hz = ssb_cpu_clock(&ssb_bcm47xx.mipscore) / 2; ++ switch (bcm47xx_active_bus_type) { ++ case BCM47XX_BUS_TYPE_SSB: ++ hz = ssb_cpu_clock(&bcm47xx_bus.ssb.mipscore) / 2; ++ break; ++ } ++ + if (!hz) + hz = 100000000; + +--- a/arch/mips/bcm47xx/wgt634u.c ++++ b/arch/mips/bcm47xx/wgt634u.c +@@ -108,7 +108,7 @@ static irqreturn_t gpio_interrupt(int ir + + /* Interrupts are shared, check if the current one is + a GPIO interrupt. */ +- if (!ssb_chipco_irq_status(&ssb_bcm47xx.chipco, ++ if (!ssb_chipco_irq_status(&bcm47xx_bus.ssb.chipco, + SSB_CHIPCO_IRQ_GPIO)) + return IRQ_NONE; + +@@ -133,21 +133,24 @@ static int __init wgt634u_init(void) + * been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx. + */ + +- u8 *et0mac = ssb_bcm47xx.sprom.et0mac; ++ if (bcm47xx_active_bus_type != BCM47XX_BUS_TYPE_SSB) ++ return -ENODEV; ++ ++ u8 *et0mac = bcm47xx_bus.ssb.sprom.et0mac; + + if (et0mac[0] == 0x00 && + ((et0mac[1] == 0x09 && et0mac[2] == 0x5b) || + (et0mac[1] == 0x0f && et0mac[2] == 0xb5))) { +- struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore; ++ struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore; + + printk(KERN_INFO "WGT634U machine detected.\n"); + + if (!request_irq(gpio_to_irq(WGT634U_GPIO_RESET), + gpio_interrupt, IRQF_SHARED, +- "WGT634U GPIO", &ssb_bcm47xx.chipco)) { ++ "WGT634U GPIO", &bcm47xx_bus.ssb.chipco)) { + gpio_direction_input(WGT634U_GPIO_RESET); + gpio_intmask(WGT634U_GPIO_RESET, 1); +- ssb_chipco_irq_mask(&ssb_bcm47xx.chipco, ++ ssb_chipco_irq_mask(&bcm47xx_bus.ssb.chipco, + SSB_CHIPCO_IRQ_GPIO, + SSB_CHIPCO_IRQ_GPIO); + } +--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h ++++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h +@@ -19,7 +19,17 @@ + #ifndef __ASM_BCM47XX_H + #define __ASM_BCM47XX_H + +-/* SSB bus */ +-extern struct ssb_bus ssb_bcm47xx; ++#include ++ ++enum bcm47xx_bus_type { ++ BCM47XX_BUS_TYPE_SSB, ++}; ++ ++union bcm47xx_bus { ++ struct ssb_bus ssb; ++}; ++ ++extern union bcm47xx_bus bcm47xx_bus; ++extern enum bcm47xx_bus_type bcm47xx_active_bus_type; + + #endif /* __ASM_BCM47XX_H */ +--- a/arch/mips/include/asm/mach-bcm47xx/gpio.h ++++ b/arch/mips/include/asm/mach-bcm47xx/gpio.h +@@ -21,41 +21,66 @@ extern int gpio_to_irq(unsigned gpio); + + static inline int gpio_get_value(unsigned gpio) + { +- return ssb_gpio_in(&ssb_bcm47xx, 1 << gpio); ++ switch (bcm47xx_active_bus_type) { ++ case BCM47XX_BUS_TYPE_SSB: ++ return ssb_gpio_in(&bcm47xx_bus.ssb, 1 << gpio); ++ } ++ return -EINVAL; + } + + 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) { ++ case BCM47XX_BUS_TYPE_SSB: ++ ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio, ++ value ? 1 << gpio : 0); ++ } + } + + static inline int gpio_direction_input(unsigned gpio) + { +- ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 0); +- return 0; ++ switch (bcm47xx_active_bus_type) { ++ case BCM47XX_BUS_TYPE_SSB: ++ ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 0); ++ return 0; ++ } ++ return -EINVAL; + } + + static inline int gpio_direction_output(unsigned gpio, int value) + { +- /* first set the gpio out value */ +- ssb_gpio_out(&ssb_bcm47xx, 1 << gpio, value ? 1 << gpio : 0); +- /* then set the gpio mode */ +- ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 1 << gpio); +- return 0; ++ switch (bcm47xx_active_bus_type) { ++ case BCM47XX_BUS_TYPE_SSB: ++ /* first set the gpio out value */ ++ ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio, ++ value ? 1 << gpio : 0); ++ /* then set the gpio mode */ ++ ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 1 << gpio); ++ return 0; ++ } ++ return -EINVAL; + } + + static inline int gpio_intmask(unsigned gpio, int value) + { +- ssb_gpio_intmask(&ssb_bcm47xx, 1 << gpio, +- value ? 1 << gpio : 0); +- return 0; ++ switch (bcm47xx_active_bus_type) { ++ case BCM47XX_BUS_TYPE_SSB: ++ ssb_gpio_intmask(&bcm47xx_bus.ssb, 1 << gpio, ++ value ? 1 << gpio : 0); ++ return 0; ++ } ++ return -EINVAL; + } + + static inline int gpio_polarity(unsigned gpio, int value) + { +- ssb_gpio_polarity(&ssb_bcm47xx, 1 << gpio, +- value ? 1 << gpio : 0); +- return 0; ++ switch (bcm47xx_active_bus_type) { ++ case BCM47XX_BUS_TYPE_SSB: ++ ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << gpio, ++ value ? 1 << gpio : 0); ++ return 0; ++ } ++ return -EINVAL; + } + + +--- a/drivers/watchdog/bcm47xx_wdt.c ++++ b/drivers/watchdog/bcm47xx_wdt.c +@@ -54,12 +54,20 @@ static atomic_t ticks; + static inline void bcm47xx_wdt_hw_start(void) + { + /* this is 2,5s on 100Mhz clock and 2s on 133 Mhz */ +- ssb_watchdog_timer_set(&ssb_bcm47xx, 0xfffffff); ++ switch (bcm47xx_active_bus_type) { ++ case BCM47XX_BUS_TYPE_SSB: ++ ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0xfffffff); ++ break; ++ } + } + + static inline int bcm47xx_wdt_hw_stop(void) + { +- return ssb_watchdog_timer_set(&ssb_bcm47xx, 0); ++ switch (bcm47xx_active_bus_type) { ++ case BCM47XX_BUS_TYPE_SSB: ++ return ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0); ++ } ++ return -EINVAL; + } + + static void bcm47xx_timer_tick(unsigned long unused) diff --git a/target/linux/brcm47xx/patches-3.0/0011-bcm47xx-make-it-possible-to-build-bcm47xx-without-ss.patch b/target/linux/brcm47xx/patches-3.0/0011-bcm47xx-make-it-possible-to-build-bcm47xx-without-ss.patch new file mode 100644 index 000000000..cfb19e065 --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0011-bcm47xx-make-it-possible-to-build-bcm47xx-without-ss.patch @@ -0,0 +1,395 @@ +From 82d03f33ba3e41511e56bd6ae5ae93b3b1bd0b63 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Wed, 22 Jun 2011 22:16:35 +0200 +Subject: [PATCH 11/14] bcm47xx: make it possible to build bcm47xx without ssb. + + +Signed-off-by: Hauke Mehrtens +--- + arch/mips/Kconfig | 8 +------- + arch/mips/bcm47xx/Kconfig | 18 ++++++++++++++++++ + arch/mips/bcm47xx/Makefile | 3 ++- + arch/mips/bcm47xx/gpio.c | 6 ++++++ + arch/mips/bcm47xx/nvram.c | 4 ++++ + arch/mips/bcm47xx/serial.c | 4 ++++ + arch/mips/bcm47xx/setup.c | 8 ++++++++ + arch/mips/bcm47xx/time.c | 2 ++ + arch/mips/include/asm/mach-bcm47xx/bcm47xx.h | 4 ++++ + arch/mips/include/asm/mach-bcm47xx/gpio.h | 12 ++++++++++++ + arch/mips/pci/pci-bcm47xx.c | 6 ++++++ + drivers/watchdog/bcm47xx_wdt.c | 4 ++++ + 12 files changed, 71 insertions(+), 8 deletions(-) + create mode 100644 arch/mips/bcm47xx/Kconfig + +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -91,15 +91,8 @@ config BCM47XX + select DMA_NONCOHERENT + select HW_HAS_PCI + select IRQ_CPU +- select SYS_HAS_CPU_MIPS32_R1 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN +- select SSB +- select SSB_DRIVER_MIPS +- select SSB_DRIVER_EXTIF +- select SSB_EMBEDDED +- select SSB_B43_PCI_BRIDGE if PCI +- select SSB_PCICORE_HOSTMODE if PCI + select GENERIC_GPIO + select SYS_HAS_EARLY_PRINTK + select CFE +@@ -785,6 +778,7 @@ endchoice + + source "arch/mips/alchemy/Kconfig" + source "arch/mips/ath79/Kconfig" ++source "arch/mips/bcm47xx/Kconfig" + source "arch/mips/bcm63xx/Kconfig" + source "arch/mips/jazz/Kconfig" + source "arch/mips/jz4740/Kconfig" +--- /dev/null ++++ b/arch/mips/bcm47xx/Kconfig +@@ -0,0 +1,18 @@ ++if BCM47XX ++ ++config BCM47XX_SSB ++ bool "SSB Support for Broadcom BCM47XX" ++ select SYS_HAS_CPU_MIPS32_R1 ++ select SSB ++ select SSB_DRIVER_MIPS ++ select SSB_DRIVER_EXTIF ++ select SSB_EMBEDDED ++ select SSB_B43_PCI_BRIDGE if PCI ++ select SSB_PCICORE_HOSTMODE if PCI ++ default y ++ help ++ Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support bus. ++ ++ This will generate an image with support for SSB and MIPS32 R2 instruction set. ++ ++endif +--- a/arch/mips/bcm47xx/Makefile ++++ b/arch/mips/bcm47xx/Makefile +@@ -3,4 +3,5 @@ + # under Linux. + # + +-obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o ++obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o ++obj-$(CONFIG_BCM47XX_SSB) += wgt634u.o +--- a/arch/mips/bcm47xx/gpio.c ++++ b/arch/mips/bcm47xx/gpio.c +@@ -21,6 +21,7 @@ static DECLARE_BITMAP(gpio_in_use, BCM47 + int gpio_request(unsigned gpio, const char *tag) + { + switch (bcm47xx_active_bus_type) { ++#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) && + ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES)) +@@ -34,6 +35,7 @@ int gpio_request(unsigned gpio, const ch + return -EBUSY; + + return 0; ++#endif + } + return -EINVAL; + } +@@ -42,6 +44,7 @@ EXPORT_SYMBOL(gpio_request); + void gpio_free(unsigned gpio) + { + switch (bcm47xx_active_bus_type) { ++#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) && + ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES)) +@@ -53,6 +56,7 @@ void gpio_free(unsigned gpio) + + clear_bit(gpio, gpio_in_use); + return; ++#endif + } + } + EXPORT_SYMBOL(gpio_free); +@@ -60,6 +64,7 @@ EXPORT_SYMBOL(gpio_free); + int gpio_to_irq(unsigned gpio) + { + switch (bcm47xx_active_bus_type) { ++#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco)) + return ssb_mips_irq(bcm47xx_bus.ssb.chipco.dev) + 2; +@@ -67,6 +72,7 @@ int gpio_to_irq(unsigned gpio) + return ssb_mips_irq(bcm47xx_bus.ssb.extif.dev) + 2; + else + return -EINVAL; ++#endif + } + return -EINVAL; + } +--- a/arch/mips/bcm47xx/nvram.c ++++ b/arch/mips/bcm47xx/nvram.c +@@ -26,7 +26,9 @@ static char nvram_buf[NVRAM_SPACE]; + /* Probe for NVRAM header */ + static void early_nvram_init(void) + { ++#ifdef CONFIG_BCM47XX_SSB + struct ssb_mipscore *mcore_ssb; ++#endif + struct nvram_header *header; + int i; + u32 base = 0; +@@ -35,11 +37,13 @@ static void early_nvram_init(void) + u32 *src, *dst; + + switch (bcm47xx_active_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; + break; ++#endif + } + + off = FLASH_MIN; +--- a/arch/mips/bcm47xx/serial.c ++++ b/arch/mips/bcm47xx/serial.c +@@ -23,6 +23,7 @@ static struct platform_device uart8250_d + }, + }; + ++#ifdef CONFIG_BCM47XX_SSB + static int __init uart8250_init_ssb(void) + { + int i; +@@ -44,12 +45,15 @@ static int __init uart8250_init_ssb(void + } + return platform_device_register(&uart8250_device); + } ++#endif + + static int __init uart8250_init(void) + { + switch (bcm47xx_active_bus_type) { ++#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + return uart8250_init_ssb(); ++#endif + } + return -EINVAL; + } +--- a/arch/mips/bcm47xx/setup.c ++++ b/arch/mips/bcm47xx/setup.c +@@ -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) { ++#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1); + break; ++#endif + } + while (1) + cpu_relax(); +@@ -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) { ++#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0); + break; ++#endif + } + while (1) + cpu_relax(); + } + ++#ifdef CONFIG_BCM47XX_SSB + #define READ_FROM_NVRAM(_outvar, name, buf) \ + if (nvram_getprefix(prefix, name, buf, sizeof(buf)) >= 0)\ + sprom->_outvar = simple_strtoul(buf, NULL, 0); +@@ -288,13 +293,16 @@ static void __init bcm47xx_register_ssb( + } + } + } ++#endif + + void __init plat_mem_setup(void) + { + struct cpuinfo_mips *c = ¤t_cpu_data; + ++#ifdef CONFIG_BCM47XX_SSB + bcm47xx_active_bus_type = BCM47XX_BUS_TYPE_SSB; + bcm47xx_register_ssb(); ++#endif + + _machine_restart = bcm47xx_machine_restart; + _machine_halt = bcm47xx_machine_halt; +--- a/arch/mips/bcm47xx/time.c ++++ b/arch/mips/bcm47xx/time.c +@@ -40,9 +40,11 @@ void __init plat_time_init(void) + write_c0_compare(0xffff); + + switch (bcm47xx_active_bus_type) { ++#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + hz = ssb_cpu_clock(&bcm47xx_bus.ssb.mipscore) / 2; + break; ++#endif + } + + if (!hz) +--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h ++++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h +@@ -22,11 +22,15 @@ + #include + + enum bcm47xx_bus_type { ++#ifdef CONFIG_BCM47XX_SSB + BCM47XX_BUS_TYPE_SSB, ++#endif + }; + + union bcm47xx_bus { ++#ifdef CONFIG_BCM47XX_SSB + struct ssb_bus ssb; ++#endif + }; + + extern union bcm47xx_bus bcm47xx_bus; +--- a/arch/mips/include/asm/mach-bcm47xx/gpio.h ++++ b/arch/mips/include/asm/mach-bcm47xx/gpio.h +@@ -22,8 +22,10 @@ extern int gpio_to_irq(unsigned gpio); + static inline int gpio_get_value(unsigned gpio) + { + switch (bcm47xx_active_bus_type) { ++#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + return ssb_gpio_in(&bcm47xx_bus.ssb, 1 << gpio); ++#endif + } + return -EINVAL; + } +@@ -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) { ++#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio, + value ? 1 << gpio : 0); ++#endif + } + } + + static inline int gpio_direction_input(unsigned gpio) + { + switch (bcm47xx_active_bus_type) { ++#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 0); + return 0; ++#endif + } + return -EINVAL; + } +@@ -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) { ++#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + /* first set the gpio out value */ + ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio, +@@ -57,6 +64,7 @@ static inline int gpio_direction_output( + /* then set the gpio mode */ + ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 1 << gpio); + return 0; ++#endif + } + return -EINVAL; + } +@@ -64,10 +72,12 @@ static inline int gpio_direction_output( + static inline int gpio_intmask(unsigned gpio, int value) + { + switch (bcm47xx_active_bus_type) { ++#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + ssb_gpio_intmask(&bcm47xx_bus.ssb, 1 << gpio, + value ? 1 << gpio : 0); + return 0; ++#endif + } + return -EINVAL; + } +@@ -75,10 +85,12 @@ static inline int gpio_intmask(unsigned + static inline int gpio_polarity(unsigned gpio, int value) + { + switch (bcm47xx_active_bus_type) { ++#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << gpio, + value ? 1 << gpio : 0); + return 0; ++#endif + } + return -EINVAL; + } +--- a/arch/mips/pci/pci-bcm47xx.c ++++ b/arch/mips/pci/pci-bcm47xx.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) + { +@@ -33,9 +34,13 @@ int __init pcibios_map_irq(const struct + + int pcibios_plat_dev_init(struct pci_dev *dev) + { ++#ifdef CONFIG_BCM47XX_SSB + int res; + u8 slot, pin; + ++ if (bcm47xx_active_bus_type != BCM47XX_BUS_TYPE_SSB) ++ return 0; ++ + res = ssb_pcibios_plat_dev_init(dev); + if (res < 0) { + printk(KERN_ALERT "PCI: Failed to init device %s\n", +@@ -55,5 +60,6 @@ int pcibios_plat_dev_init(struct pci_dev + } + + dev->irq = res; ++#endif + return 0; + } +--- a/drivers/watchdog/bcm47xx_wdt.c ++++ b/drivers/watchdog/bcm47xx_wdt.c +@@ -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) { ++#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0xfffffff); + break; ++#endif + } + } + + static inline int bcm47xx_wdt_hw_stop(void) + { + switch (bcm47xx_active_bus_type) { ++#ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: + return ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0); ++#endif + } + return -EINVAL; + } diff --git a/target/linux/brcm47xx/patches-3.0/0012-bcm47xx-add-support-for-bcma-bus.patch b/target/linux/brcm47xx/patches-3.0/0012-bcm47xx-add-support-for-bcma-bus.patch new file mode 100644 index 000000000..a800f4d68 --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0012-bcm47xx-add-support-for-bcma-bus.patch @@ -0,0 +1,410 @@ +From 0b7b4817579b5b283e48b96de24b7b2c1a861644 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Mon, 6 Jun 2011 00:07:37 +0200 +Subject: [PATCH 12/14] 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 +74K CPUs. + +Signed-off-by: Hauke Mehrtens +--- + arch/mips/bcm47xx/Kconfig | 13 ++++++ + arch/mips/bcm47xx/gpio.c | 22 +++++++++++ + arch/mips/bcm47xx/nvram.c | 10 +++++ + arch/mips/bcm47xx/serial.c | 29 ++++++++++++++ + arch/mips/bcm47xx/setup.c | 53 +++++++++++++++++++++++++- + arch/mips/bcm47xx/time.c | 5 ++ + arch/mips/include/asm/mach-bcm47xx/bcm47xx.h | 8 ++++ + arch/mips/include/asm/mach-bcm47xx/gpio.h | 41 ++++++++++++++++++++ + drivers/watchdog/bcm47xx_wdt.c | 11 +++++ + 9 files changed, 190 insertions(+), 2 deletions(-) + +--- a/arch/mips/bcm47xx/Kconfig ++++ b/arch/mips/bcm47xx/Kconfig +@@ -15,4 +15,17 @@ config BCM47XX_SSB + + This will generate an image with support for SSB and MIPS32 R2 instruction set. + ++config BCM47XX_BCMA ++ bool "SSB Support for Broadcom BCM47XX" ++ select SYS_HAS_CPU_MIPS32_R2 ++ select BCMA ++ select BCMA_HOST_SOC ++ select BCMA_DRIVER_MIPS ++ select BCMA_DRIVER_PCI_HOSTMODE if PCI ++ default y ++ help ++ Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus. ++ ++ This will generate an image with support for BCMA and MIPS32 R2 instruction set. ++ + endif +--- a/arch/mips/bcm47xx/gpio.c ++++ b/arch/mips/bcm47xx/gpio.c +@@ -36,6 +36,16 @@ int gpio_request(unsigned gpio, const ch + + return 0; + #endif ++#ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++ if ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES) ++ return -EINVAL; ++ ++ if (test_and_set_bit(gpio, gpio_in_use)) ++ return -EBUSY; ++ ++ return 0; ++#endif + } + return -EINVAL; + } +@@ -57,6 +67,14 @@ void gpio_free(unsigned gpio) + clear_bit(gpio, gpio_in_use); + return; + #endif ++#ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++ if ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES) ++ return; ++ ++ clear_bit(gpio, gpio_in_use); ++ return; ++#endif + } + } + EXPORT_SYMBOL(gpio_free); +@@ -73,6 +91,10 @@ int gpio_to_irq(unsigned gpio) + else + return -EINVAL; + #endif ++#ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++ return bcma_core_mips_irq(bcm47xx_bus.bcma.bus.drv_cc.core) + 2; ++#endif + } + return -EINVAL; + } +--- a/arch/mips/bcm47xx/nvram.c ++++ b/arch/mips/bcm47xx/nvram.c +@@ -29,6 +29,9 @@ static void early_nvram_init(void) + #ifdef CONFIG_BCM47XX_SSB + struct ssb_mipscore *mcore_ssb; + #endif ++#ifdef CONFIG_BCM47XX_BCMA ++ struct bcma_drv_mips *mcore_bcma; ++#endif + struct nvram_header *header; + int i; + u32 base = 0; +@@ -44,6 +47,13 @@ static void early_nvram_init(void) + lim = mcore_ssb->flash_window_size; + break; + #endif ++#ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++ mcore_bcma = &bcm47xx_bus.bcma.bus.drv_mips; ++ base = mcore_bcma->flash_window; ++ lim = mcore_bcma->flash_window_size; ++ break; ++#endif + } + + off = FLASH_MIN; +--- a/arch/mips/bcm47xx/serial.c ++++ b/arch/mips/bcm47xx/serial.c +@@ -47,6 +47,31 @@ static int __init uart8250_init_ssb(void + } + #endif + ++#ifdef CONFIG_BCM47XX_BCMA ++static int __init uart8250_init_bcma(void) ++{ ++ int i; ++ struct bcma_drv_mips *mcore = &(bcm47xx_bus.bcma.bus.drv_mips); ++ ++ memset(&uart8250_data, 0, sizeof(uart8250_data)); ++ ++ for (i = 0; i < mcore->nr_serial_ports; i++) { ++ struct plat_serial8250_port *p = &(uart8250_data[i]); ++ struct bcma_drv_mips_serial_port *bcma_port; ++ bcma_port = &(mcore->serial_ports[i]); ++ ++ p->mapbase = (unsigned int) bcma_port->regs; ++ p->membase = (void *) bcma_port->regs; ++ p->irq = bcma_port->irq + 2; ++ p->uartclk = bcma_port->baud_base; ++ p->regshift = bcma_port->reg_shift; ++ p->iotype = UPIO_MEM; ++ p->flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; ++ } ++ return platform_device_register(&uart8250_device); ++} ++#endif ++ + static int __init uart8250_init(void) + { + switch (bcm47xx_active_bus_type) { +@@ -54,6 +79,10 @@ static int __init uart8250_init(void) + case BCM47XX_BUS_TYPE_SSB: + return uart8250_init_ssb(); + #endif ++#ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++ return uart8250_init_bcma(); ++#endif + } + return -EINVAL; + } +--- a/arch/mips/bcm47xx/setup.c ++++ b/arch/mips/bcm47xx/setup.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -52,6 +53,11 @@ static void bcm47xx_machine_restart(char + ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1); + break; + #endif ++#ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++ bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 1); ++ break; ++#endif + } + while (1) + cpu_relax(); +@@ -67,6 +73,11 @@ static void bcm47xx_machine_halt(void) + ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0); + break; + #endif ++#ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++ bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 0); ++ break; ++#endif + } + while (1) + cpu_relax(); +@@ -295,16 +306,54 @@ static void __init bcm47xx_register_ssb( + } + #endif + ++#ifdef CONFIG_BCM47XX_BCMA ++static void __init bcm47xx_register_bcma(void) ++{ ++ int err; ++ ++ err = bcma_host_soc_register(&bcm47xx_bus.bcma); ++ if (err) ++ panic("Failed to initialize BCMA bus (err %d)\n", err); ++} ++#endif ++ + void __init plat_mem_setup(void) + { + struct cpuinfo_mips *c = ¤t_cpu_data; + ++ 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_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_register_ssb(); ++ bcm47xx_active_bus_type = BCM47XX_BUS_TYPE_SSB; ++ bcm47xx_register_ssb(); + #endif ++ } + + _machine_restart = bcm47xx_machine_restart; + _machine_halt = bcm47xx_machine_halt; + pm_power_off = bcm47xx_machine_halt; + } ++ ++static int __init bcm47xx_register_bus_complete(void) ++{ ++ switch (bcm47xx_active_bus_type) { ++#ifdef CONFIG_BCM47XX_SSB ++ case BCM47XX_BUS_TYPE_SSB: ++ /* Nothing to do */ ++ break; ++#endif ++#ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++ bcma_bus_register(&bcm47xx_bus.bcma.bus); ++ break; ++#endif ++ } ++ return 0; ++} ++device_initcall(bcm47xx_register_bus_complete); +--- a/arch/mips/bcm47xx/time.c ++++ b/arch/mips/bcm47xx/time.c +@@ -45,6 +45,11 @@ void __init plat_time_init(void) + hz = ssb_cpu_clock(&bcm47xx_bus.ssb.mipscore) / 2; + break; + #endif ++#ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++ hz = bcma_cpu_clock(&bcm47xx_bus.bcma.bus.drv_mips) / 2; ++ break; ++#endif + } + + if (!hz) +--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h ++++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx.h +@@ -20,17 +20,25 @@ + #define __ASM_BCM47XX_H + + #include ++#include ++#include + + enum bcm47xx_bus_type { + #ifdef CONFIG_BCM47XX_SSB + BCM47XX_BUS_TYPE_SSB, + #endif ++#ifdef CONFIG_BCM47XX_BCMA ++ BCM47XX_BUS_TYPE_BCMA, ++#endif + }; + + union bcm47xx_bus { + #ifdef CONFIG_BCM47XX_SSB + struct ssb_bus ssb; + #endif ++#ifdef CONFIG_BCM47XX_BCMA ++ struct bcma_soc bcma; ++#endif + }; + + extern union bcm47xx_bus bcm47xx_bus; +--- a/arch/mips/include/asm/mach-bcm47xx/gpio.h ++++ b/arch/mips/include/asm/mach-bcm47xx/gpio.h +@@ -10,6 +10,7 @@ + #define __BCM47XX_GPIO_H + + #include ++#include + #include + + #define BCM47XX_EXTIF_GPIO_LINES 5 +@@ -26,6 +27,11 @@ static inline int gpio_get_value(unsigne + case BCM47XX_BUS_TYPE_SSB: + return ssb_gpio_in(&bcm47xx_bus.ssb, 1 << gpio); + #endif ++#ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++ return bcma_chipco_gpio_in(&bcm47xx_bus.bcma.bus.drv_cc, ++ 1 << gpio); ++#endif + } + return -EINVAL; + } +@@ -37,6 +43,13 @@ static inline void gpio_set_value(unsign + case BCM47XX_BUS_TYPE_SSB: + ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio, + value ? 1 << gpio : 0); ++ return; ++#endif ++#ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++ bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio, ++ value ? 1 << gpio : 0); ++ return; + #endif + } + } +@@ -49,6 +62,12 @@ static inline int gpio_direction_input(u + ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 0); + return 0; + #endif ++#ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++ bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio, ++ 0); ++ return 0; ++#endif + } + return -EINVAL; + } +@@ -65,6 +84,16 @@ static inline int gpio_direction_output( + ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 1 << gpio); + return 0; + #endif ++#ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++ /* first set the gpio out value */ ++ bcma_chipco_gpio_out(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio, ++ value ? 1 << gpio : 0); ++ /* then set the gpio mode */ ++ bcma_chipco_gpio_outen(&bcm47xx_bus.bcma.bus.drv_cc, 1 << gpio, ++ 1 << gpio); ++ return 0; ++#endif + } + return -EINVAL; + } +@@ -78,6 +107,12 @@ static inline int gpio_intmask(unsigned + value ? 1 << gpio : 0); + return 0; + #endif ++#ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++ bcma_chipco_gpio_intmask(&bcm47xx_bus.bcma.bus.drv_cc, ++ 1 << gpio, value ? 1 << gpio : 0); ++ return 0; ++#endif + } + return -EINVAL; + } +@@ -91,6 +126,12 @@ static inline int gpio_polarity(unsigned + value ? 1 << gpio : 0); + return 0; + #endif ++#ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++ bcma_chipco_gpio_polarity(&bcm47xx_bus.bcma.bus.drv_cc, ++ 1 << gpio, value ? 1 << gpio : 0); ++ return 0; ++#endif + } + return -EINVAL; + } +--- a/drivers/watchdog/bcm47xx_wdt.c ++++ b/drivers/watchdog/bcm47xx_wdt.c +@@ -60,6 +60,12 @@ static inline void bcm47xx_wdt_hw_start( + ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0xfffffff); + break; + #endif ++#ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++ bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, ++ 0xfffffff); ++ break; ++#endif + } + } + +@@ -70,6 +76,11 @@ static inline int bcm47xx_wdt_hw_stop(vo + case BCM47XX_BUS_TYPE_SSB: + return ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0); + #endif ++#ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++ bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 0); ++ return 0; ++#endif + } + return -EINVAL; + } diff --git a/target/linux/brcm47xx/patches-3.0/0013-bcm47xx-fix-irq-assignment-for-new-SoCs.patch b/target/linux/brcm47xx/patches-3.0/0013-bcm47xx-fix-irq-assignment-for-new-SoCs.patch new file mode 100644 index 000000000..a40e72695 --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/0013-bcm47xx-fix-irq-assignment-for-new-SoCs.patch @@ -0,0 +1,37 @@ +From 360eb82fd303ac24590a1b99ad1866162f6b0171 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Mon, 6 Jun 2011 00:07:38 +0200 +Subject: [PATCH 13/14] bcm47xx: fix irq assignment for new SoCs. + +Signed-off-by: Hauke Mehrtens +--- + arch/mips/bcm47xx/irq.c | 12 ++++++++++++ + 1 files changed, 12 insertions(+), 0 deletions(-) + +--- a/arch/mips/bcm47xx/irq.c ++++ b/arch/mips/bcm47xx/irq.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + void plat_irq_dispatch(void) + { +@@ -51,5 +52,16 @@ void plat_irq_dispatch(void) + + void __init arch_init_irq(void) + { ++#ifdef CONFIG_BCM47XX_BCMA ++ if (bcm47xx_active_bus_type == BCM47XX_BUS_TYPE_BCMA) { ++ bcma_write32(bcm47xx_bus.bcma.bus.drv_mips.core, ++ BCMA_MIPS_MIPS74K_INTMASK(5), 1 << 31); ++ /* ++ * the kernel reads the timer irq from some register and thinks ++ * it's #5, but we offset it by 2 and route to #7 ++ */ ++ cp0_compare_irq = 7; ++ } ++#endif + mips_cpu_irq_init(); + } diff --git a/target/linux/brcm47xx/patches-3.0/014-MIPS-BCM47xx-Setup-and-register-serial-early.patch b/target/linux/brcm47xx/patches-3.0/014-MIPS-BCM47xx-Setup-and-register-serial-early.patch index 419a4f6f1..824dd09c0 100644 --- a/target/linux/brcm47xx/patches-3.0/014-MIPS-BCM47xx-Setup-and-register-serial-early.patch +++ b/target/linux/brcm47xx/patches-3.0/014-MIPS-BCM47xx-Setup-and-register-serial-early.patch @@ -15,16 +15,16 @@ Signed-off-by: Hauke Mehrtens --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c -@@ -29,6 +29,8 @@ - #include +@@ -30,6 +30,8 @@ #include #include + #include +#include +#include #include #include #include -@@ -247,6 +249,31 @@ static int bcm47xx_get_invariants(struct +@@ -274,6 +276,31 @@ static int bcm47xx_get_invariants(struct return 0; } @@ -53,17 +53,17 @@ Signed-off-by: Hauke Mehrtens +} +#endif + - void __init plat_mem_setup(void) + static void __init bcm47xx_register_ssb(void) { int err; -@@ -277,6 +304,10 @@ void __init plat_mem_setup(void) +@@ -303,6 +330,10 @@ static void __init bcm47xx_register_ssb( + memcpy(&mcore->serial_ports[1], &port, sizeof(port)); } } - ++ +#ifdef CONFIG_SERIAL_8250 + bcm47xx_early_serial_setup(mcore); +#endif -+ - _machine_restart = bcm47xx_machine_restart; - _machine_halt = bcm47xx_machine_halt; - pm_power_off = bcm47xx_machine_halt; + } + #endif + diff --git a/target/linux/brcm47xx/patches-3.0/016-MIPS-BCM47xx-Remove-CFE-console.patch b/target/linux/brcm47xx/patches-3.0/016-MIPS-BCM47xx-Remove-CFE-console.patch index 2b34ec5c0..69d4eefa8 100644 --- a/target/linux/brcm47xx/patches-3.0/016-MIPS-BCM47xx-Remove-CFE-console.patch +++ b/target/linux/brcm47xx/patches-3.0/016-MIPS-BCM47xx-Remove-CFE-console.patch @@ -16,9 +16,9 @@ Signed-off-by: Hauke Mehrtens --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -101,7 +101,6 @@ config BCM47XX - select SSB_B43_PCI_BRIDGE if PCI - select SSB_PCICORE_HOSTMODE if PCI +@@ -94,7 +94,6 @@ config BCM47XX + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN select GENERIC_GPIO - select SYS_HAS_EARLY_PRINTK select CFE diff --git a/target/linux/brcm47xx/patches-3.0/040-bcm47xx-add-gpio_set_debounce.patch b/target/linux/brcm47xx/patches-3.0/040-bcm47xx-add-gpio_set_debounce.patch index 32593908d..2bc7718c3 100644 --- a/target/linux/brcm47xx/patches-3.0/040-bcm47xx-add-gpio_set_debounce.patch +++ b/target/linux/brcm47xx/patches-3.0/040-bcm47xx-add-gpio_set_debounce.patch @@ -1,7 +1,7 @@ --- a/arch/mips/include/asm/mach-bcm47xx/gpio.h +++ b/arch/mips/include/asm/mach-bcm47xx/gpio.h -@@ -58,6 +58,10 @@ static inline int gpio_polarity(unsigned - return 0; +@@ -136,6 +136,10 @@ static inline int gpio_polarity(unsigned + return -EINVAL; } +static inline int gpio_set_debounce(unsigned gpio, unsigned debounce) diff --git a/target/linux/brcm47xx/patches-3.0/250-bcma-flash.patch b/target/linux/brcm47xx/patches-3.0/250-bcma-flash.patch new file mode 100644 index 000000000..2b2f01106 --- /dev/null +++ b/target/linux/brcm47xx/patches-3.0/250-bcma-flash.patch @@ -0,0 +1,78 @@ +--- a/drivers/mtd/maps/bcm47xx-flash.c ++++ b/drivers/mtd/maps/bcm47xx-flash.c +@@ -46,11 +46,9 @@ + #include + #include + #include +-#ifdef CONFIG_SSB +-#include +-#endif + #include + #include ++#include + #include + + +@@ -90,9 +88,6 @@ struct trx_header { + #define ROUTER_NETGEAR_WNR3500L 4 + #define ROUTER_SIMPLETECH_SIMPLESHARE 5 + +-#ifdef CONFIG_SSB +-extern struct ssb_bus ssb_bcm47xx; +-#endif + static struct mtd_info *bcm47xx_mtd; + + static void bcm47xx_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +@@ -552,27 +547,42 @@ init_mtd_partitions(struct mtd_info *mtd + + int __init init_bcm47xx_map(void) + { +-#ifdef CONFIG_SSB +- struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore; ++#ifdef CONFIG_BCM47XX_SSB ++ struct ssb_mipscore *mcore_ssb; ++#endif ++#ifdef CONFIG_BCM47XX_BCMA ++ struct bcma_drv_mips *mcore_bcma; + #endif + size_t size; + int ret = 0; ++ u32 window = 0; ++ u32 window_size = 0; + struct mtd_partition *parts; + int i; + +-#ifdef CONFIG_SSB +- u32 window = mcore->flash_window; +- u32 window_size = mcore->flash_window_size; ++ switch (bcm47xx_active_bus_type) { ++#ifdef CONFIG_BCM47XX_SSB ++ case BCM47XX_BUS_TYPE_SSB: ++ mcore_ssb = &bcm47xx_bus.ssb.mipscore; ++ window = mcore_ssb->flash_window; ++ window_size = mcore_ssb->flash_window_size; ++ bcm47xx_map.bankwidth = mcore_ssb->flash_buswidth; ++ break; ++#endif ++#ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++ mcore_bcma = &bcm47xx_bus.bcma.bus.drv_mips; ++ window = mcore_bcma->flash_window; ++ window_size = mcore_bcma->flash_window_size; ++ bcm47xx_map.bankwidth = mcore_bcma->flash_buswidth; ++ break; ++#endif ++ } + + printk("flash init: 0x%08x 0x%08x\n", window, window_size); + bcm47xx_map.phys = window; + bcm47xx_map.size = window_size; +- bcm47xx_map.bankwidth = mcore->flash_buswidth; + bcm47xx_map.virt = ioremap_nocache(window, window_size); +-#else +- printk("flash init: 0x%08x 0x%08x\n", WINDOW_ADDR, WINDOW_SIZE); +- bcm47xx_map.virt = ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE); +-#endif + + if (!bcm47xx_map.virt) { + printk("Failed to ioremap\n"); diff --git a/target/linux/brcm47xx/patches-3.0/400-arch-bcm47xx.patch b/target/linux/brcm47xx/patches-3.0/400-arch-bcm47xx.patch index 14b408842..8e5e88b6b 100644 --- a/target/linux/brcm47xx/patches-3.0/400-arch-bcm47xx.patch +++ b/target/linux/brcm47xx/patches-3.0/400-arch-bcm47xx.patch @@ -1,6 +1,6 @@ --- a/arch/mips/bcm47xx/nvram.c +++ b/arch/mips/bcm47xx/nvram.c -@@ -93,3 +93,30 @@ int nvram_getenv(char *name, char *val, +@@ -114,3 +114,30 @@ int nvram_getenv(char *name, char *val, return NVRAM_ERR_ENVNOTFOUND; } EXPORT_SYMBOL(nvram_getenv); @@ -33,10 +33,10 @@ +EXPORT_SYMBOL(nvram_get); --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c -@@ -312,3 +312,20 @@ void __init plat_mem_setup(void) - _machine_halt = bcm47xx_machine_halt; - pm_power_off = bcm47xx_machine_halt; +@@ -388,3 +388,20 @@ static int __init bcm47xx_register_bus_c + return 0; } + device_initcall(bcm47xx_register_bus_complete); + +static int __init bcm47xx_register_gpiodev(void) +{ diff --git a/target/linux/brcm47xx/patches-3.0/812-disable_wgt634u_crap.patch b/target/linux/brcm47xx/patches-3.0/812-disable_wgt634u_crap.patch index a0331399d..a1a9055e7 100644 --- a/target/linux/brcm47xx/patches-3.0/812-disable_wgt634u_crap.patch +++ b/target/linux/brcm47xx/patches-3.0/812-disable_wgt634u_crap.patch @@ -1,14 +1,13 @@ --- a/arch/mips/bcm47xx/Makefile +++ b/arch/mips/bcm47xx/Makefile -@@ -3,4 +3,4 @@ - # under Linux. +@@ -4,4 +4,3 @@ # --obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o -+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 +-obj-$(CONFIG_BCM47XX_SSB) += wgt634u.o --- a/arch/mips/bcm47xx/wgt634u.c +++ /dev/null -@@ -1,166 +0,0 @@ +@@ -1,169 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive @@ -119,7 +118,7 @@ - - /* Interrupts are shared, check if the current one is - a GPIO interrupt. */ -- if (!ssb_chipco_irq_status(&ssb_bcm47xx.chipco, +- if (!ssb_chipco_irq_status(&bcm47xx_bus.ssb.chipco, - SSB_CHIPCO_IRQ_GPIO)) - return IRQ_NONE; - @@ -144,21 +143,24 @@ - * been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx. - */ - -- u8 *et0mac = ssb_bcm47xx.sprom.et0mac; +- if (bcm47xx_active_bus_type != BCM47XX_BUS_TYPE_SSB) +- return -ENODEV; +- +- u8 *et0mac = bcm47xx_bus.ssb.sprom.et0mac; - - if (et0mac[0] == 0x00 && - ((et0mac[1] == 0x09 && et0mac[2] == 0x5b) || - (et0mac[1] == 0x0f && et0mac[2] == 0xb5))) { -- struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore; +- struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore; - - printk(KERN_INFO "WGT634U machine detected.\n"); - - if (!request_irq(gpio_to_irq(WGT634U_GPIO_RESET), - gpio_interrupt, IRQF_SHARED, -- "WGT634U GPIO", &ssb_bcm47xx.chipco)) { +- "WGT634U GPIO", &bcm47xx_bus.ssb.chipco)) { - gpio_direction_input(WGT634U_GPIO_RESET); - gpio_intmask(WGT634U_GPIO_RESET, 1); -- ssb_chipco_irq_mask(&ssb_bcm47xx.chipco, +- ssb_chipco_irq_mask(&bcm47xx_bus.ssb.chipco, - SSB_CHIPCO_IRQ_GPIO, - SSB_CHIPCO_IRQ_GPIO); - } diff --git a/target/linux/brcm47xx/patches-3.0/820-wgt634u-nvram-fix.patch b/target/linux/brcm47xx/patches-3.0/820-wgt634u-nvram-fix.patch index e1bf69f8c..301c9a421 100644 --- a/target/linux/brcm47xx/patches-3.0/820-wgt634u-nvram-fix.patch +++ b/target/linux/brcm47xx/patches-3.0/820-wgt634u-nvram-fix.patch @@ -9,8 +9,8 @@ out the configuration than the in kernel cfe config reader. # under Linux. # --obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o -+obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o cfe_env.o +-obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o ++obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o cfe_env.o --- /dev/null +++ b/arch/mips/bcm47xx/cfe_env.c @@ -0,0 +1,229 @@ @@ -254,10 +254,10 @@ out the configuration than the in kernel cfe config reader. /* Probe for NVRAM header */ static void early_nvram_init(void) -@@ -34,6 +36,25 @@ static void early_nvram_init(void) - - base = mcore->flash_window; - lim = mcore->flash_window_size; +@@ -55,6 +57,25 @@ static void early_nvram_init(void) + break; + #endif + } + cfe_env = 0; + + /* XXX: hack for supporting the CFE environment stuff on WGT634U */ @@ -280,7 +280,7 @@ out the configuration than the in kernel cfe config reader. off = FLASH_MIN; while (off <= lim) { -@@ -75,6 +96,12 @@ int nvram_getenv(char *name, char *val, +@@ -96,6 +117,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; -@@ -104,6 +131,9 @@ char *nvram_get(const char *name) +@@ -125,6 +152,9 @@ char *nvram_get(const char *name) if (!nvram_buf[0]) early_nvram_init(); diff --git a/target/linux/brcm47xx/patches-3.0/900-bcm47xx_wdt-noprescale.patch b/target/linux/brcm47xx/patches-3.0/900-bcm47xx_wdt-noprescale.patch index 6bc2b12eb..d259dcf16 100644 --- a/target/linux/brcm47xx/patches-3.0/900-bcm47xx_wdt-noprescale.patch +++ b/target/linux/brcm47xx/patches-3.0/900-bcm47xx_wdt-noprescale.patch @@ -8,7 +8,7 @@ static int wdt_time = WDT_DEFAULT_TIME; static int nowayout = WATCHDOG_NOWAYOUT; -@@ -50,11 +51,11 @@ static unsigned long bcm47xx_wdt_busy; +@@ -50,20 +51,20 @@ static unsigned long bcm47xx_wdt_busy; static char expect_release; static struct timer_list wdt_timer; static atomic_t ticks; @@ -18,12 +18,22 @@ +static inline void bcm47xx_wdt_hw_start(u32 ticks) { - /* this is 2,5s on 100Mhz clock and 2s on 133 Mhz */ -- ssb_watchdog_timer_set(&ssb_bcm47xx, 0xfffffff); -+ ssb_watchdog_timer_set(&ssb_bcm47xx, ticks); - } - - static inline int bcm47xx_wdt_hw_stop(void) -@@ -65,33 +66,34 @@ static inline int bcm47xx_wdt_hw_stop(vo + switch (bcm47xx_active_bus_type) { + #ifdef CONFIG_BCM47XX_SSB + case BCM47XX_BUS_TYPE_SSB: +- ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0xfffffff); ++ ssb_watchdog_timer_set(&bcm47xx_bus.ssb, ticks); + break; + #endif + #ifdef CONFIG_BCM47XX_BCMA + case BCM47XX_BUS_TYPE_BCMA: + bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, +- 0xfffffff); ++ ticks); + break; + #endif + } +@@ -88,33 +89,34 @@ static inline int bcm47xx_wdt_hw_stop(vo static void bcm47xx_timer_tick(unsigned long unused) { if (!atomic_dec_and_test(&ticks)) { @@ -70,20 +80,25 @@ } static int bcm47xx_wdt_settimeout(int new_time) -@@ -243,7 +245,15 @@ static int __init bcm47xx_wdt_init(void) +@@ -266,7 +268,20 @@ static int __init bcm47xx_wdt_init(void) if (bcm47xx_wdt_hw_stop() < 0) return -ENODEV; - setup_timer(&wdt_timer, bcm47xx_timer_tick, 0L); + /* FIXME Other cores */ -+ if(ssb_bcm47xx.chip_id == 0x5354) { ++#ifdef BCM47XX_BUS_TYPE_BCMA ++ if(bcm47xx_active_bus_type == BCM47XX_BUS_TYPE_BCMA && ++ bcm47xx_bus.ssb.chip_id == 0x5354) { + /* Slow WDT clock, no pre-scaling */ + needs_sw_scale = 0; + } else { ++#endif + /* Fast WDT clock, needs software pre-scaling */ + needs_sw_scale = 1; + setup_timer(&wdt_timer, bcm47xx_timer_tick, 0L); ++#ifdef BCM47XX_BUS_TYPE_BCMA + } ++#endif if (bcm47xx_wdt_settimeout(wdt_time)) { bcm47xx_wdt_settimeout(WDT_DEFAULT_TIME); diff --git a/target/linux/brcm47xx/patches-3.0/980-wnr834b_no_cardbus_invariant.patch b/target/linux/brcm47xx/patches-3.0/980-wnr834b_no_cardbus_invariant.patch index 518e63401..09415038a 100644 --- a/target/linux/brcm47xx/patches-3.0/980-wnr834b_no_cardbus_invariant.patch +++ b/target/linux/brcm47xx/patches-3.0/980-wnr834b_no_cardbus_invariant.patch @@ -1,6 +1,6 @@ --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c -@@ -246,6 +246,10 @@ static int bcm47xx_get_invariants(struct +@@ -273,6 +273,10 @@ static int bcm47xx_get_invariants(struct if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0) iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);