From: Rafał Miłecki Date: Wed, 11 Feb 2015 10:04:51 +0000 (+0000) Subject: kernel: backport bcma patches queued for 3.20 X-Git-Tag: v19.07.0-rc1~14974 X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=ddcbef5766fa18f52e7a7d1928b25edc63e73937;p=openwrt%2Fstaging%2Fhauke.git kernel: backport bcma patches queued for 3.20 Signed-off-by: Rafał Miłecki SVN-Revision: 44385 --- diff --git a/target/linux/bcm53xx/patches-3.14/800-bcma-use-two-different-initcalls-if-built-in.patch b/target/linux/bcm53xx/patches-3.14/800-bcma-use-two-different-initcalls-if-built-in.patch index 9d229a4c33..6ae555b4dc 100644 --- a/target/linux/bcm53xx/patches-3.14/800-bcma-use-two-different-initcalls-if-built-in.patch +++ b/target/linux/bcm53xx/patches-3.14/800-bcma-use-two-different-initcalls-if-built-in.patch @@ -29,7 +29,7 @@ diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 9635f10..c394207 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c -@@ -639,13 +639,25 @@ static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env) +@@ -637,13 +637,25 @@ static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env) core->id.rev, core->id.class); } @@ -56,7 +56,7 @@ index 9635f10..c394207 100644 err = bcma_host_soc_register_driver(); if (err) { -@@ -662,7 +674,7 @@ static int __init bcma_modinit(void) +@@ -660,7 +672,7 @@ static int __init bcma_modinit(void) return err; } diff --git a/target/linux/bcm53xx/patches-3.18/800-bcma-use-two-different-initcalls-if-built-in.patch b/target/linux/bcm53xx/patches-3.18/800-bcma-use-two-different-initcalls-if-built-in.patch index 9d229a4c33..6ae555b4dc 100644 --- a/target/linux/bcm53xx/patches-3.18/800-bcma-use-two-different-initcalls-if-built-in.patch +++ b/target/linux/bcm53xx/patches-3.18/800-bcma-use-two-different-initcalls-if-built-in.patch @@ -29,7 +29,7 @@ diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 9635f10..c394207 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c -@@ -639,13 +639,25 @@ static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env) +@@ -637,13 +637,25 @@ static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env) core->id.rev, core->id.class); } @@ -56,7 +56,7 @@ index 9635f10..c394207 100644 err = bcma_host_soc_register_driver(); if (err) { -@@ -662,7 +674,7 @@ static int __init bcma_modinit(void) +@@ -660,7 +672,7 @@ static int __init bcma_modinit(void) return err; } diff --git a/target/linux/generic/patches-3.14/026-bcma-from-3.20.patch b/target/linux/generic/patches-3.14/026-bcma-from-3.20.patch new file mode 100644 index 0000000000..17c06b001f --- /dev/null +++ b/target/linux/generic/patches-3.14/026-bcma-from-3.20.patch @@ -0,0 +1,527 @@ +--- a/drivers/bcma/bcma_private.h ++++ b/drivers/bcma/bcma_private.h +@@ -25,22 +25,18 @@ struct bcma_bus; + bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value, + int timeout); + void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core); ++void bcma_init_bus(struct bcma_bus *bus); + 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); ++int __init bcma_bus_early_register(struct bcma_bus *bus); + #ifdef CONFIG_PM + int bcma_bus_suspend(struct bcma_bus *bus); + int bcma_bus_resume(struct bcma_bus *bus); + #endif + + /* scan.c */ ++void bcma_detect_chip(struct bcma_bus *bus); + 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); +@@ -111,6 +107,14 @@ extern int bcma_chipco_watchdog_register + #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE + bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc); + void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); ++#else ++static inline bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) ++{ ++ return false; ++} ++static inline void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) ++{ ++} + #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ + + #ifdef CONFIG_BCMA_DRIVER_GPIO +--- a/drivers/bcma/driver_chipcommon.c ++++ b/drivers/bcma/driver_chipcommon.c +@@ -79,7 +79,9 @@ static int bcma_chipco_watchdog_ticks_pe + + if (cc->capabilities & BCMA_CC_CAP_PMU) { + if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) +- /* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP clock */ ++ /* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP ++ * clock ++ */ + return bcma_chipco_get_alp_clock(cc) / 4000; + else + /* based on 32KHz ILP clock */ +@@ -97,7 +99,8 @@ int bcma_chipco_watchdog_register(struct + wdt.driver_data = cc; + wdt.timer_set = bcma_chipco_watchdog_timer_set_wdt; + wdt.timer_set_ms = bcma_chipco_watchdog_timer_set_ms_wdt; +- wdt.max_timer_ms = bcma_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms; ++ wdt.max_timer_ms = ++ bcma_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms; + + pdev = platform_device_register_data(NULL, "bcm47xx-wdt", + cc->core->bus->num, &wdt, +@@ -175,7 +178,6 @@ void bcma_core_chipcommon_init(struct bc + u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks) + { + u32 maxt; +- enum bcma_clkmode clkmode; + + maxt = bcma_chipco_watchdog_get_max_timer(cc); + if (cc->capabilities & BCMA_CC_CAP_PMU) { +@@ -185,8 +187,13 @@ u32 bcma_chipco_watchdog_timer_set(struc + ticks = maxt; + bcma_cc_write32(cc, BCMA_CC_PMU_WATCHDOG, ticks); + } else { +- clkmode = ticks ? BCMA_CLKMODE_FAST : BCMA_CLKMODE_DYNAMIC; +- bcma_core_set_clockmode(cc->core, clkmode); ++ struct bcma_bus *bus = cc->core->bus; ++ ++ if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4707 && ++ bus->chipinfo.id != BCMA_CHIP_ID_BCM53018) ++ bcma_core_set_clockmode(cc->core, ++ ticks ? BCMA_CLKMODE_FAST : BCMA_CLKMODE_DYNAMIC); ++ + if (ticks > maxt) + ticks = maxt; + /* instant NMI */ +@@ -335,7 +342,8 @@ void bcma_chipco_serial_init(struct bcma + | BCMA_CC_CORECTL_UARTCLKEN); + } + } else { +- bcma_err(cc->core->bus, "serial not supported on this device ccrev: 0x%x\n", ccrev); ++ bcma_err(cc->core->bus, "serial not supported on this device ccrev: 0x%x\n", ++ ccrev); + return; + } + +--- a/drivers/bcma/driver_pci.c ++++ b/drivers/bcma/driver_pci.c +@@ -145,6 +145,47 @@ static u16 bcma_pcie_mdio_writeread(stru + } + + /************************************************** ++ * Early init. ++ **************************************************/ ++ ++static void bcma_core_pci_fixcfg(struct bcma_drv_pci *pc) ++{ ++ struct bcma_device *core = pc->core; ++ u16 val16, core_index; ++ uint regoff; ++ ++ regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_PI_OFFSET); ++ core_index = (u16)core->core_index; ++ ++ val16 = pcicore_read16(pc, regoff); ++ if (((val16 & BCMA_CORE_PCI_SPROM_PI_MASK) >> BCMA_CORE_PCI_SPROM_PI_SHIFT) ++ != core_index) { ++ val16 = (core_index << BCMA_CORE_PCI_SPROM_PI_SHIFT) | ++ (val16 & ~BCMA_CORE_PCI_SPROM_PI_MASK); ++ pcicore_write16(pc, regoff, val16); ++ } ++} ++ ++/* ++ * Apply some early fixes required before accessing SPROM. ++ * See also si_pci_fixcfg. ++ */ ++void bcma_core_pci_early_init(struct bcma_drv_pci *pc) ++{ ++ if (pc->early_setup_done) ++ return; ++ ++ pc->hostmode = bcma_core_pci_is_in_hostmode(pc); ++ if (pc->hostmode) ++ goto out; ++ ++ bcma_core_pci_fixcfg(pc); ++ ++out: ++ pc->early_setup_done = true; ++} ++ ++/************************************************** + * Workarounds. + **************************************************/ + +@@ -175,24 +216,6 @@ static void bcma_pcicore_serdes_workarou + tmp & ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN); + } + +-static void bcma_core_pci_fixcfg(struct bcma_drv_pci *pc) +-{ +- struct bcma_device *core = pc->core; +- u16 val16, core_index; +- uint regoff; +- +- regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_PI_OFFSET); +- core_index = (u16)core->core_index; +- +- val16 = pcicore_read16(pc, regoff); +- if (((val16 & BCMA_CORE_PCI_SPROM_PI_MASK) >> BCMA_CORE_PCI_SPROM_PI_SHIFT) +- != core_index) { +- val16 = (core_index << BCMA_CORE_PCI_SPROM_PI_SHIFT) | +- (val16 & ~BCMA_CORE_PCI_SPROM_PI_MASK); +- pcicore_write16(pc, regoff, val16); +- } +-} +- + /* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */ + /* Needs to happen when coming out of 'standby'/'hibernate' */ + static void bcma_core_pci_config_fixup(struct bcma_drv_pci *pc) +@@ -216,7 +239,6 @@ static void bcma_core_pci_config_fixup(s + + static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc) + { +- bcma_core_pci_fixcfg(pc); + bcma_pcicore_serdes_workaround(pc); + bcma_core_pci_config_fixup(pc); + } +@@ -226,13 +248,11 @@ void bcma_core_pci_init(struct bcma_drv_ + if (pc->setup_done) + return; + +-#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE +- pc->hostmode = bcma_core_pci_is_in_hostmode(pc); ++ bcma_core_pci_early_init(pc); ++ + if (pc->hostmode) + bcma_core_pci_hostmode_init(pc); +-#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ +- +- if (!pc->hostmode) ++ else + bcma_core_pci_clientmode_init(pc); + } + +--- a/drivers/bcma/host_pci.c ++++ b/drivers/bcma/host_pci.c +@@ -13,10 +13,12 @@ + + static void bcma_host_pci_switch_core(struct bcma_device *core) + { ++ int win2 = core->bus->host_is_pcie2 ? ++ BCMA_PCIE2_BAR0_WIN2 : BCMA_PCI_BAR0_WIN2; ++ + pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN, + core->addr); +- pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN2, +- core->wrap); ++ pci_write_config_dword(core->bus->host_pci, win2, core->wrap); + core->bus->mapped_core = core; + bcma_debug(core->bus, "Switched to core: 0x%X\n", core->id.id); + } +--- a/drivers/bcma/host_soc.c ++++ b/drivers/bcma/host_soc.c +@@ -193,7 +193,7 @@ int __init bcma_host_soc_init(struct bcm + int err; + + /* Scan bus and initialize it */ +- err = bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips); ++ err = bcma_bus_early_register(bus); + if (err) + iounmap(bus->mmio); + +--- a/drivers/bcma/main.c ++++ b/drivers/bcma/main.c +@@ -268,6 +268,18 @@ void bcma_prepare_core(struct bcma_bus * + } + } + ++void bcma_init_bus(struct bcma_bus *bus) ++{ ++ mutex_lock(&bcma_buses_mutex); ++ bus->num = bcma_bus_next_num++; ++ mutex_unlock(&bcma_buses_mutex); ++ ++ INIT_LIST_HEAD(&bus->cores); ++ bus->nr_cores = 0; ++ ++ bcma_detect_chip(bus); ++} ++ + static void bcma_register_core(struct bcma_bus *bus, struct bcma_device *core) + { + int err; +@@ -356,12 +368,19 @@ static void bcma_unregister_cores(struct + struct bcma_device *core, *tmp; + + list_for_each_entry_safe(core, tmp, &bus->cores, list) { ++ if (!core->dev_registered) ++ continue; + list_del(&core->list); +- if (core->dev_registered) +- device_unregister(&core->dev); ++ device_unregister(&core->dev); + } + if (bus->hosttype == BCMA_HOSTTYPE_SOC) + platform_device_unregister(bus->drv_cc.watchdog); ++ ++ /* Now noone uses internally-handled cores, we can free them */ ++ list_for_each_entry_safe(core, tmp, &bus->cores, list) { ++ list_del(&core->list); ++ kfree(core); ++ } + } + + int bcma_bus_register(struct bcma_bus *bus) +@@ -369,10 +388,6 @@ int bcma_bus_register(struct bcma_bus *b + int err; + struct bcma_device *core; + +- mutex_lock(&bcma_buses_mutex); +- bus->num = bcma_bus_next_num++; +- mutex_unlock(&bcma_buses_mutex); +- + /* Scan for devices (cores) */ + err = bcma_bus_scan(bus); + if (err) { +@@ -387,6 +402,13 @@ int bcma_bus_register(struct bcma_bus *b + bcma_core_chipcommon_early_init(&bus->drv_cc); + } + ++ /* Early init PCIE core */ ++ core = bcma_find_core(bus, BCMA_CORE_PCIE); ++ if (core) { ++ bus->drv_pci[0].core = core; ++ bcma_core_pci_early_init(&bus->drv_pci[0]); ++ } ++ + /* Cores providing flash access go before SPROM init */ + list_for_each_entry(core, &bus->cores, list) { + if (bcma_is_core_needed_early(core->id.id)) +@@ -459,7 +481,6 @@ int bcma_bus_register(struct bcma_bus *b + + void bcma_bus_unregister(struct bcma_bus *bus) + { +- struct bcma_device *cores[3]; + int err; + + err = bcma_gpio_unregister(&bus->drv_cc); +@@ -470,46 +491,23 @@ void bcma_bus_unregister(struct bcma_bus + + bcma_core_chipcommon_b_free(&bus->drv_cc_b); + +- cores[0] = bcma_find_core(bus, BCMA_CORE_MIPS_74K); +- cores[1] = bcma_find_core(bus, BCMA_CORE_PCIE); +- cores[2] = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON); +- + bcma_unregister_cores(bus); +- +- kfree(cores[2]); +- kfree(cores[1]); +- kfree(cores[0]); + } + +-int __init bcma_bus_early_register(struct bcma_bus *bus, +- struct bcma_device *core_cc, +- struct bcma_device *core_mips) ++/* ++ * This is a special version of bus registration function designed for SoCs. ++ * It scans bus and performs basic initialization of main cores only. ++ * Please note it requires memory allocation, however it won't try to sleep. ++ */ ++int __init bcma_bus_early_register(struct bcma_bus *bus) + { + int err; + struct bcma_device *core; +- struct bcma_device_id match; +- +- match.manuf = BCMA_MANUF_BCM; +- match.id = bcma_cc_core_id(bus); +- match.class = BCMA_CL_SIM; +- match.rev = BCMA_ANY_REV; + +- /* Scan for chip common core */ +- err = bcma_bus_scan_early(bus, &match, core_cc); +- if (err) { +- bcma_err(bus, "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; +- +- /* Scan for mips core */ +- err = bcma_bus_scan_early(bus, &match, core_mips); ++ /* Scan for devices (cores) */ ++ err = bcma_bus_scan(bus); + if (err) { +- bcma_err(bus, "Failed to scan for mips core: %d\n", err); ++ bcma_err(bus, "Failed to scan bus: %d\n", err); + return -1; + } + +--- a/drivers/bcma/scan.c ++++ b/drivers/bcma/scan.c +@@ -435,15 +435,12 @@ static int bcma_get_next_core(struct bcm + return 0; + } + +-void bcma_init_bus(struct bcma_bus *bus) ++void bcma_detect_chip(struct bcma_bus *bus) + { + s32 tmp; + struct bcma_chipinfo *chipinfo = &(bus->chipinfo); + char chip_id[8]; + +- INIT_LIST_HEAD(&bus->cores); +- bus->nr_cores = 0; +- + bcma_scan_switch_core(bus, BCMA_ADDR_BASE); + + tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID); +@@ -464,6 +461,10 @@ int bcma_bus_scan(struct bcma_bus *bus) + + int err, core_num = 0; + ++ /* Skip if bus was already scanned (e.g. during early register) */ ++ if (bus->nr_cores) ++ return 0; ++ + erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); + if (bus->hosttype == BCMA_HOSTTYPE_SOC) { + eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE); +@@ -519,64 +520,6 @@ int bcma_bus_scan(struct bcma_bus *bus) + out: + if (bus->hosttype == BCMA_HOSTTYPE_SOC) + iounmap(eromptr); +- +- return err; +-} +- +-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 = -ENODEV; +- int core_num = 0; +- +- erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); +- if (bus->hosttype == BCMA_HOSTTYPE_SOC) { +- eromptr = ioremap_nocache(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); +- +- 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) +- goto out; +- +- core->core_index = core_num++; +- bus->nr_cores++; +- bcma_info(bus, "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_tail(&core->list, &bus->cores); +- err = 0; +- break; +- } +- +-out: +- if (bus->hosttype == BCMA_HOSTTYPE_SOC) +- iounmap(eromptr); + + return err; + } +--- a/drivers/bcma/sprom.c ++++ b/drivers/bcma/sprom.c +@@ -579,7 +579,8 @@ int bcma_sprom_get(struct bcma_bus *bus) + u16 offset = BCMA_CC_SPROM; + u16 *sprom; + size_t sprom_sizes[] = { SSB_SPROMSIZE_WORDS_R4, +- SSB_SPROMSIZE_WORDS_R10, }; ++ SSB_SPROMSIZE_WORDS_R10, ++ SSB_SPROMSIZE_WORDS_R11, }; + int i, err = 0; + + if (!bus->drv_cc.core) +--- a/include/linux/bcma/bcma.h ++++ b/include/linux/bcma/bcma.h +@@ -318,6 +318,7 @@ struct bcma_bus { + const struct bcma_host_ops *ops; + + enum bcma_hosttype hosttype; ++ bool host_is_pcie2; /* Used for BCMA_HOSTTYPE_PCI only */ + union { + /* Pointer to the PCI bus (only for BCMA_HOSTTYPE_PCI) */ + struct pci_dev *host_pci; +--- a/include/linux/bcma/bcma_driver_pci.h ++++ b/include/linux/bcma/bcma_driver_pci.h +@@ -223,6 +223,7 @@ struct bcma_drv_pci_host { + + struct bcma_drv_pci { + struct bcma_device *core; ++ u8 early_setup_done:1; + u8 setup_done:1; + u8 hostmode:1; + +@@ -237,6 +238,7 @@ struct bcma_drv_pci { + #define pcicore_write16(pc, offset, val) bcma_write16((pc)->core, offset, val) + #define pcicore_write32(pc, offset, val) bcma_write32((pc)->core, offset, val) + ++extern void bcma_core_pci_early_init(struct bcma_drv_pci *pc); + extern void bcma_core_pci_init(struct bcma_drv_pci *pc); + extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, + struct bcma_device *core, bool enable); +--- a/include/linux/bcma/bcma_regs.h ++++ b/include/linux/bcma/bcma_regs.h +@@ -64,6 +64,8 @@ + #define BCMA_PCI_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */ + #define BCMA_PCI_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */ + ++#define BCMA_PCIE2_BAR0_WIN2 0x70 ++ + /* SiliconBackplane Address Map. + * All regions may not exist on all chips. + */ +--- a/include/linux/bcma/bcma_soc.h ++++ b/include/linux/bcma/bcma_soc.h +@@ -5,8 +5,6 @@ + + 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); +--- a/include/linux/ssb/ssb_regs.h ++++ b/include/linux/ssb/ssb_regs.h +@@ -173,6 +173,7 @@ + #define SSB_SPROMSIZE_BYTES_R123 (SSB_SPROMSIZE_WORDS_R123 * sizeof(u16)) + #define SSB_SPROMSIZE_BYTES_R4 (SSB_SPROMSIZE_WORDS_R4 * sizeof(u16)) + #define SSB_SPROMSIZE_WORDS_R10 230 ++#define SSB_SPROMSIZE_WORDS_R11 234 + #define SSB_SPROM_BASE1 0x1000 + #define SSB_SPROM_BASE31 0x0800 + #define SSB_SPROM_REVISION 0x007E diff --git a/target/linux/generic/patches-3.18/026-bcma-from-3.20.patch b/target/linux/generic/patches-3.18/026-bcma-from-3.20.patch new file mode 100644 index 0000000000..17c06b001f --- /dev/null +++ b/target/linux/generic/patches-3.18/026-bcma-from-3.20.patch @@ -0,0 +1,527 @@ +--- a/drivers/bcma/bcma_private.h ++++ b/drivers/bcma/bcma_private.h +@@ -25,22 +25,18 @@ struct bcma_bus; + bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value, + int timeout); + void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core); ++void bcma_init_bus(struct bcma_bus *bus); + 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); ++int __init bcma_bus_early_register(struct bcma_bus *bus); + #ifdef CONFIG_PM + int bcma_bus_suspend(struct bcma_bus *bus); + int bcma_bus_resume(struct bcma_bus *bus); + #endif + + /* scan.c */ ++void bcma_detect_chip(struct bcma_bus *bus); + 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); +@@ -111,6 +107,14 @@ extern int bcma_chipco_watchdog_register + #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE + bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc); + void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); ++#else ++static inline bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) ++{ ++ return false; ++} ++static inline void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) ++{ ++} + #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ + + #ifdef CONFIG_BCMA_DRIVER_GPIO +--- a/drivers/bcma/driver_chipcommon.c ++++ b/drivers/bcma/driver_chipcommon.c +@@ -79,7 +79,9 @@ static int bcma_chipco_watchdog_ticks_pe + + if (cc->capabilities & BCMA_CC_CAP_PMU) { + if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) +- /* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP clock */ ++ /* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP ++ * clock ++ */ + return bcma_chipco_get_alp_clock(cc) / 4000; + else + /* based on 32KHz ILP clock */ +@@ -97,7 +99,8 @@ int bcma_chipco_watchdog_register(struct + wdt.driver_data = cc; + wdt.timer_set = bcma_chipco_watchdog_timer_set_wdt; + wdt.timer_set_ms = bcma_chipco_watchdog_timer_set_ms_wdt; +- wdt.max_timer_ms = bcma_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms; ++ wdt.max_timer_ms = ++ bcma_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms; + + pdev = platform_device_register_data(NULL, "bcm47xx-wdt", + cc->core->bus->num, &wdt, +@@ -175,7 +178,6 @@ void bcma_core_chipcommon_init(struct bc + u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks) + { + u32 maxt; +- enum bcma_clkmode clkmode; + + maxt = bcma_chipco_watchdog_get_max_timer(cc); + if (cc->capabilities & BCMA_CC_CAP_PMU) { +@@ -185,8 +187,13 @@ u32 bcma_chipco_watchdog_timer_set(struc + ticks = maxt; + bcma_cc_write32(cc, BCMA_CC_PMU_WATCHDOG, ticks); + } else { +- clkmode = ticks ? BCMA_CLKMODE_FAST : BCMA_CLKMODE_DYNAMIC; +- bcma_core_set_clockmode(cc->core, clkmode); ++ struct bcma_bus *bus = cc->core->bus; ++ ++ if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4707 && ++ bus->chipinfo.id != BCMA_CHIP_ID_BCM53018) ++ bcma_core_set_clockmode(cc->core, ++ ticks ? BCMA_CLKMODE_FAST : BCMA_CLKMODE_DYNAMIC); ++ + if (ticks > maxt) + ticks = maxt; + /* instant NMI */ +@@ -335,7 +342,8 @@ void bcma_chipco_serial_init(struct bcma + | BCMA_CC_CORECTL_UARTCLKEN); + } + } else { +- bcma_err(cc->core->bus, "serial not supported on this device ccrev: 0x%x\n", ccrev); ++ bcma_err(cc->core->bus, "serial not supported on this device ccrev: 0x%x\n", ++ ccrev); + return; + } + +--- a/drivers/bcma/driver_pci.c ++++ b/drivers/bcma/driver_pci.c +@@ -145,6 +145,47 @@ static u16 bcma_pcie_mdio_writeread(stru + } + + /************************************************** ++ * Early init. ++ **************************************************/ ++ ++static void bcma_core_pci_fixcfg(struct bcma_drv_pci *pc) ++{ ++ struct bcma_device *core = pc->core; ++ u16 val16, core_index; ++ uint regoff; ++ ++ regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_PI_OFFSET); ++ core_index = (u16)core->core_index; ++ ++ val16 = pcicore_read16(pc, regoff); ++ if (((val16 & BCMA_CORE_PCI_SPROM_PI_MASK) >> BCMA_CORE_PCI_SPROM_PI_SHIFT) ++ != core_index) { ++ val16 = (core_index << BCMA_CORE_PCI_SPROM_PI_SHIFT) | ++ (val16 & ~BCMA_CORE_PCI_SPROM_PI_MASK); ++ pcicore_write16(pc, regoff, val16); ++ } ++} ++ ++/* ++ * Apply some early fixes required before accessing SPROM. ++ * See also si_pci_fixcfg. ++ */ ++void bcma_core_pci_early_init(struct bcma_drv_pci *pc) ++{ ++ if (pc->early_setup_done) ++ return; ++ ++ pc->hostmode = bcma_core_pci_is_in_hostmode(pc); ++ if (pc->hostmode) ++ goto out; ++ ++ bcma_core_pci_fixcfg(pc); ++ ++out: ++ pc->early_setup_done = true; ++} ++ ++/************************************************** + * Workarounds. + **************************************************/ + +@@ -175,24 +216,6 @@ static void bcma_pcicore_serdes_workarou + tmp & ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN); + } + +-static void bcma_core_pci_fixcfg(struct bcma_drv_pci *pc) +-{ +- struct bcma_device *core = pc->core; +- u16 val16, core_index; +- uint regoff; +- +- regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_PI_OFFSET); +- core_index = (u16)core->core_index; +- +- val16 = pcicore_read16(pc, regoff); +- if (((val16 & BCMA_CORE_PCI_SPROM_PI_MASK) >> BCMA_CORE_PCI_SPROM_PI_SHIFT) +- != core_index) { +- val16 = (core_index << BCMA_CORE_PCI_SPROM_PI_SHIFT) | +- (val16 & ~BCMA_CORE_PCI_SPROM_PI_MASK); +- pcicore_write16(pc, regoff, val16); +- } +-} +- + /* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */ + /* Needs to happen when coming out of 'standby'/'hibernate' */ + static void bcma_core_pci_config_fixup(struct bcma_drv_pci *pc) +@@ -216,7 +239,6 @@ static void bcma_core_pci_config_fixup(s + + static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc) + { +- bcma_core_pci_fixcfg(pc); + bcma_pcicore_serdes_workaround(pc); + bcma_core_pci_config_fixup(pc); + } +@@ -226,13 +248,11 @@ void bcma_core_pci_init(struct bcma_drv_ + if (pc->setup_done) + return; + +-#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE +- pc->hostmode = bcma_core_pci_is_in_hostmode(pc); ++ bcma_core_pci_early_init(pc); ++ + if (pc->hostmode) + bcma_core_pci_hostmode_init(pc); +-#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ +- +- if (!pc->hostmode) ++ else + bcma_core_pci_clientmode_init(pc); + } + +--- a/drivers/bcma/host_pci.c ++++ b/drivers/bcma/host_pci.c +@@ -13,10 +13,12 @@ + + static void bcma_host_pci_switch_core(struct bcma_device *core) + { ++ int win2 = core->bus->host_is_pcie2 ? ++ BCMA_PCIE2_BAR0_WIN2 : BCMA_PCI_BAR0_WIN2; ++ + pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN, + core->addr); +- pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN2, +- core->wrap); ++ pci_write_config_dword(core->bus->host_pci, win2, core->wrap); + core->bus->mapped_core = core; + bcma_debug(core->bus, "Switched to core: 0x%X\n", core->id.id); + } +--- a/drivers/bcma/host_soc.c ++++ b/drivers/bcma/host_soc.c +@@ -193,7 +193,7 @@ int __init bcma_host_soc_init(struct bcm + int err; + + /* Scan bus and initialize it */ +- err = bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips); ++ err = bcma_bus_early_register(bus); + if (err) + iounmap(bus->mmio); + +--- a/drivers/bcma/main.c ++++ b/drivers/bcma/main.c +@@ -268,6 +268,18 @@ void bcma_prepare_core(struct bcma_bus * + } + } + ++void bcma_init_bus(struct bcma_bus *bus) ++{ ++ mutex_lock(&bcma_buses_mutex); ++ bus->num = bcma_bus_next_num++; ++ mutex_unlock(&bcma_buses_mutex); ++ ++ INIT_LIST_HEAD(&bus->cores); ++ bus->nr_cores = 0; ++ ++ bcma_detect_chip(bus); ++} ++ + static void bcma_register_core(struct bcma_bus *bus, struct bcma_device *core) + { + int err; +@@ -356,12 +368,19 @@ static void bcma_unregister_cores(struct + struct bcma_device *core, *tmp; + + list_for_each_entry_safe(core, tmp, &bus->cores, list) { ++ if (!core->dev_registered) ++ continue; + list_del(&core->list); +- if (core->dev_registered) +- device_unregister(&core->dev); ++ device_unregister(&core->dev); + } + if (bus->hosttype == BCMA_HOSTTYPE_SOC) + platform_device_unregister(bus->drv_cc.watchdog); ++ ++ /* Now noone uses internally-handled cores, we can free them */ ++ list_for_each_entry_safe(core, tmp, &bus->cores, list) { ++ list_del(&core->list); ++ kfree(core); ++ } + } + + int bcma_bus_register(struct bcma_bus *bus) +@@ -369,10 +388,6 @@ int bcma_bus_register(struct bcma_bus *b + int err; + struct bcma_device *core; + +- mutex_lock(&bcma_buses_mutex); +- bus->num = bcma_bus_next_num++; +- mutex_unlock(&bcma_buses_mutex); +- + /* Scan for devices (cores) */ + err = bcma_bus_scan(bus); + if (err) { +@@ -387,6 +402,13 @@ int bcma_bus_register(struct bcma_bus *b + bcma_core_chipcommon_early_init(&bus->drv_cc); + } + ++ /* Early init PCIE core */ ++ core = bcma_find_core(bus, BCMA_CORE_PCIE); ++ if (core) { ++ bus->drv_pci[0].core = core; ++ bcma_core_pci_early_init(&bus->drv_pci[0]); ++ } ++ + /* Cores providing flash access go before SPROM init */ + list_for_each_entry(core, &bus->cores, list) { + if (bcma_is_core_needed_early(core->id.id)) +@@ -459,7 +481,6 @@ int bcma_bus_register(struct bcma_bus *b + + void bcma_bus_unregister(struct bcma_bus *bus) + { +- struct bcma_device *cores[3]; + int err; + + err = bcma_gpio_unregister(&bus->drv_cc); +@@ -470,46 +491,23 @@ void bcma_bus_unregister(struct bcma_bus + + bcma_core_chipcommon_b_free(&bus->drv_cc_b); + +- cores[0] = bcma_find_core(bus, BCMA_CORE_MIPS_74K); +- cores[1] = bcma_find_core(bus, BCMA_CORE_PCIE); +- cores[2] = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON); +- + bcma_unregister_cores(bus); +- +- kfree(cores[2]); +- kfree(cores[1]); +- kfree(cores[0]); + } + +-int __init bcma_bus_early_register(struct bcma_bus *bus, +- struct bcma_device *core_cc, +- struct bcma_device *core_mips) ++/* ++ * This is a special version of bus registration function designed for SoCs. ++ * It scans bus and performs basic initialization of main cores only. ++ * Please note it requires memory allocation, however it won't try to sleep. ++ */ ++int __init bcma_bus_early_register(struct bcma_bus *bus) + { + int err; + struct bcma_device *core; +- struct bcma_device_id match; +- +- match.manuf = BCMA_MANUF_BCM; +- match.id = bcma_cc_core_id(bus); +- match.class = BCMA_CL_SIM; +- match.rev = BCMA_ANY_REV; + +- /* Scan for chip common core */ +- err = bcma_bus_scan_early(bus, &match, core_cc); +- if (err) { +- bcma_err(bus, "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; +- +- /* Scan for mips core */ +- err = bcma_bus_scan_early(bus, &match, core_mips); ++ /* Scan for devices (cores) */ ++ err = bcma_bus_scan(bus); + if (err) { +- bcma_err(bus, "Failed to scan for mips core: %d\n", err); ++ bcma_err(bus, "Failed to scan bus: %d\n", err); + return -1; + } + +--- a/drivers/bcma/scan.c ++++ b/drivers/bcma/scan.c +@@ -435,15 +435,12 @@ static int bcma_get_next_core(struct bcm + return 0; + } + +-void bcma_init_bus(struct bcma_bus *bus) ++void bcma_detect_chip(struct bcma_bus *bus) + { + s32 tmp; + struct bcma_chipinfo *chipinfo = &(bus->chipinfo); + char chip_id[8]; + +- INIT_LIST_HEAD(&bus->cores); +- bus->nr_cores = 0; +- + bcma_scan_switch_core(bus, BCMA_ADDR_BASE); + + tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID); +@@ -464,6 +461,10 @@ int bcma_bus_scan(struct bcma_bus *bus) + + int err, core_num = 0; + ++ /* Skip if bus was already scanned (e.g. during early register) */ ++ if (bus->nr_cores) ++ return 0; ++ + erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); + if (bus->hosttype == BCMA_HOSTTYPE_SOC) { + eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE); +@@ -519,64 +520,6 @@ int bcma_bus_scan(struct bcma_bus *bus) + out: + if (bus->hosttype == BCMA_HOSTTYPE_SOC) + iounmap(eromptr); +- +- return err; +-} +- +-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 = -ENODEV; +- int core_num = 0; +- +- erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); +- if (bus->hosttype == BCMA_HOSTTYPE_SOC) { +- eromptr = ioremap_nocache(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); +- +- 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) +- goto out; +- +- core->core_index = core_num++; +- bus->nr_cores++; +- bcma_info(bus, "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_tail(&core->list, &bus->cores); +- err = 0; +- break; +- } +- +-out: +- if (bus->hosttype == BCMA_HOSTTYPE_SOC) +- iounmap(eromptr); + + return err; + } +--- a/drivers/bcma/sprom.c ++++ b/drivers/bcma/sprom.c +@@ -579,7 +579,8 @@ int bcma_sprom_get(struct bcma_bus *bus) + u16 offset = BCMA_CC_SPROM; + u16 *sprom; + size_t sprom_sizes[] = { SSB_SPROMSIZE_WORDS_R4, +- SSB_SPROMSIZE_WORDS_R10, }; ++ SSB_SPROMSIZE_WORDS_R10, ++ SSB_SPROMSIZE_WORDS_R11, }; + int i, err = 0; + + if (!bus->drv_cc.core) +--- a/include/linux/bcma/bcma.h ++++ b/include/linux/bcma/bcma.h +@@ -318,6 +318,7 @@ struct bcma_bus { + const struct bcma_host_ops *ops; + + enum bcma_hosttype hosttype; ++ bool host_is_pcie2; /* Used for BCMA_HOSTTYPE_PCI only */ + union { + /* Pointer to the PCI bus (only for BCMA_HOSTTYPE_PCI) */ + struct pci_dev *host_pci; +--- a/include/linux/bcma/bcma_driver_pci.h ++++ b/include/linux/bcma/bcma_driver_pci.h +@@ -223,6 +223,7 @@ struct bcma_drv_pci_host { + + struct bcma_drv_pci { + struct bcma_device *core; ++ u8 early_setup_done:1; + u8 setup_done:1; + u8 hostmode:1; + +@@ -237,6 +238,7 @@ struct bcma_drv_pci { + #define pcicore_write16(pc, offset, val) bcma_write16((pc)->core, offset, val) + #define pcicore_write32(pc, offset, val) bcma_write32((pc)->core, offset, val) + ++extern void bcma_core_pci_early_init(struct bcma_drv_pci *pc); + extern void bcma_core_pci_init(struct bcma_drv_pci *pc); + extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, + struct bcma_device *core, bool enable); +--- a/include/linux/bcma/bcma_regs.h ++++ b/include/linux/bcma/bcma_regs.h +@@ -64,6 +64,8 @@ + #define BCMA_PCI_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */ + #define BCMA_PCI_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */ + ++#define BCMA_PCIE2_BAR0_WIN2 0x70 ++ + /* SiliconBackplane Address Map. + * All regions may not exist on all chips. + */ +--- a/include/linux/bcma/bcma_soc.h ++++ b/include/linux/bcma/bcma_soc.h +@@ -5,8 +5,6 @@ + + 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); +--- a/include/linux/ssb/ssb_regs.h ++++ b/include/linux/ssb/ssb_regs.h +@@ -173,6 +173,7 @@ + #define SSB_SPROMSIZE_BYTES_R123 (SSB_SPROMSIZE_WORDS_R123 * sizeof(u16)) + #define SSB_SPROMSIZE_BYTES_R4 (SSB_SPROMSIZE_WORDS_R4 * sizeof(u16)) + #define SSB_SPROMSIZE_WORDS_R10 230 ++#define SSB_SPROMSIZE_WORDS_R11 234 + #define SSB_SPROM_BASE1 0x1000 + #define SSB_SPROM_BASE31 0x0800 + #define SSB_SPROM_REVISION 0x007E