From 5cbc7a981677f96a737c01c48f50a5fac8db3c77 Mon Sep 17 00:00:00 2001 From: Tim Niemeyer Date: Sun, 1 Dec 2013 14:15:14 +0100 Subject: [PATCH] buildscript: use src folder for downloads This also integrates the ffol packages feed into this repo. Signed-off-by: Tim Niemeyer --- build_patches/feeds.conf | 8 +- build_patches/kernel_ar71xx_36664.patch | 283 + build_patches/kernel_generic_37768.patch | 6841 +++++++++++++++++ .../480-ar913x_wmac_external_reset.patch | 31 - ...-mac-argument-to-ath79_register_wmac.patch | 81 - ...ath79-add-ath79_gpio_function_select.patch | 47 - ...S-ath79-enable-UART-for-early_serial.patch | 61 - .../606-MIPS-ath79-pb44-fixes.patch | 153 - .../620-MIPS-ath79-OTP-support.patch | 166 - ...add-ath79_wmac_disable_25ghz-helpers.patch | 31 - .../650-MIPS-ath79-fix-ar933x-reset.patch | 31 - buildscript | 86 +- src/packages/ffol/ath9k-watchdog/Makefile | 47 + .../ffol/ath9k-watchdog/files/ath9k-watchdog | 31 + .../ath9k-watchdog/files/ath9k-watchdog-pm | 25 + .../ath9k-watchdog/files/ath9k-watchdog.init | 28 + src/packages/ffol/libwlocate/Makefile | 51 + src/packages/ffol/lwtrace/Makefile | 48 + src/packages/ffol/nodewatcher/Makefile | 40 + 19 files changed, 7468 insertions(+), 621 deletions(-) create mode 100644 build_patches/kernel_ar71xx_36664.patch create mode 100644 build_patches/kernel_generic_37768.patch delete mode 100644 build_patches/linux/ar71xx/patches-3.3/480-ar913x_wmac_external_reset.patch delete mode 100644 build_patches/linux/ar71xx/patches-3.3/501-MIPS-ath79-add-mac-argument-to-ath79_register_wmac.patch delete mode 100644 build_patches/linux/ar71xx/patches-3.3/505-MIPS-ath79-add-ath79_gpio_function_select.patch delete mode 100644 build_patches/linux/ar71xx/patches-3.3/521-MIPS-ath79-enable-UART-for-early_serial.patch delete mode 100644 build_patches/linux/ar71xx/patches-3.3/606-MIPS-ath79-pb44-fixes.patch delete mode 100644 build_patches/linux/ar71xx/patches-3.3/620-MIPS-ath79-OTP-support.patch delete mode 100644 build_patches/linux/ar71xx/patches-3.3/621-MIPS-ath79-add-ath79_wmac_disable_25ghz-helpers.patch delete mode 100644 build_patches/linux/ar71xx/patches-3.3/650-MIPS-ath79-fix-ar933x-reset.patch create mode 100755 src/packages/ffol/ath9k-watchdog/Makefile create mode 100755 src/packages/ffol/ath9k-watchdog/files/ath9k-watchdog create mode 100755 src/packages/ffol/ath9k-watchdog/files/ath9k-watchdog-pm create mode 100755 src/packages/ffol/ath9k-watchdog/files/ath9k-watchdog.init create mode 100644 src/packages/ffol/libwlocate/Makefile create mode 100644 src/packages/ffol/lwtrace/Makefile create mode 100644 src/packages/ffol/nodewatcher/Makefile diff --git a/build_patches/feeds.conf b/build_patches/feeds.conf index 783a6c7..b5ff13d 100644 --- a/build_patches/feeds.conf +++ b/build_patches/feeds.conf @@ -1,4 +1,4 @@ -src-svn packages svn://svn.openwrt.org/openwrt/packages@35298 -src-git routing https://github.com/openwrt-routing/packages.git^072ba90ce4b126e84d3e1734ba8e9d4beab48f03 -src-git fastd git://git.metameute.de/lff/pkg_fastd;v10 -src-git packagesol git://freifunk-ol.de/ffol/packages.git;0.3.999d +src-link openwrt PATH/openwrt +src-link routing PATH/routing +src-link fastd PATH/fastd +src-link packagesol PATH/ffol diff --git a/build_patches/kernel_ar71xx_36664.patch b/build_patches/kernel_ar71xx_36664.patch new file mode 100644 index 0000000..f021ec3 --- /dev/null +++ b/build_patches/kernel_ar71xx_36664.patch @@ -0,0 +1,283 @@ +Index: files/arch/mips/ath79/mach-dir-825-b1.c +=================================================================== +--- files/arch/mips/ath79/mach-dir-825-b1.c (Revision 35298) ++++ files/arch/mips/ath79/mach-dir-825-b1.c (Revision 36664) +@@ -138,7 +138,8 @@ + static void __init dir825b1_wlan_init(void) + { + u8 *caldata; +- u8 mac1[ETH_ALEN], mac2[ETH_ALEN]; ++ u8 mac0[ETH_ALEN], mac1[ETH_ALEN]; ++ u8 wmac0[ETH_ALEN], wmac1[ETH_ALEN]; + + caldata = (u8 *) KSEG1ADDR(DIR825B1_CAL_LOCATION_0); + if (!dir825b1_is_caldata_valid(caldata)) { +@@ -149,17 +150,19 @@ + } + } + +- dir825b1_read_ascii_mac(mac1, caldata + DIR825B1_MAC0_OFFSET); +- dir825b1_read_ascii_mac(mac2, caldata + DIR825B1_MAC1_OFFSET); ++ dir825b1_read_ascii_mac(mac0, caldata + DIR825B1_MAC0_OFFSET); ++ dir825b1_read_ascii_mac(mac1, caldata + DIR825B1_MAC1_OFFSET); + +- ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 2); +- ath79_init_mac(ath79_eth1_data.mac_addr, mac1, 3); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac0, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac1, 0); ++ ath79_init_mac(wmac0, mac0, 0); ++ ath79_init_mac(wmac1, mac1, 1); + + ap9x_pci_setup_wmac_led_pin(0, 5); + ap9x_pci_setup_wmac_led_pin(1, 5); + +- ap94_pci_init(caldata + DIR825B1_CAL0_OFFSET, mac1, +- caldata + DIR825B1_CAL1_OFFSET, mac2); ++ ap94_pci_init(caldata + DIR825B1_CAL0_OFFSET, wmac0, ++ caldata + DIR825B1_CAL1_OFFSET, wmac1); + } + + static void __init dir825b1_setup(void) +Index: files/arch/mips/ath79/mach-rb750.c +=================================================================== +--- files/arch/mips/ath79/mach-rb750.c (Revision 35298) ++++ files/arch/mips/ath79/mach-rb750.c (Revision 36664) +@@ -282,7 +282,6 @@ + + #define RB751_HARDCONFIG 0x1f00b000 + #define RB751_HARDCONFIG_SIZE 0x1000 +-#define RB751_MAC_ADDRESS_OFFSET 0xE80 + + static void __init rb751_wlan_setup(void) + { +@@ -290,6 +289,8 @@ + struct ath9k_platform_data *wmac_data; + u16 tag_len; + u8 *tag; ++ u16 mac_len; ++ u8 *mac; + int err; + + wmac_data = ap9x_pci_get_wmac_data(0); +@@ -314,7 +315,14 @@ + return; + } + +- ap91_pci_init(NULL, hardconfig + RB751_MAC_ADDRESS_OFFSET); ++ err = routerboot_find_tag(hardconfig, RB751_HARDCONFIG_SIZE, ++ RB_ID_MAC_ADDRESS_PACK, &mac, &mac_len); ++ if (err) { ++ pr_err("rb75x: no mac address found\n"); ++ return; ++ } ++ ++ ap91_pci_init(NULL, mac); + } + + static void __init rb751_setup(void) +Index: files/arch/mips/ath79/mach-om2p.c +=================================================================== +--- files/arch/mips/ath79/mach-om2p.c (Revision 35298) ++++ files/arch/mips/ath79/mach-om2p.c (Revision 36664) +@@ -187,7 +187,7 @@ + + /* enable reset button */ + ath79_gpio_output_select(OM2P_GPIO_BTN_RESET, AR934X_GPIO_OUT_GPIO); +- ath79_gpio_function_enable(AR933X_GPIO_FUNC_JTAG_DISABLE); ++ ath79_gpio_function_enable(AR934X_GPIO_FUNC_JTAG_DISABLE); + + om2p_leds_gpio[4].gpio = OM2P_GPIO_LED_WAN; + om2p_leds_gpio[5].gpio = OM2P_GPIO_LED_LAN; +Index: files/arch/mips/ath79/mach-rb4xx.c +=================================================================== +--- files/arch/mips/ath79/mach-rb4xx.c (Revision 35298) ++++ files/arch/mips/ath79/mach-rb4xx.c (Revision 36664) +@@ -429,6 +429,9 @@ + rb4xx_leds_gpio); + + spi_register_board_info(rb4xx_spi_info, ARRAY_SIZE(rb4xx_spi_info)); ++ spi_register_board_info(rb4xx_microsd_info, ++ ARRAY_SIZE(rb4xx_microsd_info)); ++ + platform_device_register(&rb4xx_spi_device); + platform_device_register(&rb4xx_nand_device); + +Index: image/Makefile +=================================================================== +--- image/Makefile (Revision 35298) ++++ image/Makefile (Revision 36664) +@@ -279,6 +279,10 @@ + fi + endef + ++define Image/Build/WZRHPG30XNH/initramfs ++ $(call MkuImageLzma/initramfs,$(2),$(3) $(4)) ++endef ++ + define Image/Build/WHRHPG300N + $(call MkuImageLzma,$(2),$(3) $(4)) + $(call Sysupgrade/KRuImage,$(1),$(2),983040,2883584) +Index: patches-3.3/480-ar913x_wmac_external_reset.patch +=================================================================== +--- patches-3.3/480-ar913x_wmac_external_reset.patch (Revision 0) ++++ patches-3.3/480-ar913x_wmac_external_reset.patch (Revision 36664) +@@ -0,0 +1,31 @@ ++--- a/arch/mips/ath79/dev-wmac.c +++++ b/arch/mips/ath79/dev-wmac.c ++@@ -44,7 +44,7 @@ static struct platform_device ath79_wmac ++ }, ++ }; ++ ++-static void __init ar913x_wmac_setup(void) +++static int ar913x_wmac_reset(void) ++ { ++ /* reset the WMAC */ ++ ath79_device_reset_set(AR913X_RESET_AMBA2WMAC); ++@@ -53,10 +53,19 @@ static void __init ar913x_wmac_setup(voi ++ ath79_device_reset_clear(AR913X_RESET_AMBA2WMAC); ++ mdelay(10); ++ +++ return 0; +++} +++ +++static void __init ar913x_wmac_setup(void) +++{ +++ ar913x_wmac_reset(); +++ ++ ath79_wmac_resources[0].start = AR913X_WMAC_BASE; ++ ath79_wmac_resources[0].end = AR913X_WMAC_BASE + AR913X_WMAC_SIZE - 1; ++ ath79_wmac_resources[1].start = ATH79_CPU_IRQ_IP2; ++ ath79_wmac_resources[1].end = ATH79_CPU_IRQ_IP2; +++ +++ ath79_wmac_data.external_reset = ar913x_wmac_reset; ++ } ++ ++ +Index: patches-3.3/505-MIPS-ath79-add-ath79_gpio_function_select.patch +=================================================================== +--- patches-3.3/505-MIPS-ath79-add-ath79_gpio_function_select.patch (Revision 35298) ++++ patches-3.3/505-MIPS-ath79-add-ath79_gpio_function_select.patch (Revision 36664) +@@ -10,7 +10,7 @@ + #endif /* __ATH79_COMMON_H */ + --- a/arch/mips/ath79/gpio.c + +++ b/arch/mips/ath79/gpio.c +-@@ -198,6 +198,34 @@ void ath79_gpio_function_setup(u32 set, ++@@ -198,6 +198,34 @@ void ath79_gpio_function_setup(u32 set, + spin_unlock_irqrestore(&ath79_gpio_lock, flags); + } + +Index: patches-3.3/620-MIPS-ath79-OTP-support.patch +=================================================================== +--- patches-3.3/620-MIPS-ath79-OTP-support.patch (Revision 35298) ++++ patches-3.3/620-MIPS-ath79-OTP-support.patch (Revision 36664) +@@ -1,6 +1,6 @@ + --- a/arch/mips/ath79/dev-wmac.c + +++ b/arch/mips/ath79/dev-wmac.c +-@@ -139,6 +139,137 @@ static void qca955x_wmac_setup(void) ++@@ -148,6 +148,137 @@ static void qca955x_wmac_setup(void) + ath79_wmac_data.is_clk_25mhz = true; + } + +Index: patches-3.3/601-MIPS-ath79-add-more-register-defines.patch +=================================================================== +--- patches-3.3/601-MIPS-ath79-add-more-register-defines.patch (Revision 35298) ++++ patches-3.3/601-MIPS-ath79-add-more-register-defines.patch (Revision 36664) +@@ -166,7 +166,7 @@ + #define AR934X_GPIO_REG_FUNC 0x6c + + #define AR71XX_GPIO_COUNT 16 +-@@ -550,4 +618,133 @@ ++@@ -550,4 +618,139 @@ + #define AR934X_SRIF_DPLL2_OUTDIV_SHIFT 13 + #define AR934X_SRIF_DPLL2_OUTDIV_MASK 0x7 + +@@ -227,9 +227,15 @@ + +#define AR933X_GPIO_FUNC_UART_EN BIT(1) + +#define AR933X_GPIO_FUNC_JTAG_DISABLE BIT(0) + + +-+#define AR934X_GPIO_FUNC_DDR_DQOE_EN BIT(17) +-+#define AR934X_GPIO_FUNC_SPI_CS_1_EN BIT(14) +-+#define AR934X_GPIO_FUNC_SPI_CS_0_EN BIT(13) +++#define AR934X_GPIO_FUNC_CLK_OBS7_EN BIT(9) +++#define AR934X_GPIO_FUNC_CLK_OBS6_EN BIT(8) +++#define AR934X_GPIO_FUNC_CLK_OBS5_EN BIT(7) +++#define AR934X_GPIO_FUNC_CLK_OBS4_EN BIT(6) +++#define AR934X_GPIO_FUNC_CLK_OBS3_EN BIT(5) +++#define AR934X_GPIO_FUNC_CLK_OBS2_EN BIT(4) +++#define AR934X_GPIO_FUNC_CLK_OBS1_EN BIT(3) +++#define AR934X_GPIO_FUNC_CLK_OBS0_EN BIT(2) +++#define AR934X_GPIO_FUNC_JTAG_DISABLE BIT(1) + + + +#define AR934X_GPIO_OUT_GPIO 0x00 + + +Index: patches-3.3/501-MIPS-ath79-add-mac-argument-to-ath79_register_wmac.patch +=================================================================== +--- patches-3.3/501-MIPS-ath79-add-mac-argument-to-ath79_register_wmac.patch (Revision 35298) ++++ patches-3.3/501-MIPS-ath79-add-mac-argument-to-ath79_register_wmac.patch (Revision 36664) +@@ -16,7 +16,7 @@ + static struct ath9k_platform_data ath79_wmac_data; + + static struct resource ath79_wmac_resources[] = { +-@@ -134,7 +136,7 @@ static void qca955x_wmac_setup(void) ++@@ -143,7 +145,7 @@ static void qca955x_wmac_setup(void) + ath79_wmac_data.is_clk_25mhz = true; + } + +@@ -25,7 +25,7 @@ + { + if (soc_is_ar913x()) + ar913x_wmac_setup(); +-@@ -151,5 +153,10 @@ void __init ath79_register_wmac(u8 *cal_ ++@@ -160,5 +162,10 @@ void __init ath79_register_wmac(u8 *cal_ + memcpy(ath79_wmac_data.eeprom_data, cal_data, + sizeof(ath79_wmac_data.eeprom_data)); + +Index: patches-3.3/621-MIPS-ath79-add-ath79_wmac_disable_25ghz-helpers.patch +=================================================================== +--- patches-3.3/621-MIPS-ath79-add-ath79_wmac_disable_25ghz-helpers.patch (Revision 35298) ++++ patches-3.3/621-MIPS-ath79-add-ath79_wmac_disable_25ghz-helpers.patch (Revision 36664) +@@ -1,6 +1,6 @@ + --- a/arch/mips/ath79/dev-wmac.c + +++ b/arch/mips/ath79/dev-wmac.c +-@@ -270,6 +270,16 @@ bool __init ar93xx_wmac_read_mac_address ++@@ -279,6 +279,16 @@ bool __init ar93xx_wmac_read_mac_address + return ret; + } + +Index: patches-3.3/650-MIPS-ath79-fix-ar933x-reset.patch +=================================================================== +--- patches-3.3/650-MIPS-ath79-fix-ar933x-reset.patch (Revision 35298) ++++ patches-3.3/650-MIPS-ath79-fix-ar933x-reset.patch (Revision 36664) +@@ -1,6 +1,6 @@ + --- a/arch/mips/ath79/dev-wmac.c + +++ b/arch/mips/ath79/dev-wmac.c +-@@ -67,10 +67,27 @@ static void __init ar913x_wmac_setup(voi ++@@ -76,10 +76,27 @@ static void __init ar913x_wmac_setup(voi + + static int ar933x_wmac_reset(void) + { +Index: patches-3.3/606-MIPS-ath79-pb44-fixes.patch +=================================================================== +--- patches-3.3/606-MIPS-ath79-pb44-fixes.patch (Revision 35298) ++++ patches-3.3/606-MIPS-ath79-pb44-fixes.patch (Revision 36664) +@@ -50,7 +50,7 @@ + #define PB44_GPIO_SW_RESET (PB44_GPIO_EXP_BASE + 6) + #define PB44_GPIO_SW_JUMP (PB44_GPIO_EXP_BASE + 8) + #define PB44_GPIO_LED_JUMP1 (PB44_GPIO_EXP_BASE + 9) +-@@ -92,21 +117,66 @@ static struct ath79_spi_controller_data ++@@ -92,21 +117,66 @@ static struct ath79_spi_controller_data + .cs_line = 0, + }; + +Index: patches-3.3/521-MIPS-ath79-enable-UART-for-early_serial.patch +=================================================================== +--- patches-3.3/521-MIPS-ath79-enable-UART-for-early_serial.patch (Revision 35298) ++++ patches-3.3/521-MIPS-ath79-enable-UART-for-early_serial.patch (Revision 36664) +@@ -1,6 +1,6 @@ + --- a/arch/mips/ath79/early_printk.c + +++ b/arch/mips/ath79/early_printk.c +-@@ -56,6 +56,46 @@ static void prom_putchar_dummy(unsigned ++@@ -56,6 +56,46 @@ static void prom_putchar_dummy(unsigned + /* nothing to do */ + } + diff --git a/build_patches/kernel_generic_37768.patch b/build_patches/kernel_generic_37768.patch new file mode 100644 index 0000000..ec796ce --- /dev/null +++ b/build_patches/kernel_generic_37768.patch @@ -0,0 +1,6841 @@ +Index: files/include/linux/ath9k_platform.h +=================================================================== +--- files/include/linux/ath9k_platform.h (Revision 35298) ++++ files/include/linux/ath9k_platform.h (Revision 37768) +@@ -22,6 +22,8 @@ + #define ATH9K_PLAT_EEP_MAX_WORDS 2048 + + struct ath9k_platform_data { ++ const char *eeprom_name; ++ + u16 eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS]; + u8 *macaddr; + +Index: config-3.3 +=================================================================== +--- config-3.3 (Revision 35298) ++++ config-3.3 (Revision 37768) +@@ -193,6 +193,7 @@ + # CONFIG_BCM63XX is not set + # CONFIG_BCM63XX_PHY is not set + # CONFIG_BCMA is not set ++# CONFIG_BCMA_DRIVER_GPIO is not set + # CONFIG_BCM_WIMAX is not set + # CONFIG_BDI_SWITCH is not set + # CONFIG_BE2ISCSI is not set +@@ -2842,6 +2843,7 @@ + CONFIG_SQUASHFS_XZ=y + # CONFIG_SQUASHFS_ZLIB is not set + # CONFIG_SSB is not set ++# CONFIG_SSB_DRIVER_GPIO is not set + # CONFIG_SSB_DEBUG is not set + # CONFIG_SSB_PCMCIAHOST is not set + CONFIG_SSB_POSSIBLE=y +Index: patches-3.3/028-bcma-fix-regression-in-interrupt-assignment-on-mips.patch +=================================================================== +--- patches-3.3/028-bcma-fix-regression-in-interrupt-assignment-on-mips.patch (Revision 35298) ++++ patches-3.3/028-bcma-fix-regression-in-interrupt-assignment-on-mips.patch (Revision 37768) +@@ -1,29 +0,0 @@ +---- a/drivers/bcma/driver_mips.c +-+++ b/drivers/bcma/driver_mips.c +-@@ -131,7 +131,7 @@ static void bcma_core_mips_set_irq(struc +- /* 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) { +-+ list_for_each_entry(core, &bus->cores, list) { +- if ((1 << bcma_core_mips_irqflag(core)) == +- oldirqflag) { +- bcma_core_mips_set_irq(core, 0); +-@@ -161,7 +161,7 @@ static void bcma_core_mips_dump_irq(stru +- { +- struct bcma_device *core; +- +-- list_for_each_entry_reverse(core, &bus->cores, list) { +-+ list_for_each_entry(core, &bus->cores, list) { +- bcma_core_mips_print_irq(core, bcma_core_mips_irq(core)); +- } +- } +-@@ -215,7 +215,7 @@ void bcma_core_mips_init(struct bcma_drv +- mcore->assigned_irqs = 1; +- +- /* Assign IRQs to all cores on the bus */ +-- list_for_each_entry_reverse(core, &bus->cores, list) { +-+ list_for_each_entry(core, &bus->cores, list) { +- int mips_irq; +- if (core->irq) +- continue; +Index: patches-3.3/027-bcma-add-missing-iounmap-on-error-path.patch +=================================================================== +--- patches-3.3/027-bcma-add-missing-iounmap-on-error-path.patch (Revision 35298) ++++ patches-3.3/027-bcma-add-missing-iounmap-on-error-path.patch (Revision 37768) +@@ -1,55 +0,0 @@ +---- a/drivers/bcma/scan.c +-+++ b/drivers/bcma/scan.c +-@@ -462,8 +462,10 @@ int bcma_bus_scan(struct bcma_bus *bus) +- while (eromptr < eromend) { +- struct bcma_device *other_core; +- struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL); +-- if (!core) +-- return -ENOMEM; +-+ if (!core) { +-+ err = -ENOMEM; +-+ goto out; +-+ } +- INIT_LIST_HEAD(&core->list); +- core->bus = bus; +- +-@@ -478,7 +480,7 @@ int bcma_bus_scan(struct bcma_bus *bus) +- } else if (err == -ESPIPE) { +- break; +- } +-- return err; +-+ goto out; +- } +- +- core->core_index = core_num++; +-@@ -494,10 +496,12 @@ int bcma_bus_scan(struct bcma_bus *bus) +- list_add_tail(&core->list, &bus->cores); +- } +- +-+ err = 0; +-+out: +- if (bus->hosttype == BCMA_HOSTTYPE_SOC) +- iounmap(eromptr); +- +-- return 0; +-+ return err; +- } +- +- int __init bcma_bus_scan_early(struct bcma_bus *bus, +-@@ -537,7 +541,7 @@ int __init bcma_bus_scan_early(struct bc +- else if (err == -ESPIPE) +- break; +- else if (err < 0) +-- return err; +-+ goto out; +- +- core->core_index = core_num++; +- bus->nr_cores++; +-@@ -551,6 +555,7 @@ int __init bcma_bus_scan_early(struct bc +- break; +- } +- +-+out: +- if (bus->hosttype == BCMA_HOSTTYPE_SOC) +- iounmap(eromptr); +- +Index: patches-3.3/026-bcma_pmu_regression.patch +=================================================================== +--- patches-3.3/026-bcma_pmu_regression.patch (Revision 35298) ++++ patches-3.3/026-bcma_pmu_regression.patch (Revision 37768) +@@ -1,29 +0,0 @@ +---- a/drivers/bcma/driver_chipcommon_pmu.c +-+++ b/drivers/bcma/driver_chipcommon_pmu.c +-@@ -110,7 +110,7 @@ void bcma_pmu_workarounds(struct bcma_dr +- /* enable 12 mA drive strenth for 4313 and set chipControl +- register bit 1 */ +- bcma_chipco_chipctl_maskset(cc, 0, +-- BCMA_CCTRL_4313_12MA_LED_DRIVE, +-+ ~BCMA_CCTRL_4313_12MA_LED_DRIVE, +- BCMA_CCTRL_4313_12MA_LED_DRIVE); +- break; +- case BCMA_CHIP_ID_BCM4331: +-@@ -124,14 +124,14 @@ void bcma_pmu_workarounds(struct bcma_dr +- register bit 15 */ +- if (bus->chipinfo.rev == 0) { +- bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL, +-- BCMA_CCTRL_43224_GPIO_TOGGLE, +-+ ~BCMA_CCTRL_43224_GPIO_TOGGLE, +- BCMA_CCTRL_43224_GPIO_TOGGLE); +- bcma_chipco_chipctl_maskset(cc, 0, +-- BCMA_CCTRL_43224A0_12MA_LED_DRIVE, +-+ ~BCMA_CCTRL_43224A0_12MA_LED_DRIVE, +- BCMA_CCTRL_43224A0_12MA_LED_DRIVE); +- } else { +- bcma_chipco_chipctl_maskset(cc, 0, +-- BCMA_CCTRL_43224B0_12MA_LED_DRIVE, +-+ ~BCMA_CCTRL_43224B0_12MA_LED_DRIVE, +- BCMA_CCTRL_43224B0_12MA_LED_DRIVE); +- } +- break; +Index: patches-3.3/660-ipv6-loopback-policy-routing.patch +=================================================================== +--- patches-3.3/660-ipv6-loopback-policy-routing.patch (Revision 0) ++++ patches-3.3/660-ipv6-loopback-policy-routing.patch (Revision 37768) +@@ -0,0 +1,11 @@ ++--- a/net/ipv6/route.c +++++ b/net/ipv6/route.c ++@@ -899,6 +899,8 @@ struct dst_entry * ip6_route_output(stru ++ { ++ int flags = 0; ++ +++ fl6->flowi6_iif = net->loopback_dev->ifindex; +++ ++ if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr)) ++ flags |= RT6_LOOKUP_F_IFACE; ++ +Index: patches-3.3/065-8139cp-fixes.patch +=================================================================== +--- patches-3.3/065-8139cp-fixes.patch (Revision 35298) ++++ patches-3.3/065-8139cp-fixes.patch (Revision 37768) +@@ -66,11 +66,9 @@ + + Signed-off-by: David S. Miller + +-diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c +-index b01f83a..6cb96b4 100644 + --- a/drivers/net/ethernet/realtek/8139cp.c + +++ b/drivers/net/ethernet/realtek/8139cp.c +-@@ -648,6 +648,7 @@ static void cp_tx (struct cp_private *cp) ++@@ -645,6 +645,7 @@ static void cp_tx (struct cp_private *cp + { + unsigned tx_head = cp->tx_head; + unsigned tx_tail = cp->tx_tail; +@@ -78,7 +76,7 @@ + + while (tx_tail != tx_head) { + struct cp_desc *txd = cp->tx_ring + tx_tail; +-@@ -666,6 +667,9 @@ static void cp_tx (struct cp_private *cp) ++@@ -663,6 +664,9 @@ static void cp_tx (struct cp_private *cp + le32_to_cpu(txd->opts1) & 0xffff, + PCI_DMA_TODEVICE); + +@@ -88,7 +86,7 @@ + if (status & LastFrag) { + if (status & (TxError | TxFIFOUnder)) { + netif_dbg(cp, tx_err, cp->dev, +-@@ -697,6 +701,7 @@ static void cp_tx (struct cp_private *cp) ++@@ -694,6 +698,7 @@ static void cp_tx (struct cp_private *cp + + cp->tx_tail = tx_tail; + +@@ -96,7 +94,7 @@ + if (TX_BUFFS_AVAIL(cp) > (MAX_SKB_FRAGS + 1)) + netif_wake_queue(cp->dev); + } +-@@ -843,6 +848,8 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, ++@@ -840,6 +845,8 @@ static netdev_tx_t cp_start_xmit (struct + wmb(); + } + cp->tx_head = entry; +@@ -105,7 +103,7 @@ + netif_dbg(cp, tx_queued, cp->dev, "tx queued, slot %d, skblen %d\n", + entry, skb->len); + if (TX_BUFFS_AVAIL(cp) <= (MAX_SKB_FRAGS + 1)) +-@@ -937,6 +944,8 @@ static void cp_stop_hw (struct cp_private *cp) ++@@ -934,6 +941,8 @@ static void cp_stop_hw (struct cp_privat + + cp->rx_tail = 0; + cp->tx_head = cp->tx_tail = 0; +@@ -114,7 +112,7 @@ + } + + static void cp_reset_hw (struct cp_private *cp) +-@@ -957,8 +966,38 @@ static void cp_reset_hw (struct cp_private *cp) ++@@ -954,8 +963,38 @@ static void cp_reset_hw (struct cp_priva + + static inline void cp_start_hw (struct cp_private *cp) + { +@@ -153,7 +151,7 @@ + } + + static void cp_enable_irq(struct cp_private *cp) +-@@ -969,7 +1008,6 @@ static void cp_enable_irq(struct cp_private *cp) ++@@ -966,7 +1005,6 @@ static void cp_enable_irq(struct cp_priv + static void cp_init_hw (struct cp_private *cp) + { + struct net_device *dev = cp->dev; +@@ -161,7 +159,7 @@ + + cp_reset_hw(cp); + +-@@ -992,17 +1030,6 @@ static void cp_init_hw (struct cp_private *cp) ++@@ -989,17 +1027,6 @@ static void cp_init_hw (struct cp_privat + + cpw8(Config5, cpr8(Config5) & PMEStatus); + +@@ -179,7 +177,7 @@ + cpw16(MultiIntr, 0); + + cpw8_f(Cfg9346, Cfg9346_Lock); +-@@ -1192,6 +1219,7 @@ static void cp_tx_timeout(struct net_device *dev) ++@@ -1188,6 +1215,7 @@ static void cp_tx_timeout(struct net_dev + cp_clean_rings(cp); + rc = cp_init_rings(cp); + cp_start_hw(cp); +Index: patches-3.3/259-compressor_kconfig_hack.patch +=================================================================== +--- patches-3.3/259-compressor_kconfig_hack.patch (Revision 0) ++++ patches-3.3/259-compressor_kconfig_hack.patch (Revision 37768) +@@ -0,0 +1,23 @@ ++--- a/lib/Kconfig +++++ b/lib/Kconfig ++@@ -105,16 +105,16 @@ config AUDIT_GENERIC ++ # compression support is select'ed if needed ++ # ++ config ZLIB_INFLATE ++- tristate +++ tristate "ZLIB inflate support" ++ ++ config ZLIB_DEFLATE ++- tristate +++ tristate "ZLIB deflate support" ++ ++ config LZO_COMPRESS ++- tristate +++ tristate "LZO compress support" ++ ++ config LZO_DECOMPRESS ++- tristate +++ tristate "LZO decompress support" ++ ++ source "lib/xz/Kconfig" ++ +Index: patches-3.3/020-ssb_update.patch +=================================================================== +--- patches-3.3/020-ssb_update.patch (Revision 35298) ++++ patches-3.3/020-ssb_update.patch (Revision 37768) +@@ -1,6 +1,31 @@ ++--- a/drivers/ssb/Kconfig +++++ b/drivers/ssb/Kconfig ++@@ -160,4 +160,12 @@ config SSB_DRIVER_GIGE ++ ++ If unsure, say N ++ +++config SSB_DRIVER_GPIO +++ bool "SSB GPIO driver" +++ depends on SSB && GPIOLIB +++ help +++ Driver to provide access to the GPIO pins on the bus. +++ +++ If unsure, say N +++ ++ endmenu ++--- a/drivers/ssb/Makefile +++++ b/drivers/ssb/Makefile ++@@ -15,6 +15,7 @@ ssb-$(CONFIG_SSB_DRIVER_MIPS) += driver ++ ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o ++ ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o ++ ssb-$(CONFIG_SSB_DRIVER_GIGE) += driver_gige.o +++ssb-$(CONFIG_SSB_DRIVER_GPIO) += driver_gpio.o ++ ++ # b43 pci-ssb-bridge driver ++ # Not strictly a part of SSB, but kept here for convenience + --- a/drivers/ssb/b43_pci_bridge.c + +++ b/drivers/ssb/b43_pci_bridge.c +-@@ -29,11 +29,14 @@ static const struct pci_device_id b43_pc ++@@ -29,11 +29,15 @@ static const struct pci_device_id b43_pc + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) }, +@@ -12,9 +37,265 @@ + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4329) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432b) }, + + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432c) }, +++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4350) }, + { 0, }, + }; + MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl); ++--- a/drivers/ssb/driver_chipcommon.c +++++ b/drivers/ssb/driver_chipcommon.c ++@@ -4,6 +4,7 @@ ++ * ++ * Copyright 2005, Broadcom Corporation ++ * Copyright 2006, 2007, Michael Buesch +++ * Copyright 2012, Hauke Mehrtens ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++@@ -12,6 +13,7 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include "ssb_private.h" ++ ++@@ -280,13 +282,79 @@ static void calc_fast_powerup_delay(stru ++ cc->fast_pwrup_delay = tmp; ++ } ++ +++static u32 ssb_chipco_alp_clock(struct ssb_chipcommon *cc) +++{ +++ if (cc->capabilities & SSB_CHIPCO_CAP_PMU) +++ return ssb_pmu_get_alp_clock(cc); +++ +++ return 20000000; +++} +++ +++static u32 ssb_chipco_watchdog_get_max_timer(struct ssb_chipcommon *cc) +++{ +++ u32 nb; +++ +++ if (cc->capabilities & SSB_CHIPCO_CAP_PMU) { +++ if (cc->dev->id.revision < 26) +++ nb = 16; +++ else +++ nb = (cc->dev->id.revision >= 37) ? 32 : 24; +++ } else { +++ nb = 28; +++ } +++ if (nb == 32) +++ return 0xffffffff; +++ else +++ return (1 << nb) - 1; +++} +++ +++u32 ssb_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks) +++{ +++ struct ssb_chipcommon *cc = bcm47xx_wdt_get_drvdata(wdt); +++ +++ if (cc->dev->bus->bustype != SSB_BUSTYPE_SSB) +++ return 0; +++ +++ return ssb_chipco_watchdog_timer_set(cc, ticks); +++} +++ +++u32 ssb_chipco_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms) +++{ +++ struct ssb_chipcommon *cc = bcm47xx_wdt_get_drvdata(wdt); +++ u32 ticks; +++ +++ if (cc->dev->bus->bustype != SSB_BUSTYPE_SSB) +++ return 0; +++ +++ ticks = ssb_chipco_watchdog_timer_set(cc, cc->ticks_per_ms * ms); +++ return ticks / cc->ticks_per_ms; +++} +++ +++static int ssb_chipco_watchdog_ticks_per_ms(struct ssb_chipcommon *cc) +++{ +++ struct ssb_bus *bus = cc->dev->bus; +++ +++ if (cc->capabilities & SSB_CHIPCO_CAP_PMU) { +++ /* based on 32KHz ILP clock */ +++ return 32; +++ } else { +++ if (cc->dev->id.revision < 18) +++ return ssb_clockspeed(bus) / 1000; +++ else +++ return ssb_chipco_alp_clock(cc) / 1000; +++ } +++} +++ ++ void ssb_chipcommon_init(struct ssb_chipcommon *cc) ++ { ++ if (!cc->dev) ++ return; /* We don't have a ChipCommon */ +++ +++ spin_lock_init(&cc->gpio_lock); +++ ++ if (cc->dev->id.revision >= 11) ++ cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT); ++- ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status); +++ ssb_dbg("chipcommon status is 0x%x\n", cc->status); ++ ++ if (cc->dev->id.revision >= 20) { ++ chipco_write32(cc, SSB_CHIPCO_GPIOPULLUP, 0); ++@@ -297,6 +365,11 @@ void ssb_chipcommon_init(struct ssb_chip ++ chipco_powercontrol_init(cc); ++ ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST); ++ calc_fast_powerup_delay(cc); +++ +++ if (cc->dev->bus->bustype == SSB_BUSTYPE_SSB) { +++ cc->ticks_per_ms = ssb_chipco_watchdog_ticks_per_ms(cc); +++ cc->max_timer_ms = ssb_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms; +++ } ++ } ++ ++ void ssb_chipco_suspend(struct ssb_chipcommon *cc) ++@@ -395,10 +468,27 @@ void ssb_chipco_timing_init(struct ssb_c ++ } ++ ++ /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */ ++-void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks) +++u32 ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks) ++ { ++- /* instant NMI */ ++- chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks); +++ u32 maxt; +++ enum ssb_clkmode clkmode; +++ +++ maxt = ssb_chipco_watchdog_get_max_timer(cc); +++ if (cc->capabilities & SSB_CHIPCO_CAP_PMU) { +++ if (ticks == 1) +++ ticks = 2; +++ else if (ticks > maxt) +++ ticks = maxt; +++ chipco_write32(cc, SSB_CHIPCO_PMU_WATCHDOG, ticks); +++ } else { +++ clkmode = ticks ? SSB_CLKMODE_FAST : SSB_CLKMODE_DYNAMIC; +++ ssb_chipco_set_clockmode(cc, clkmode); +++ if (ticks > maxt) +++ ticks = maxt; +++ /* instant NMI */ +++ chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks); +++ } +++ return ticks; ++ } ++ ++ void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value) ++@@ -418,28 +508,93 @@ u32 ssb_chipco_gpio_in(struct ssb_chipco ++ ++ u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value) ++ { ++- return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value); +++ unsigned long flags; +++ u32 res = 0; +++ +++ spin_lock_irqsave(&cc->gpio_lock, flags); +++ res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value); +++ spin_unlock_irqrestore(&cc->gpio_lock, flags); +++ +++ return res; ++ } ++ ++ u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value) ++ { ++- return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value); +++ unsigned long flags; +++ u32 res = 0; +++ +++ spin_lock_irqsave(&cc->gpio_lock, flags); +++ res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value); +++ spin_unlock_irqrestore(&cc->gpio_lock, flags); +++ +++ return res; ++ } ++ ++ u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value) ++ { ++- return chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value); +++ unsigned long flags; +++ u32 res = 0; +++ +++ spin_lock_irqsave(&cc->gpio_lock, flags); +++ res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value); +++ spin_unlock_irqrestore(&cc->gpio_lock, flags); +++ +++ return res; ++ } ++ EXPORT_SYMBOL(ssb_chipco_gpio_control); ++ ++ u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value) ++ { ++- return chipco_write32_masked(cc, SSB_CHIPCO_GPIOIRQ, mask, value); +++ unsigned long flags; +++ u32 res = 0; +++ +++ spin_lock_irqsave(&cc->gpio_lock, flags); +++ res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOIRQ, mask, value); +++ spin_unlock_irqrestore(&cc->gpio_lock, flags); +++ +++ return res; ++ } ++ ++ u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value) ++ { ++- return chipco_write32_masked(cc, SSB_CHIPCO_GPIOPOL, mask, value); +++ unsigned long flags; +++ u32 res = 0; +++ +++ spin_lock_irqsave(&cc->gpio_lock, flags); +++ res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPOL, mask, value); +++ spin_unlock_irqrestore(&cc->gpio_lock, flags); +++ +++ return res; +++} +++ +++u32 ssb_chipco_gpio_pullup(struct ssb_chipcommon *cc, u32 mask, u32 value) +++{ +++ unsigned long flags; +++ u32 res = 0; +++ +++ if (cc->dev->id.revision < 20) +++ return 0xffffffff; +++ +++ spin_lock_irqsave(&cc->gpio_lock, flags); +++ res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPULLUP, mask, value); +++ spin_unlock_irqrestore(&cc->gpio_lock, flags); +++ +++ return res; +++} +++ +++u32 ssb_chipco_gpio_pulldown(struct ssb_chipcommon *cc, u32 mask, u32 value) +++{ +++ unsigned long flags; +++ u32 res = 0; +++ +++ if (cc->dev->id.revision < 20) +++ return 0xffffffff; +++ +++ spin_lock_irqsave(&cc->gpio_lock, flags); +++ res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPULLDOWN, mask, value); +++ spin_unlock_irqrestore(&cc->gpio_lock, flags); +++ +++ return res; ++ } ++ ++ #ifdef CONFIG_SSB_SERIAL ++@@ -473,12 +628,7 @@ int ssb_chipco_serial_init(struct ssb_ch ++ chipco_read32(cc, SSB_CHIPCO_CORECTL) ++ | SSB_CHIPCO_CORECTL_UARTCLK0); ++ } else if ((ccrev >= 11) && (ccrev != 15)) { ++- /* Fixed ALP clock */ ++- baud_base = 20000000; ++- if (cc->capabilities & SSB_CHIPCO_CAP_PMU) { ++- /* FIXME: baud_base is different for devices with a PMU */ ++- SSB_WARN_ON(1); ++- } +++ baud_base = ssb_chipco_alp_clock(cc); ++ div = 1; ++ if (ccrev >= 21) { ++ /* Turn off UART clock before switching clocksource. */ + --- a/drivers/ssb/driver_chipcommon_pmu.c + +++ b/drivers/ssb/driver_chipcommon_pmu.c + @@ -13,6 +13,9 @@ +@@ -22,7 +303,7 @@ + #include + #include + +#ifdef CONFIG_BCM47XX +-+#include +++#include + +#endif + + #include "ssb_private.h" +@@ -38,6 +319,46 @@ + if (crystalfreq) + e = pmu0_plltab_find_entry(crystalfreq); + if (!e) ++@@ -111,8 +110,8 @@ static void ssb_pmu0_pllinit_r0(struct s ++ return; ++ } ++ ++- ssb_printk(KERN_INFO PFX "Programming PLL to %u.%03u MHz\n", ++- (crystalfreq / 1000), (crystalfreq % 1000)); +++ ssb_info("Programming PLL to %u.%03u MHz\n", +++ crystalfreq / 1000, crystalfreq % 1000); ++ ++ /* First turn the PLL off. */ ++ switch (bus->chip_id) { ++@@ -139,7 +138,7 @@ static void ssb_pmu0_pllinit_r0(struct s ++ } ++ tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); ++ if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT) ++- ssb_printk(KERN_EMERG PFX "Failed to turn the PLL off!\n"); +++ ssb_emerg("Failed to turn the PLL off!\n"); ++ ++ /* Set PDIV in PLL control 0. */ ++ pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL0); ++@@ -250,8 +249,8 @@ static void ssb_pmu1_pllinit_r0(struct s ++ return; ++ } ++ ++- ssb_printk(KERN_INFO PFX "Programming PLL to %u.%03u MHz\n", ++- (crystalfreq / 1000), (crystalfreq % 1000)); +++ ssb_info("Programming PLL to %u.%03u MHz\n", +++ crystalfreq / 1000, crystalfreq % 1000); ++ ++ /* First turn the PLL off. */ ++ switch (bus->chip_id) { ++@@ -276,7 +275,7 @@ static void ssb_pmu1_pllinit_r0(struct s ++ } ++ tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); ++ if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT) ++- ssb_printk(KERN_EMERG PFX "Failed to turn the PLL off!\n"); +++ ssb_emerg("Failed to turn the PLL off!\n"); ++ ++ /* Set p1div and p2div. */ ++ pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL0); + @@ -321,7 +320,11 @@ static void ssb_pmu_pll_init(struct ssb_ + u32 crystalfreq = 0; /* in kHz. 0 = keep default freq. */ + +@@ -63,11 +384,83 @@ + ssb_pmu0_pllinit_r0(cc, crystalfreq); + break; + case 0x4322: +-@@ -607,3 +614,34 @@ void ssb_pmu_set_ldo_paref(struct ssb_ch ++@@ -339,10 +346,11 @@ static void ssb_pmu_pll_init(struct ssb_ ++ chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, 0x380005C0); ++ } ++ break; +++ case 43222: +++ break; ++ default: ++- ssb_printk(KERN_ERR PFX ++- "ERROR: PLL init unknown for device %04X\n", ++- bus->chip_id); +++ ssb_err("ERROR: PLL init unknown for device %04X\n", +++ bus->chip_id); ++ } ++ } + ++@@ -427,6 +435,7 @@ static void ssb_pmu_resources_init(struc ++ min_msk = 0xCBB; ++ break; ++ case 0x4322: +++ case 43222: ++ /* We keep the default settings: ++ * min_msk = 0xCBB ++ * max_msk = 0x7FFFF ++@@ -462,9 +471,8 @@ static void ssb_pmu_resources_init(struc ++ max_msk = 0xFFFFF; ++ break; ++ default: ++- ssb_printk(KERN_ERR PFX ++- "ERROR: PMU resource config unknown for device %04X\n", ++- bus->chip_id); +++ ssb_err("ERROR: PMU resource config unknown for device %04X\n", +++ bus->chip_id); ++ } ++ ++ if (updown_tab) { ++@@ -516,8 +524,8 @@ void ssb_pmu_init(struct ssb_chipcommon ++ pmucap = chipco_read32(cc, SSB_CHIPCO_PMU_CAP); ++ cc->pmu.rev = (pmucap & SSB_CHIPCO_PMU_CAP_REVISION); ++ ++- ssb_dprintk(KERN_DEBUG PFX "Found rev %u PMU (capabilities 0x%08X)\n", ++- cc->pmu.rev, pmucap); +++ ssb_dbg("Found rev %u PMU (capabilities 0x%08X)\n", +++ cc->pmu.rev, pmucap); ++ ++ if (cc->pmu.rev == 1) ++ chipco_mask32(cc, SSB_CHIPCO_PMU_CTL, ++@@ -607,3 +615,102 @@ void ssb_pmu_set_ldo_paref(struct ssb_ch ++ + EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage); + EXPORT_SYMBOL(ssb_pmu_set_ldo_paref); + + +++static u32 ssb_pmu_get_alp_clock_clk0(struct ssb_chipcommon *cc) +++{ +++ u32 crystalfreq; +++ const struct pmu0_plltab_entry *e = NULL; +++ +++ crystalfreq = chipco_read32(cc, SSB_CHIPCO_PMU_CTL) & +++ SSB_CHIPCO_PMU_CTL_XTALFREQ >> SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT; +++ e = pmu0_plltab_find_entry(crystalfreq); +++ BUG_ON(!e); +++ return e->freq * 1000; +++} +++ +++u32 ssb_pmu_get_alp_clock(struct ssb_chipcommon *cc) +++{ +++ struct ssb_bus *bus = cc->dev->bus; +++ +++ switch (bus->chip_id) { +++ case 0x5354: +++ ssb_pmu_get_alp_clock_clk0(cc); +++ default: +++ ssb_err("ERROR: PMU alp clock unknown for device %04X\n", +++ bus->chip_id); +++ return 0; +++ } +++} +++ + +u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc) + +{ + + struct ssb_bus *bus = cc->dev->bus; +@@ -77,9 +470,8 @@ + + /* 5354 chip uses a non programmable PLL of frequency 240MHz */ + + return 240000000; + + default: +-+ ssb_printk(KERN_ERR PFX +-+ "ERROR: PMU cpu clock unknown for device %04X\n", +-+ bus->chip_id); +++ ssb_err("ERROR: PMU cpu clock unknown for device %04X\n", +++ bus->chip_id); + + return 0; + + } + +} +@@ -92,27 +484,596 @@ + + case 0x5354: + + return 120000000; + + default: +-+ ssb_printk(KERN_ERR PFX +-+ "ERROR: PMU controlclock unknown for device %04X\n", +-+ bus->chip_id); +++ ssb_err("ERROR: PMU controlclock unknown for device %04X\n", +++ bus->chip_id); + + return 0; + + } + +} +++ +++void ssb_pmu_spuravoid_pllupdate(struct ssb_chipcommon *cc, int spuravoid) +++{ +++ u32 pmu_ctl = 0; +++ +++ switch (cc->dev->bus->chip_id) { +++ case 0x4322: +++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, 0x11100070); +++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL1, 0x1014140a); +++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, 0x88888854); +++ if (spuravoid == 1) +++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x05201828); +++ else +++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x05001828); +++ pmu_ctl = SSB_CHIPCO_PMU_CTL_PLL_UPD; +++ break; +++ case 43222: +++ if (spuravoid == 1) { +++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, 0x11500008); +++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL1, 0x0C000C06); +++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x0F600a08); +++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL3, 0x00000000); +++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL4, 0x2001E920); +++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, 0x88888815); +++ } else { +++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, 0x11100008); +++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL1, 0x0c000c06); +++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x03000a08); +++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL3, 0x00000000); +++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL4, 0x200005c0); +++ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, 0x88888855); +++ } +++ pmu_ctl = SSB_CHIPCO_PMU_CTL_PLL_UPD; +++ break; +++ default: +++ ssb_printk(KERN_ERR PFX +++ "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n", +++ cc->dev->bus->chip_id); +++ return; +++ } +++ +++ chipco_set32(cc, SSB_CHIPCO_PMU_CTL, pmu_ctl); +++} +++EXPORT_SYMBOL_GPL(ssb_pmu_spuravoid_pllupdate); ++--- a/drivers/ssb/driver_extif.c +++++ b/drivers/ssb/driver_extif.c ++@@ -112,10 +112,37 @@ void ssb_extif_get_clockcontrol(struct s ++ *m = extif_read32(extif, SSB_EXTIF_CLOCK_SB); ++ } ++ ++-void ssb_extif_watchdog_timer_set(struct ssb_extif *extif, ++- u32 ticks) +++u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks) ++ { +++ struct ssb_extif *extif = bcm47xx_wdt_get_drvdata(wdt); +++ +++ return ssb_extif_watchdog_timer_set(extif, ticks); +++} +++ +++u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms) +++{ +++ struct ssb_extif *extif = bcm47xx_wdt_get_drvdata(wdt); +++ u32 ticks = (SSB_EXTIF_WATCHDOG_CLK / 1000) * ms; +++ +++ ticks = ssb_extif_watchdog_timer_set(extif, ticks); +++ +++ return (ticks * 1000) / SSB_EXTIF_WATCHDOG_CLK; +++} +++ +++u32 ssb_extif_watchdog_timer_set(struct ssb_extif *extif, u32 ticks) +++{ +++ if (ticks > SSB_EXTIF_WATCHDOG_MAX_TIMER) +++ ticks = SSB_EXTIF_WATCHDOG_MAX_TIMER; ++ extif_write32(extif, SSB_EXTIF_WATCHDOG, ticks); +++ +++ return ticks; +++} +++ +++void ssb_extif_init(struct ssb_extif *extif) +++{ +++ if (!extif->dev) +++ return; /* We don't have a Extif core */ +++ spin_lock_init(&extif->gpio_lock); ++ } ++ ++ u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask) ++@@ -125,22 +152,50 @@ u32 ssb_extif_gpio_in(struct ssb_extif * ++ ++ u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value) ++ { ++- return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0), +++ unsigned long flags; +++ u32 res = 0; +++ +++ spin_lock_irqsave(&extif->gpio_lock, flags); +++ res = extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0), ++ mask, value); +++ spin_unlock_irqrestore(&extif->gpio_lock, flags); +++ +++ return res; ++ } ++ ++ u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value) ++ { ++- return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0), +++ unsigned long flags; +++ u32 res = 0; +++ +++ spin_lock_irqsave(&extif->gpio_lock, flags); +++ res = extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0), ++ mask, value); +++ spin_unlock_irqrestore(&extif->gpio_lock, flags); +++ +++ return res; ++ } ++ ++ u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask, u32 value) ++ { ++- return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTPOL, mask, value); +++ unsigned long flags; +++ u32 res = 0; +++ +++ spin_lock_irqsave(&extif->gpio_lock, flags); +++ res = extif_write32_masked(extif, SSB_EXTIF_GPIO_INTPOL, mask, value); +++ spin_unlock_irqrestore(&extif->gpio_lock, flags); +++ +++ return res; ++ } ++ ++ u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask, u32 value) ++ { ++- return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTMASK, mask, value); +++ unsigned long flags; +++ u32 res = 0; +++ +++ spin_lock_irqsave(&extif->gpio_lock, flags); +++ res = extif_write32_masked(extif, SSB_EXTIF_GPIO_INTMASK, mask, value); +++ spin_unlock_irqrestore(&extif->gpio_lock, flags); +++ +++ return res; ++ } ++--- /dev/null +++++ b/drivers/ssb/driver_gpio.c ++@@ -0,0 +1,210 @@ +++/* +++ * Sonics Silicon Backplane +++ * GPIO driver +++ * +++ * Copyright 2011, Broadcom Corporation +++ * Copyright 2012, Hauke Mehrtens +++ * +++ * Licensed under the GNU/GPL. See COPYING for details. +++ */ +++ +++#include +++#include +++#include +++ +++#include "ssb_private.h" +++ +++static struct ssb_bus *ssb_gpio_get_bus(struct gpio_chip *chip) +++{ +++ return container_of(chip, struct ssb_bus, gpio); +++} +++ +++static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned gpio) +++{ +++ struct ssb_bus *bus = ssb_gpio_get_bus(chip); +++ +++ return !!ssb_chipco_gpio_in(&bus->chipco, 1 << gpio); +++} +++ +++static void ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned gpio, +++ int value) +++{ +++ struct ssb_bus *bus = ssb_gpio_get_bus(chip); +++ +++ ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0); +++} +++ +++static int ssb_gpio_chipco_direction_input(struct gpio_chip *chip, +++ unsigned gpio) +++{ +++ struct ssb_bus *bus = ssb_gpio_get_bus(chip); +++ +++ ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 0); +++ return 0; +++} +++ +++static int ssb_gpio_chipco_direction_output(struct gpio_chip *chip, +++ unsigned gpio, int value) +++{ +++ struct ssb_bus *bus = ssb_gpio_get_bus(chip); +++ +++ ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 1 << gpio); +++ ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0); +++ return 0; +++} +++ +++static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned gpio) +++{ +++ struct ssb_bus *bus = ssb_gpio_get_bus(chip); +++ +++ ssb_chipco_gpio_control(&bus->chipco, 1 << gpio, 0); +++ /* clear pulldown */ +++ ssb_chipco_gpio_pulldown(&bus->chipco, 1 << gpio, 0); +++ /* Set pullup */ +++ ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 1 << gpio); +++ +++ return 0; +++} +++ +++static void ssb_gpio_chipco_free(struct gpio_chip *chip, unsigned gpio) +++{ +++ struct ssb_bus *bus = ssb_gpio_get_bus(chip); +++ +++ /* clear pullup */ +++ ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 0); +++} +++ +++static int ssb_gpio_chipco_to_irq(struct gpio_chip *chip, unsigned gpio) +++{ +++ struct ssb_bus *bus = ssb_gpio_get_bus(chip); +++ +++ if (bus->bustype == SSB_BUSTYPE_SSB) +++ return ssb_mips_irq(bus->chipco.dev) + 2; +++ else +++ return -EINVAL; +++} +++ +++static int ssb_gpio_chipco_init(struct ssb_bus *bus) +++{ +++ struct gpio_chip *chip = &bus->gpio; +++ +++ chip->label = "ssb_chipco_gpio"; +++ chip->owner = THIS_MODULE; +++ chip->request = ssb_gpio_chipco_request; +++ chip->free = ssb_gpio_chipco_free; +++ chip->get = ssb_gpio_chipco_get_value; +++ chip->set = ssb_gpio_chipco_set_value; +++ chip->direction_input = ssb_gpio_chipco_direction_input; +++ chip->direction_output = ssb_gpio_chipco_direction_output; +++ chip->to_irq = ssb_gpio_chipco_to_irq; +++ chip->ngpio = 16; +++ /* There is just one SoC in one device and its GPIO addresses should be +++ * deterministic to address them more easily. The other buses could get +++ * a random base number. */ +++ if (bus->bustype == SSB_BUSTYPE_SSB) +++ chip->base = 0; +++ else +++ chip->base = -1; +++ +++ return gpiochip_add(chip); +++} +++ +++#ifdef CONFIG_SSB_DRIVER_EXTIF +++ +++static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio) +++{ +++ struct ssb_bus *bus = ssb_gpio_get_bus(chip); +++ +++ return !!ssb_extif_gpio_in(&bus->extif, 1 << gpio); +++} +++ +++static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned gpio, +++ int value) +++{ +++ struct ssb_bus *bus = ssb_gpio_get_bus(chip); +++ +++ ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0); +++} +++ +++static int ssb_gpio_extif_direction_input(struct gpio_chip *chip, +++ unsigned gpio) +++{ +++ struct ssb_bus *bus = ssb_gpio_get_bus(chip); +++ +++ ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 0); +++ return 0; +++} +++ +++static int ssb_gpio_extif_direction_output(struct gpio_chip *chip, +++ unsigned gpio, int value) +++{ +++ struct ssb_bus *bus = ssb_gpio_get_bus(chip); +++ +++ ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 1 << gpio); +++ ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0); +++ return 0; +++} +++ +++static int ssb_gpio_extif_to_irq(struct gpio_chip *chip, unsigned gpio) +++{ +++ struct ssb_bus *bus = ssb_gpio_get_bus(chip); +++ +++ if (bus->bustype == SSB_BUSTYPE_SSB) +++ return ssb_mips_irq(bus->extif.dev) + 2; +++ else +++ return -EINVAL; +++} +++ +++static int ssb_gpio_extif_init(struct ssb_bus *bus) +++{ +++ struct gpio_chip *chip = &bus->gpio; +++ +++ chip->label = "ssb_extif_gpio"; +++ chip->owner = THIS_MODULE; +++ chip->get = ssb_gpio_extif_get_value; +++ chip->set = ssb_gpio_extif_set_value; +++ chip->direction_input = ssb_gpio_extif_direction_input; +++ chip->direction_output = ssb_gpio_extif_direction_output; +++ chip->to_irq = ssb_gpio_extif_to_irq; +++ chip->ngpio = 5; +++ /* There is just one SoC in one device and its GPIO addresses should be +++ * deterministic to address them more easily. The other buses could get +++ * a random base number. */ +++ if (bus->bustype == SSB_BUSTYPE_SSB) +++ chip->base = 0; +++ else +++ chip->base = -1; +++ +++ return gpiochip_add(chip); +++} +++ +++#else +++static int ssb_gpio_extif_init(struct ssb_bus *bus) +++{ +++ return -ENOTSUPP; +++} +++#endif +++ +++int ssb_gpio_init(struct ssb_bus *bus) +++{ +++ if (ssb_chipco_available(&bus->chipco)) +++ return ssb_gpio_chipco_init(bus); +++ else if (ssb_extif_available(&bus->extif)) +++ return ssb_gpio_extif_init(bus); +++ else +++ SSB_WARN_ON(1); +++ +++ return -1; +++} +++ +++int ssb_gpio_unregister(struct ssb_bus *bus) +++{ +++ if (ssb_chipco_available(&bus->chipco) || +++ ssb_extif_available(&bus->extif)) { +++ return gpiochip_remove(&bus->gpio); +++ } else { +++ SSB_WARN_ON(1); +++ } +++ +++ return -1; +++} + --- a/drivers/ssb/driver_mipscore.c + +++ b/drivers/ssb/driver_mipscore.c +-@@ -208,6 +208,9 @@ u32 ssb_cpu_clock(struct ssb_mipscore *m ++@@ -17,7 +17,6 @@ ++ ++ #include "ssb_private.h" ++ ++- ++ static inline u32 mips_read32(struct ssb_mipscore *mcore, ++ u16 offset) ++ { ++@@ -147,21 +146,22 @@ static void set_irq(struct ssb_device *d ++ irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]); ++ ssb_write32(mdev, SSB_IPSFLAG, irqflag); ++ } ++- ssb_dprintk(KERN_INFO PFX ++- "set_irq: core 0x%04x, irq %d => %d\n", ++- dev->id.coreid, oldirq+2, irq+2); +++ ssb_dbg("set_irq: core 0x%04x, irq %d => %d\n", +++ dev->id.coreid, oldirq+2, irq+2); ++ } ++ ++ static void print_irq(struct ssb_device *dev, unsigned int irq) ++ { ++- int i; ++ static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; ++- ssb_dprintk(KERN_INFO PFX ++- "core 0x%04x, irq :", dev->id.coreid); ++- for (i = 0; i <= 6; i++) { ++- ssb_dprintk(" %s%s", irq_name[i], i==irq?"*":" "); ++- } ++- ssb_dprintk("\n"); +++ ssb_dbg("core 0x%04x, irq : %s%s %s%s %s%s %s%s %s%s %s%s %s%s\n", +++ dev->id.coreid, +++ irq_name[0], irq == 0 ? "*" : " ", +++ irq_name[1], irq == 1 ? "*" : " ", +++ irq_name[2], irq == 2 ? "*" : " ", +++ irq_name[3], irq == 3 ? "*" : " ", +++ irq_name[4], irq == 4 ? "*" : " ", +++ irq_name[5], irq == 5 ? "*" : " ", +++ irq_name[6], irq == 6 ? "*" : " "); ++ } ++ ++ static void dump_irq(struct ssb_bus *bus) ++@@ -178,9 +178,9 @@ static void ssb_mips_serial_init(struct ++ { + struct ssb_bus *bus = mcore->dev->bus; ++ ++- if (bus->extif.dev) +++ if (ssb_extif_available(&bus->extif)) ++ mcore->nr_serial_ports = ssb_extif_serial_init(&bus->extif, mcore->serial_ports); ++- else if (bus->chipco.dev) +++ else if (ssb_chipco_available(&bus->chipco)) ++ mcore->nr_serial_ports = ssb_chipco_serial_init(&bus->chipco, mcore->serial_ports); ++ else ++ mcore->nr_serial_ports = 0; ++@@ -191,7 +191,7 @@ static void ssb_mips_flash_detect(struct ++ struct ssb_bus *bus = mcore->dev->bus; ++ ++ mcore->flash_buswidth = 2; ++- if (bus->chipco.dev) { +++ if (ssb_chipco_available(&bus->chipco)) { ++ mcore->flash_window = 0x1c000000; ++ mcore->flash_window_size = 0x02000000; ++ if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG) ++@@ -208,9 +208,12 @@ u32 ssb_cpu_clock(struct ssb_mipscore *m ++ struct ssb_bus *bus = mcore->dev->bus; + u32 pll_type, n, m, rate = 0; + ++- if (bus->extif.dev) { + + if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU) + + return ssb_pmu_get_cpu_clock(&bus->chipco); + + +- if (bus->extif.dev) { +++ if (ssb_extif_available(&bus->extif)) { + ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m); +- } else if (bus->chipco.dev) { ++- } else if (bus->chipco.dev) { +++ } else if (ssb_chipco_available(&bus->chipco)) { ++ ssb_chipco_get_clockcpu(&bus->chipco, &pll_type, &n, &m); ++ } else ++ return 0; ++@@ -238,7 +241,7 @@ void ssb_mipscore_init(struct ssb_mipsco ++ if (!mcore->dev) ++ return; /* We don't have a MIPS core */ ++ ++- ssb_dprintk(KERN_INFO PFX "Initializing MIPS core...\n"); +++ ssb_dbg("Initializing MIPS core...\n"); ++ ++ bus = mcore->dev->bus; ++ hz = ssb_clockspeed(bus); ++@@ -246,9 +249,9 @@ void ssb_mipscore_init(struct ssb_mipsco ++ hz = 100000000; ++ ns = 1000000000 / hz; ++ ++- if (bus->extif.dev) +++ if (ssb_extif_available(&bus->extif)) ++ ssb_extif_timing_init(&bus->extif, ns); ++- else if (bus->chipco.dev) +++ else if (ssb_chipco_available(&bus->chipco)) ++ ssb_chipco_timing_init(&bus->chipco, ns); ++ ++ /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */ ++@@ -286,7 +289,7 @@ void ssb_mipscore_init(struct ssb_mipsco ++ break; ++ } ++ } ++- ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n"); +++ ssb_dbg("after irq reconfiguration\n"); ++ dump_irq(bus); ++ ++ ssb_mips_serial_init(mcore); ++--- a/drivers/ssb/driver_pcicore.c +++++ b/drivers/ssb/driver_pcicore.c ++@@ -263,8 +263,7 @@ int ssb_pcicore_plat_dev_init(struct pci ++ return -ENODEV; ++ } ++ ++- ssb_printk(KERN_INFO "PCI: Fixing up device %s\n", ++- pci_name(d)); +++ ssb_info("PCI: Fixing up device %s\n", pci_name(d)); ++ ++ /* Fix up interrupt lines */ ++ d->irq = ssb_mips_irq(extpci_core->dev) + 2; ++@@ -285,12 +284,12 @@ static void ssb_pcicore_fixup_pcibridge( ++ if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0) ++ return; ++ ++- ssb_printk(KERN_INFO "PCI: Fixing up bridge %s\n", pci_name(dev)); +++ ssb_info("PCI: Fixing up bridge %s\n", pci_name(dev)); ++ ++ /* Enable PCI bridge bus mastering and memory space */ ++ pci_set_master(dev); ++ if (pcibios_enable_device(dev, ~0) < 0) { ++- ssb_printk(KERN_ERR "PCI: SSB bridge enable failed\n"); +++ ssb_err("PCI: SSB bridge enable failed\n"); ++ return; ++ } ++ ++@@ -299,8 +298,8 @@ static void ssb_pcicore_fixup_pcibridge( ++ ++ /* Make sure our latency is high enough to handle the devices behind us */ ++ lat = 168; ++- ssb_printk(KERN_INFO "PCI: Fixing latency timer of device %s to %u\n", ++- pci_name(dev), lat); +++ ssb_info("PCI: Fixing latency timer of device %s to %u\n", +++ pci_name(dev), lat); ++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); ++ } ++ DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_pcicore_fixup_pcibridge); ++@@ -323,7 +322,7 @@ static void __devinit ssb_pcicore_init_h ++ return; ++ extpci_core = pc; ++ ++- ssb_dprintk(KERN_INFO PFX "PCIcore in host mode found\n"); +++ ssb_dbg("PCIcore in host mode found\n"); ++ /* Reset devices on the external PCI bus */ ++ val = SSB_PCICORE_CTL_RST_OE; ++ val |= SSB_PCICORE_CTL_CLK_OE; ++@@ -338,7 +337,7 @@ static void __devinit ssb_pcicore_init_h ++ udelay(1); /* Assertion time demanded by the PCI standard */ ++ ++ if (pc->dev->bus->has_cardbus_slot) { ++- ssb_dprintk(KERN_INFO PFX "CardBus slot detected\n"); +++ ssb_dbg("CardBus slot detected\n"); ++ pc->cardbusmode = 1; ++ /* GPIO 1 resets the bridge */ ++ ssb_gpio_out(pc->dev->bus, 1, 1); ++--- a/drivers/ssb/embedded.c +++++ b/drivers/ssb/embedded.c ++@@ -4,11 +4,13 @@ ++ * ++ * Copyright 2005-2008, Broadcom Corporation ++ * Copyright 2006-2008, Michael Buesch +++ * Copyright 2012, Hauke Mehrtens ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++ #include +++#include ++ #include ++ #include ++ #include ++@@ -32,6 +34,38 @@ int ssb_watchdog_timer_set(struct ssb_bu ++ } ++ EXPORT_SYMBOL(ssb_watchdog_timer_set); ++ +++int ssb_watchdog_register(struct ssb_bus *bus) +++{ +++ struct bcm47xx_wdt wdt = {}; +++ struct platform_device *pdev; +++ +++ if (ssb_chipco_available(&bus->chipco)) { +++ wdt.driver_data = &bus->chipco; +++ wdt.timer_set = ssb_chipco_watchdog_timer_set_wdt; +++ wdt.timer_set_ms = ssb_chipco_watchdog_timer_set_ms; +++ wdt.max_timer_ms = bus->chipco.max_timer_ms; +++ } else if (ssb_extif_available(&bus->extif)) { +++ wdt.driver_data = &bus->extif; +++ wdt.timer_set = ssb_extif_watchdog_timer_set_wdt; +++ wdt.timer_set_ms = ssb_extif_watchdog_timer_set_ms; +++ wdt.max_timer_ms = SSB_EXTIF_WATCHDOG_MAX_TIMER_MS; +++ } else { +++ return -ENODEV; +++ } +++ +++ pdev = platform_device_register_data(NULL, "bcm47xx-wdt", +++ bus->busnumber, &wdt, +++ sizeof(wdt)); +++ if (IS_ERR(pdev)) { +++ ssb_dbg("can not register watchdog device, err: %li\n", +++ PTR_ERR(pdev)); +++ return PTR_ERR(pdev); +++ } +++ +++ bus->watchdog = pdev; +++ return 0; +++} +++ ++ u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask) ++ { ++ unsigned long flags; + --- a/drivers/ssb/main.c + +++ b/drivers/ssb/main.c +-@@ -140,19 +140,6 @@ static void ssb_device_put(struct ssb_de ++@@ -13,6 +13,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ #include ++ #include ++@@ -140,19 +141,6 @@ static void ssb_device_put(struct ssb_de + put_device(dev->dev); + } + +@@ -132,7 +1093,7 @@ + static int ssb_device_resume(struct device *dev) + { + struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); +-@@ -250,11 +237,9 @@ int ssb_devices_freeze(struct ssb_bus *b ++@@ -250,11 +238,9 @@ int ssb_devices_freeze(struct ssb_bus *b + ssb_device_put(sdev); + continue; + } +@@ -146,15 +1107,138 @@ + sdrv->remove(sdev); + ctx->device_frozen[i] = 1; + } +-@@ -293,7 +278,6 @@ int ssb_devices_thaw(struct ssb_freeze_c +- dev_name(sdev->dev)); ++@@ -289,11 +275,10 @@ int ssb_devices_thaw(struct ssb_freeze_c ++ ++ err = sdrv->probe(sdev, &sdev->id); ++ if (err) { ++- ssb_printk(KERN_ERR PFX "Failed to thaw device %s\n", ++- dev_name(sdev->dev)); +++ ssb_err("Failed to thaw device %s\n", +++ dev_name(sdev->dev)); + result = err; + } + - ssb_driver_put(sdrv); + ssb_device_put(sdev); + } + +-@@ -1094,6 +1078,9 @@ u32 ssb_clockspeed(struct ssb_bus *bus) ++@@ -449,10 +434,23 @@ static void ssb_devices_unregister(struc ++ if (sdev->dev) ++ device_unregister(sdev->dev); ++ } +++ +++#ifdef CONFIG_SSB_EMBEDDED +++ if (bus->bustype == SSB_BUSTYPE_SSB) +++ platform_device_unregister(bus->watchdog); +++#endif ++ } ++ ++ void ssb_bus_unregister(struct ssb_bus *bus) ++ { +++ int err; +++ +++ err = ssb_gpio_unregister(bus); +++ if (err == -EBUSY) +++ ssb_dbg("Some GPIOs are still in use\n"); +++ else if (err) +++ ssb_dbg("Can not unregister GPIO driver: %i\n", err); +++ ++ ssb_buses_lock(); ++ ssb_devices_unregister(bus); ++ list_del(&bus->list); ++@@ -498,8 +496,7 @@ static int ssb_devices_register(struct s ++ ++ devwrap = kzalloc(sizeof(*devwrap), GFP_KERNEL); ++ if (!devwrap) { ++- ssb_printk(KERN_ERR PFX ++- "Could not allocate device\n"); +++ ssb_err("Could not allocate device\n"); ++ err = -ENOMEM; ++ goto error; ++ } ++@@ -538,9 +535,7 @@ static int ssb_devices_register(struct s ++ sdev->dev = dev; ++ err = device_register(dev); ++ if (err) { ++- ssb_printk(KERN_ERR PFX ++- "Could not register %s\n", ++- dev_name(dev)); +++ ssb_err("Could not register %s\n", dev_name(dev)); ++ /* Set dev to NULL to not unregister ++ * dev on error unwinding. */ ++ sdev->dev = NULL; ++@@ -577,6 +572,8 @@ static int __devinit ssb_attach_queued_b ++ if (err) ++ goto error; ++ ssb_pcicore_init(&bus->pcicore); +++ if (bus->bustype == SSB_BUSTYPE_SSB) +++ ssb_watchdog_register(bus); ++ ssb_bus_may_powerdown(bus); ++ ++ err = ssb_devices_register(bus); ++@@ -812,7 +809,13 @@ static int __devinit ssb_bus_register(st ++ if (err) ++ goto err_pcmcia_exit; ++ ssb_chipcommon_init(&bus->chipco); +++ ssb_extif_init(&bus->extif); ++ ssb_mipscore_init(&bus->mipscore); +++ err = ssb_gpio_init(bus); +++ if (err == -ENOTSUPP) +++ ssb_dbg("GPIO driver not activated\n"); +++ else if (err) +++ ssb_dbg("Error registering GPIO driver: %i\n", err); ++ err = ssb_fetch_invariants(bus, get_invariants); ++ if (err) { ++ ssb_bus_may_powerdown(bus); ++@@ -863,11 +866,11 @@ int __devinit ssb_bus_pcibus_register(st ++ ++ err = ssb_bus_register(bus, ssb_pci_get_invariants, 0); ++ if (!err) { ++- ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on " ++- "PCI device %s\n", dev_name(&host_pci->dev)); +++ ssb_info("Sonics Silicon Backplane found on PCI device %s\n", +++ dev_name(&host_pci->dev)); ++ } else { ++- ssb_printk(KERN_ERR PFX "Failed to register PCI version" ++- " of SSB with error %d\n", err); +++ ssb_err("Failed to register PCI version of SSB with error %d\n", +++ err); ++ } ++ ++ return err; ++@@ -888,8 +891,8 @@ int __devinit ssb_bus_pcmciabus_register ++ ++ err = ssb_bus_register(bus, ssb_pcmcia_get_invariants, baseaddr); ++ if (!err) { ++- ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on " ++- "PCMCIA device %s\n", pcmcia_dev->devname); +++ ssb_info("Sonics Silicon Backplane found on PCMCIA device %s\n", +++ pcmcia_dev->devname); ++ } ++ ++ return err; ++@@ -911,8 +914,8 @@ int __devinit ssb_bus_sdiobus_register(s ++ ++ err = ssb_bus_register(bus, ssb_sdio_get_invariants, ~0); ++ if (!err) { ++- ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on " ++- "SDIO device %s\n", sdio_func_id(func)); +++ ssb_info("Sonics Silicon Backplane found on SDIO device %s\n", +++ sdio_func_id(func)); ++ } ++ ++ return err; ++@@ -931,8 +934,8 @@ int __devinit ssb_bus_ssbbus_register(st ++ ++ err = ssb_bus_register(bus, get_invariants, baseaddr); ++ if (!err) { ++- ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found at " ++- "address 0x%08lX\n", baseaddr); +++ ssb_info("Sonics Silicon Backplane found at address 0x%08lX\n", +++ baseaddr); ++ } ++ ++ return err; ++@@ -1094,6 +1097,9 @@ u32 ssb_clockspeed(struct ssb_bus *bus) + u32 plltype; + u32 clkctl_n, clkctl_m; + +@@ -164,9 +1248,78 @@ + if (ssb_extif_available(&bus->extif)) + ssb_extif_get_clockcontrol(&bus->extif, &plltype, + &clkctl_n, &clkctl_m); ++@@ -1131,8 +1137,7 @@ static u32 ssb_tmslow_reject_bitmask(str ++ case SSB_IDLOW_SSBREV_27: /* same here */ ++ return SSB_TMSLOW_REJECT; /* this is a guess */ ++ default: ++- printk(KERN_INFO "ssb: Backplane Revision 0x%.8X\n", rev); ++- WARN_ON(1); +++ WARN(1, KERN_INFO "ssb: Backplane Revision 0x%.8X\n", rev); ++ } ++ return (SSB_TMSLOW_REJECT | SSB_TMSLOW_REJECT_23); ++ } ++@@ -1324,7 +1329,7 @@ out: ++ #endif ++ return err; ++ error: ++- ssb_printk(KERN_ERR PFX "Bus powerdown failed\n"); +++ ssb_err("Bus powerdown failed\n"); ++ goto out; ++ } ++ EXPORT_SYMBOL(ssb_bus_may_powerdown); ++@@ -1347,7 +1352,7 @@ int ssb_bus_powerup(struct ssb_bus *bus, ++ ++ return 0; ++ error: ++- ssb_printk(KERN_ERR PFX "Bus powerup failed\n"); +++ ssb_err("Bus powerup failed\n"); ++ return err; ++ } ++ EXPORT_SYMBOL(ssb_bus_powerup); ++@@ -1455,15 +1460,13 @@ static int __init ssb_modinit(void) ++ ++ err = b43_pci_ssb_bridge_init(); ++ if (err) { ++- ssb_printk(KERN_ERR "Broadcom 43xx PCI-SSB-bridge " ++- "initialization failed\n"); +++ ssb_err("Broadcom 43xx PCI-SSB-bridge initialization failed\n"); ++ /* don't fail SSB init because of this */ ++ err = 0; ++ } ++ err = ssb_gige_init(); ++ if (err) { ++- ssb_printk(KERN_ERR "SSB Broadcom Gigabit Ethernet " ++- "driver initialization failed\n"); +++ ssb_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n"); ++ /* don't fail SSB init because of this */ ++ err = 0; ++ } + --- a/drivers/ssb/pci.c + +++ b/drivers/ssb/pci.c +-@@ -178,6 +178,18 @@ err_pci: ++@@ -56,7 +56,7 @@ int ssb_pci_switch_coreidx(struct ssb_bu ++ } ++ return 0; ++ error: ++- ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx); +++ ssb_err("Failed to switch to core %u\n", coreidx); ++ return -ENODEV; ++ } ++ ++@@ -67,10 +67,9 @@ int ssb_pci_switch_core(struct ssb_bus * ++ unsigned long flags; ++ ++ #if SSB_VERBOSE_PCICORESWITCH_DEBUG ++- ssb_printk(KERN_INFO PFX ++- "Switching to %s core, index %d\n", ++- ssb_core_name(dev->id.coreid), ++- dev->core_index); +++ ssb_info("Switching to %s core, index %d\n", +++ ssb_core_name(dev->id.coreid), +++ dev->core_index); ++ #endif ++ ++ spin_lock_irqsave(&bus->bar_lock, flags); ++@@ -178,6 +177,18 @@ err_pci: + #define SPEX(_outvar, _offset, _mask, _shift) \ + SPEX16(_outvar, _offset, _mask, _shift) + +@@ -185,30 +1338,140 @@ + + static inline u8 ssb_crc8(u8 crc, u8 data) + { +-@@ -331,7 +343,6 @@ static void sprom_extract_r123(struct ss ++@@ -219,6 +230,15 @@ static inline u8 ssb_crc8(u8 crc, u8 dat ++ return t[crc ^ data]; ++ } ++ +++static void sprom_get_mac(char *mac, const u16 *in) +++{ +++ int i; +++ for (i = 0; i < 3; i++) { +++ *mac++ = in[i] >> 8; +++ *mac++ = in[i]; +++ } +++} +++ ++ static u8 ssb_sprom_crc(const u16 *sprom, u16 size) + { +- int i; +- u16 v; ++ int word; ++@@ -266,7 +286,7 @@ static int sprom_do_write(struct ssb_bus ++ u32 spromctl; ++ u16 size = bus->sprom_size; ++ ++- ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n"); +++ ssb_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n"); ++ err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl); ++ if (err) ++ goto err_ctlreg; ++@@ -274,17 +294,17 @@ static int sprom_do_write(struct ssb_bus ++ err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl); ++ if (err) ++ goto err_ctlreg; ++- ssb_printk(KERN_NOTICE PFX "[ 0%%"); +++ ssb_notice("[ 0%%"); ++ msleep(500); ++ for (i = 0; i < size; i++) { ++ if (i == size / 4) ++- ssb_printk("25%%"); +++ ssb_cont("25%%"); ++ else if (i == size / 2) ++- ssb_printk("50%%"); +++ ssb_cont("50%%"); ++ else if (i == (size * 3) / 4) ++- ssb_printk("75%%"); +++ ssb_cont("75%%"); ++ else if (i % 2) ++- ssb_printk("."); +++ ssb_cont("."); ++ writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2)); ++ mmiowb(); ++ msleep(20); ++@@ -297,12 +317,12 @@ static int sprom_do_write(struct ssb_bus ++ if (err) ++ goto err_ctlreg; ++ msleep(500); ++- ssb_printk("100%% ]\n"); ++- ssb_printk(KERN_NOTICE PFX "SPROM written.\n"); +++ ssb_cont("100%% ]\n"); +++ ssb_notice("SPROM written\n"); ++ ++ return 0; ++ err_ctlreg: ++- ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n"); +++ ssb_err("Could not access SPROM control register.\n"); ++ return err; ++ } ++ ++@@ -327,11 +347,23 @@ static s8 r123_extract_antgain(u8 sprom_ ++ return (s8)gain; ++ } ++ +++static void sprom_extract_r23(struct ssb_sprom *out, const u16 *in) +++{ +++ SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0); +++ SPEX(opo, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0); +++ SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0); +++ SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0); +++ SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0); +++ SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0); +++ SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0); +++ SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0); +++ SPEX(maxpwr_ah, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0); +++ SPEX(maxpwr_al, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO, +++ SSB_SPROM2_MAXP_A_LO_SHIFT); +++} +++ ++ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) ++ { ++- int i; ++- u16 v; + - s8 gain; + u16 loc[3]; + + if (out->revision == 3) /* rev 3 moved MAC */ +-@@ -361,8 +372,9 @@ static void sprom_extract_r123(struct ss ++@@ -341,19 +373,10 @@ static void sprom_extract_r123(struct ss ++ loc[1] = SSB_SPROM1_ET0MAC; ++ loc[2] = SSB_SPROM1_ET1MAC; ++ } ++- for (i = 0; i < 3; i++) { ++- v = in[SPOFF(loc[0]) + i]; ++- *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); ++- } +++ sprom_get_mac(out->il0mac, &in[SPOFF(loc[0])]); ++ if (out->revision < 3) { /* only rev 1-2 have et0, et1 */ ++- for (i = 0; i < 3; i++) { ++- v = in[SPOFF(loc[1]) + i]; ++- *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v); ++- } ++- for (i = 0; i < 3; i++) { ++- v = in[SPOFF(loc[2]) + i]; ++- *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v); ++- } +++ sprom_get_mac(out->et0mac, &in[SPOFF(loc[1])]); +++ sprom_get_mac(out->et1mac, &in[SPOFF(loc[2])]); ++ } ++ SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0); ++ SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, ++@@ -361,8 +384,10 @@ static void sprom_extract_r123(struct ss + SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14); + SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15); + SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0); + - SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE, + - SSB_SPROM1_BINF_CCODE_SHIFT); +++ SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0); + + if (out->revision == 1) + + SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE, + + SSB_SPROM1_BINF_CCODE_SHIFT); + SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA, + SSB_SPROM1_BINF_ANTA_SHIFT); + SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG, +-@@ -388,22 +400,16 @@ static void sprom_extract_r123(struct ss ++@@ -386,24 +411,19 @@ static void sprom_extract_r123(struct ss ++ SSB_SPROM1_ITSSI_A_SHIFT); ++ SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0); + SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0); +- if (out->revision >= 2) +- SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0); ++- if (out->revision >= 2) ++- SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0); +++ + + SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8); + + SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0); + +@@ -233,14 +1496,36 @@ + + out->antenna_gain.a1 = r123_extract_antgain(out->revision, in, + + SSB_SPROM1_AGAIN_A, + + SSB_SPROM1_AGAIN_A_SHIFT); +++ if (out->revision >= 2) +++ sprom_extract_r23(out, in); + } + + /* Revs 4 5 and 8 have partially shared layout */ +-@@ -464,14 +470,17 @@ static void sprom_extract_r45(struct ssb ++@@ -448,30 +468,30 @@ static void sprom_extract_r458(struct ss ++ ++ static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) ++ { ++- int i; ++- u16 v; ++ u16 il0mac_offset; ++ ++ if (out->revision == 4) ++ il0mac_offset = SSB_SPROM4_IL0MAC; ++ else ++ il0mac_offset = SSB_SPROM5_IL0MAC; ++- /* extract the MAC address */ ++- for (i = 0; i < 3; i++) { ++- v = in[SPOFF(il0mac_offset) + i]; ++- *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); ++- } +++ +++ sprom_get_mac(out->il0mac, &in[SPOFF(il0mac_offset)]); +++ + SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0); + SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A, + SSB_SPROM4_ETHPHY_ET1A_SHIFT); + + SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0); +++ SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0); + if (out->revision == 4) { + - SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0); + + SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8); +@@ -256,7 +1541,7 @@ + SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0); + SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0); + SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0); +-@@ -504,16 +513,14 @@ static void sprom_extract_r45(struct ssb ++@@ -504,16 +524,14 @@ static void sprom_extract_r45(struct ssb + } + + /* Extract the antenna gain values. */ +@@ -277,12 +1562,12 @@ + + sprom_extract_r458(out, in); + +-@@ -523,14 +530,22 @@ static void sprom_extract_r45(struct ssb ++@@ -523,14 +541,21 @@ static void sprom_extract_r45(struct ssb + static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) + { + int i; + - u16 v; +-+ u16 v, o; +++ u16 o; + + u16 pwr_info_offset[] = { + + SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1, + + SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3 +@@ -291,18 +1576,21 @@ + + ARRAY_SIZE(out->core_pwr_info)); + + /* extract the MAC address */ +- for (i = 0; i < 3; i++) { +- v = in[SPOFF(SSB_SPROM8_IL0MAC) + i]; +- *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); +- } ++- for (i = 0; i < 3; i++) { ++- v = in[SPOFF(SSB_SPROM8_IL0MAC) + i]; ++- *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); ++- } + - SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0); +++ sprom_get_mac(out->il0mac, &in[SPOFF(SSB_SPROM8_IL0MAC)]); +++ + + SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0); +++ SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0); + + SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8); + + SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0); + SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0); + SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0); + SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0); +-@@ -596,16 +611,46 @@ static void sprom_extract_r8(struct ssb_ ++@@ -596,16 +621,46 @@ static void sprom_extract_r8(struct ssb_ + SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0); + + /* Extract the antenna gain values. */ +@@ -355,7 +1643,7 @@ + + /* Extract FEM info */ + SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G, +-@@ -630,6 +675,63 @@ static void sprom_extract_r8(struct ssb_ ++@@ -630,6 +685,63 @@ static void sprom_extract_r8(struct ssb_ + SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, + SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT); + +@@ -419,7 +1707,79 @@ + sprom_extract_r458(out, in); + + /* TODO - get remaining rev 8 stuff needed */ +-@@ -759,7 +861,6 @@ static void ssb_pci_get_boardinfo(struct ++@@ -641,7 +753,7 @@ static int sprom_extract(struct ssb_bus ++ memset(out, 0, sizeof(*out)); ++ ++ out->revision = in[size - 1] & 0x00FF; ++- ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision); +++ ssb_dbg("SPROM revision %d detected\n", out->revision); ++ memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */ ++ memset(out->et1mac, 0xFF, 6); ++ ++@@ -650,7 +762,7 @@ static int sprom_extract(struct ssb_bus ++ * number stored in the SPROM. ++ * Always extract r1. */ ++ out->revision = 1; ++- ssb_dprintk(KERN_DEBUG PFX "SPROM treated as revision %d\n", out->revision); +++ ssb_dbg("SPROM treated as revision %d\n", out->revision); ++ } ++ ++ switch (out->revision) { ++@@ -667,9 +779,8 @@ static int sprom_extract(struct ssb_bus ++ sprom_extract_r8(out, in); ++ break; ++ default: ++- ssb_printk(KERN_WARNING PFX "Unsupported SPROM" ++- " revision %d detected. Will extract" ++- " v1\n", out->revision); +++ ssb_warn("Unsupported SPROM revision %d detected. Will extract v1\n", +++ out->revision); ++ out->revision = 1; ++ sprom_extract_r123(out, in); ++ } ++@@ -689,7 +800,7 @@ static int ssb_pci_sprom_get(struct ssb_ ++ u16 *buf; ++ ++ if (!ssb_is_sprom_available(bus)) { ++- ssb_printk(KERN_ERR PFX "No SPROM available!\n"); +++ ssb_err("No SPROM available!\n"); ++ return -ENODEV; ++ } ++ if (bus->chipco.dev) { /* can be unavailable! */ ++@@ -708,7 +819,7 @@ static int ssb_pci_sprom_get(struct ssb_ ++ } else { ++ bus->sprom_offset = SSB_SPROM_BASE1; ++ } ++- ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset); +++ ssb_dbg("SPROM offset is 0x%x\n", bus->sprom_offset); ++ ++ buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL); ++ if (!buf) ++@@ -733,18 +844,15 @@ static int ssb_pci_sprom_get(struct ssb_ ++ * available for this device in some other storage */ ++ err = ssb_fill_sprom_with_fallback(bus, sprom); ++ if (err) { ++- ssb_printk(KERN_WARNING PFX "WARNING: Using" ++- " fallback SPROM failed (err %d)\n", ++- err); +++ ssb_warn("WARNING: Using fallback SPROM failed (err %d)\n", +++ err); ++ } else { ++- ssb_dprintk(KERN_DEBUG PFX "Using SPROM" ++- " revision %d provided by" ++- " platform.\n", sprom->revision); +++ ssb_dbg("Using SPROM revision %d provided by platform\n", +++ sprom->revision); ++ err = 0; ++ goto out_free; ++ } ++- ssb_printk(KERN_WARNING PFX "WARNING: Invalid" ++- " SPROM CRC (corrupt SPROM)\n"); +++ ssb_warn("WARNING: Invalid SPROM CRC (corrupt SPROM)\n"); ++ } ++ } ++ err = sprom_extract(bus, sprom, buf, bus->sprom_size); ++@@ -759,7 +867,6 @@ static void ssb_pci_get_boardinfo(struct + { + bi->vendor = bus->host_pci->subsystem_vendor; + bi->type = bus->host_pci->subsystem_device; +@@ -429,7 +1789,95 @@ + int ssb_pci_get_invariants(struct ssb_bus *bus, + --- a/drivers/ssb/pcmcia.c + +++ b/drivers/ssb/pcmcia.c +-@@ -676,14 +676,10 @@ static int ssb_pcmcia_do_get_invariants( ++@@ -143,7 +143,7 @@ int ssb_pcmcia_switch_coreidx(struct ssb ++ ++ return 0; ++ error: ++- ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx); +++ ssb_err("Failed to switch to core %u\n", coreidx); ++ return err; ++ } ++ ++@@ -153,10 +153,9 @@ int ssb_pcmcia_switch_core(struct ssb_bu ++ int err; ++ ++ #if SSB_VERBOSE_PCMCIACORESWITCH_DEBUG ++- ssb_printk(KERN_INFO PFX ++- "Switching to %s core, index %d\n", ++- ssb_core_name(dev->id.coreid), ++- dev->core_index); +++ ssb_info("Switching to %s core, index %d\n", +++ ssb_core_name(dev->id.coreid), +++ dev->core_index); ++ #endif ++ ++ err = ssb_pcmcia_switch_coreidx(bus, dev->core_index); ++@@ -192,7 +191,7 @@ int ssb_pcmcia_switch_segment(struct ssb ++ ++ return 0; ++ error: ++- ssb_printk(KERN_ERR PFX "Failed to switch pcmcia segment\n"); +++ ssb_err("Failed to switch pcmcia segment\n"); ++ return err; ++ } ++ ++@@ -549,44 +548,39 @@ static int ssb_pcmcia_sprom_write_all(st ++ bool failed = 0; ++ size_t size = SSB_PCMCIA_SPROM_SIZE; ++ ++- ssb_printk(KERN_NOTICE PFX ++- "Writing SPROM. Do NOT turn off the power! " ++- "Please stand by...\n"); +++ ssb_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n"); ++ err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEEN); ++ if (err) { ++- ssb_printk(KERN_NOTICE PFX ++- "Could not enable SPROM write access.\n"); +++ ssb_notice("Could not enable SPROM write access\n"); ++ return -EBUSY; ++ } ++- ssb_printk(KERN_NOTICE PFX "[ 0%%"); +++ ssb_notice("[ 0%%"); ++ msleep(500); ++ for (i = 0; i < size; i++) { ++ if (i == size / 4) ++- ssb_printk("25%%"); +++ ssb_cont("25%%"); ++ else if (i == size / 2) ++- ssb_printk("50%%"); +++ ssb_cont("50%%"); ++ else if (i == (size * 3) / 4) ++- ssb_printk("75%%"); +++ ssb_cont("75%%"); ++ else if (i % 2) ++- ssb_printk("."); +++ ssb_cont("."); ++ err = ssb_pcmcia_sprom_write(bus, i, sprom[i]); ++ if (err) { ++- ssb_printk(KERN_NOTICE PFX ++- "Failed to write to SPROM.\n"); +++ ssb_notice("Failed to write to SPROM\n"); ++ failed = 1; ++ break; ++ } ++ } ++ err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS); ++ if (err) { ++- ssb_printk(KERN_NOTICE PFX ++- "Could not disable SPROM write access.\n"); +++ ssb_notice("Could not disable SPROM write access\n"); ++ failed = 1; ++ } ++ msleep(500); ++ if (!failed) { ++- ssb_printk("100%% ]\n"); ++- ssb_printk(KERN_NOTICE PFX "SPROM written.\n"); +++ ssb_cont("100%% ]\n"); +++ ssb_notice("SPROM written\n"); ++ } ++ ++ return failed ? -EBUSY : 0; ++@@ -676,14 +670,10 @@ static int ssb_pcmcia_do_get_invariants( + case SSB_PCMCIA_CIS_ANTGAIN: + GOTO_ERROR_ON(tuple->TupleDataLen != 2, + "antg tpl size"); +@@ -448,6 +1896,41 @@ + break; + case SSB_PCMCIA_CIS_BFLAGS: + GOTO_ERROR_ON((tuple->TupleDataLen != 3) && ++@@ -704,7 +694,7 @@ static int ssb_pcmcia_do_get_invariants( ++ return -ENOSPC; /* continue with next entry */ ++ ++ error: ++- ssb_printk(KERN_ERR PFX +++ ssb_err( ++ "PCMCIA: Failed to fetch device invariants: %s\n", ++ error_description); ++ return -ENODEV; ++@@ -726,7 +716,7 @@ int ssb_pcmcia_get_invariants(struct ssb ++ res = pcmcia_loop_tuple(bus->host_pcmcia, CISTPL_FUNCE, ++ ssb_pcmcia_get_mac, sprom); ++ if (res != 0) { ++- ssb_printk(KERN_ERR PFX +++ ssb_err( ++ "PCMCIA: Failed to fetch MAC address\n"); ++ return -ENODEV; ++ } ++@@ -737,7 +727,7 @@ int ssb_pcmcia_get_invariants(struct ssb ++ if ((res == 0) || (res == -ENOSPC)) ++ return 0; ++ ++- ssb_printk(KERN_ERR PFX +++ ssb_err( ++ "PCMCIA: Failed to fetch device invariants\n"); ++ return -ENODEV; ++ } ++@@ -847,6 +837,6 @@ int ssb_pcmcia_init(struct ssb_bus *bus) ++ ++ return 0; ++ error: ++- ssb_printk(KERN_ERR PFX "Failed to initialize PCMCIA host device\n"); +++ ssb_err("Failed to initialize PCMCIA host device\n"); ++ return err; ++ } + --- a/drivers/ssb/scan.c + +++ b/drivers/ssb/scan.c + @@ -90,6 +90,8 @@ const char *ssb_core_name(u16 coreid) +@@ -459,16 +1942,93 @@ + } + return "UNKNOWN"; + } +-@@ -318,6 +320,9 @@ int ssb_bus_scan(struct ssb_bus *bus, ++@@ -123,8 +125,7 @@ static u16 pcidev_to_chipid(struct pci_d ++ chipid_fallback = 0x4401; ++ break; ++ default: ++- ssb_printk(KERN_ERR PFX ++- "PCI-ID not in fallback list\n"); +++ ssb_err("PCI-ID not in fallback list\n"); ++ } ++ ++ return chipid_fallback; ++@@ -150,8 +151,7 @@ static u8 chipid_to_nrcores(u16 chipid) ++ case 0x4704: ++ return 9; ++ default: ++- ssb_printk(KERN_ERR PFX ++- "CHIPID not in nrcores fallback list\n"); +++ ssb_err("CHIPID not in nrcores fallback list\n"); ++ } ++ ++ return 1; ++@@ -318,12 +318,13 @@ int ssb_bus_scan(struct ssb_bus *bus, + bus->chip_package = 0; + } + } +-+ ssb_printk(KERN_INFO PFX "Found chip with id 0x%04X, rev 0x%02X and " +-+ "package 0x%02X\n", bus->chip_id, bus->chip_rev, +-+ bus->chip_package); +++ ssb_info("Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n", +++ bus->chip_id, bus->chip_rev, bus->chip_package); + if (!bus->nr_devices) + bus->nr_devices = chipid_to_nrcores(bus->chip_id); + if (bus->nr_devices > ARRAY_SIZE(bus->devices)) { ++- ssb_printk(KERN_ERR PFX ++- "More than %d ssb cores found (%d)\n", ++- SSB_MAX_NR_CORES, bus->nr_devices); +++ ssb_err("More than %d ssb cores found (%d)\n", +++ SSB_MAX_NR_CORES, bus->nr_devices); ++ goto err_unmap; ++ } ++ if (bus->bustype == SSB_BUSTYPE_SSB) { ++@@ -365,8 +366,7 @@ int ssb_bus_scan(struct ssb_bus *bus, ++ nr_80211_cores++; ++ if (nr_80211_cores > 1) { ++ if (!we_support_multiple_80211_cores(bus)) { ++- ssb_dprintk(KERN_INFO PFX "Ignoring additional " ++- "802.11 core\n"); +++ ssb_dbg("Ignoring additional 802.11 core\n"); ++ continue; ++ } ++ } ++@@ -374,8 +374,7 @@ int ssb_bus_scan(struct ssb_bus *bus, ++ case SSB_DEV_EXTIF: ++ #ifdef CONFIG_SSB_DRIVER_EXTIF ++ if (bus->extif.dev) { ++- ssb_printk(KERN_WARNING PFX ++- "WARNING: Multiple EXTIFs found\n"); +++ ssb_warn("WARNING: Multiple EXTIFs found\n"); ++ break; ++ } ++ bus->extif.dev = dev; ++@@ -383,8 +382,7 @@ int ssb_bus_scan(struct ssb_bus *bus, ++ break; ++ case SSB_DEV_CHIPCOMMON: ++ if (bus->chipco.dev) { ++- ssb_printk(KERN_WARNING PFX ++- "WARNING: Multiple ChipCommon found\n"); +++ ssb_warn("WARNING: Multiple ChipCommon found\n"); ++ break; ++ } ++ bus->chipco.dev = dev; ++@@ -393,8 +391,7 @@ int ssb_bus_scan(struct ssb_bus *bus, ++ case SSB_DEV_MIPS_3302: ++ #ifdef CONFIG_SSB_DRIVER_MIPS ++ if (bus->mipscore.dev) { ++- ssb_printk(KERN_WARNING PFX ++- "WARNING: Multiple MIPS cores found\n"); +++ ssb_warn("WARNING: Multiple MIPS cores found\n"); ++ break; ++ } ++ bus->mipscore.dev = dev; ++@@ -415,8 +412,7 @@ int ssb_bus_scan(struct ssb_bus *bus, ++ } ++ } ++ if (bus->pcicore.dev) { ++- ssb_printk(KERN_WARNING PFX ++- "WARNING: Multiple PCI(E) cores found\n"); +++ ssb_warn("WARNING: Multiple PCI(E) cores found\n"); ++ break; ++ } ++ bus->pcicore.dev = dev; + --- a/drivers/ssb/sdio.c + +++ b/drivers/ssb/sdio.c + @@ -551,14 +551,10 @@ int ssb_sdio_get_invariants(struct ssb_b +@@ -490,20 +2050,139 @@ + break; + case SSB_SDIO_CIS_BFLAGS: + GOTO_ERROR_ON((tuple->size != 3) && ++--- a/drivers/ssb/sprom.c +++++ b/drivers/ssb/sprom.c ++@@ -127,13 +127,13 @@ ssize_t ssb_attr_sprom_store(struct ssb_ ++ goto out_kfree; ++ err = ssb_devices_freeze(bus, &freeze); ++ if (err) { ++- ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n"); +++ ssb_err("SPROM write: Could not freeze all devices\n"); ++ goto out_unlock; ++ } ++ res = sprom_write(bus, sprom); ++ err = ssb_devices_thaw(&freeze); ++ if (err) ++- ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n"); +++ ssb_err("SPROM write: Could not thaw all devices\n"); ++ out_unlock: ++ mutex_unlock(&bus->sprom_mutex); ++ out_kfree: + --- a/drivers/ssb/ssb_private.h + +++ b/drivers/ssb/ssb_private.h +-@@ -207,4 +207,8 @@ static inline void b43_pci_ssb_bridge_ex ++@@ -3,21 +3,33 @@ ++ ++ #include ++ #include +++#include ++ ++ ++ #define PFX "ssb: " ++ ++ #ifdef CONFIG_SSB_SILENT ++-# define ssb_printk(fmt, x...) do { /* nothing */ } while (0) +++# define ssb_printk(fmt, ...) \ +++ do { if (0) printk(fmt, ##__VA_ARGS__); } while (0) ++ #else ++-# define ssb_printk printk +++# define ssb_printk(fmt, ...) \ +++ printk(fmt, ##__VA_ARGS__) ++ #endif /* CONFIG_SSB_SILENT */ ++ +++#define ssb_emerg(fmt, ...) ssb_printk(KERN_EMERG PFX fmt, ##__VA_ARGS__) +++#define ssb_err(fmt, ...) ssb_printk(KERN_ERR PFX fmt, ##__VA_ARGS__) +++#define ssb_warn(fmt, ...) ssb_printk(KERN_WARNING PFX fmt, ##__VA_ARGS__) +++#define ssb_notice(fmt, ...) ssb_printk(KERN_NOTICE PFX fmt, ##__VA_ARGS__) +++#define ssb_info(fmt, ...) ssb_printk(KERN_INFO PFX fmt, ##__VA_ARGS__) +++#define ssb_cont(fmt, ...) ssb_printk(KERN_CONT fmt, ##__VA_ARGS__) +++ ++ /* dprintk: Debugging printk; vanishes for non-debug compilation */ ++ #ifdef CONFIG_SSB_DEBUG ++-# define ssb_dprintk(fmt, x...) ssb_printk(fmt , ##x) +++# define ssb_dbg(fmt, ...) \ +++ ssb_printk(KERN_DEBUG PFX fmt, ##__VA_ARGS__) ++ #else ++-# define ssb_dprintk(fmt, x...) do { /* nothing */ } while (0) +++# define ssb_dbg(fmt, ...) \ +++ do { if (0) printk(KERN_DEBUG PFX fmt, ##__VA_ARGS__); } while (0) ++ #endif ++ ++ #ifdef CONFIG_SSB_DEBUG ++@@ -207,4 +219,60 @@ static inline void b43_pci_ssb_bridge_ex + } + #endif /* CONFIG_SSB_B43_PCI_BRIDGE */ + + +/* driver_chipcommon_pmu.c */ + +extern u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc); + +extern u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc); +++extern u32 ssb_pmu_get_alp_clock(struct ssb_chipcommon *cc); + + +++extern u32 ssb_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, +++ u32 ticks); +++extern u32 ssb_chipco_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms); +++ +++#ifdef CONFIG_SSB_DRIVER_EXTIF +++extern u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks); +++extern u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms); +++#else +++static inline u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, +++ u32 ticks) +++{ +++ return 0; +++} +++static inline u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, +++ u32 ms) +++{ +++ return 0; +++} +++#endif +++ +++#ifdef CONFIG_SSB_EMBEDDED +++extern int ssb_watchdog_register(struct ssb_bus *bus); +++#else /* CONFIG_SSB_EMBEDDED */ +++static inline int ssb_watchdog_register(struct ssb_bus *bus) +++{ +++ return 0; +++} +++#endif /* CONFIG_SSB_EMBEDDED */ +++ +++#ifdef CONFIG_SSB_DRIVER_EXTIF +++extern void ssb_extif_init(struct ssb_extif *extif); +++#else +++static inline void ssb_extif_init(struct ssb_extif *extif) +++{ +++} +++#endif +++ +++#ifdef CONFIG_SSB_DRIVER_GPIO +++extern int ssb_gpio_init(struct ssb_bus *bus); +++extern int ssb_gpio_unregister(struct ssb_bus *bus); +++#else /* CONFIG_SSB_DRIVER_GPIO */ +++static inline int ssb_gpio_init(struct ssb_bus *bus) +++{ +++ return -ENOTSUPP; +++} +++static inline int ssb_gpio_unregister(struct ssb_bus *bus) +++{ +++ return 0; +++} +++#endif /* CONFIG_SSB_DRIVER_GPIO */ +++ + #endif /* LINUX_SSB_PRIVATE_H_ */ + --- a/include/linux/ssb/ssb.h + +++ b/include/linux/ssb/ssb.h +-@@ -16,6 +16,12 @@ struct pcmcia_device; ++@@ -6,8 +6,10 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ #include +++#include ++ ++ #include ++ ++@@ -16,19 +18,28 @@ struct pcmcia_device; + struct ssb_bus; + struct ssb_driver; + +@@ -515,8 +2194,14 @@ + + + struct ssb_sprom { + u8 revision; +- u8 il0mac[6]; /* MAC address for 802.11b/g */ +-@@ -26,9 +32,12 @@ struct ssb_sprom { ++- u8 il0mac[6]; /* MAC address for 802.11b/g */ ++- u8 et0mac[6]; /* MAC address for Ethernet */ ++- u8 et1mac[6]; /* MAC address for 802.11a */ +++ u8 il0mac[6] __aligned(sizeof(u16)); /* MAC address for 802.11b/g */ +++ u8 et0mac[6] __aligned(sizeof(u16)); /* MAC address for Ethernet */ +++ u8 et1mac[6] __aligned(sizeof(u16)); /* MAC address for 802.11a */ ++ u8 et0phyaddr; /* MII address for enet0 */ ++ u8 et1phyaddr; /* MII address for enet1 */ + u8 et0mdcport; /* MDIO for enet0 */ + u8 et1mdcport; /* MDIO for enet1 */ + u16 board_rev; /* Board revision number from SPROM. */ +@@ -531,7 +2216,7 @@ + u8 ant_available_a; /* 2GHz antenna available bits (up to 4) */ + u8 ant_available_bg; /* 5GHz antenna available bits (up to 4) */ + u16 pa0b0; +-@@ -47,10 +56,10 @@ struct ssb_sprom { ++@@ -47,10 +58,10 @@ struct ssb_sprom { + u8 gpio1; /* GPIO pin 1 */ + u8 gpio2; /* GPIO pin 2 */ + u8 gpio3; /* GPIO pin 3 */ +@@ -546,7 +2231,7 @@ + u8 itssi_a; /* Idle TSSI Target for A-PHY */ + u8 itssi_bg; /* Idle TSSI Target for B/G-PHY */ + u8 tri2g; /* 2.4GHz TX isolation */ +-@@ -61,8 +70,8 @@ struct ssb_sprom { ++@@ -61,8 +72,8 @@ struct ssb_sprom { + u8 txpid5gl[4]; /* 4.9 - 5.1GHz TX power index */ + u8 txpid5g[4]; /* 5.1 - 5.5GHz TX power index */ + u8 txpid5gh[4]; /* 5.5 - ...GHz TX power index */ +@@ -557,7 +2242,7 @@ + u8 rssisav2g; /* 2GHz RSSI params */ + u8 rssismc2g; + u8 rssismf2g; +-@@ -82,16 +91,13 @@ struct ssb_sprom { ++@@ -82,16 +93,13 @@ struct ssb_sprom { + u16 boardflags2_hi; /* Board flags (bits 48-63) */ + /* TODO store board flags in a single u64 */ + +@@ -577,7 +2262,7 @@ + } antenna_gain; + + struct { +-@@ -103,14 +109,85 @@ struct ssb_sprom { ++@@ -103,14 +111,85 @@ struct ssb_sprom { + } ghz5; + } fem; + +@@ -665,7 +2350,7 @@ + }; + + +-@@ -166,6 +243,7 @@ struct ssb_bus_ops { ++@@ -166,6 +245,7 @@ struct ssb_bus_ops { + #define SSB_DEV_MINI_MACPHY 0x823 + #define SSB_DEV_ARM_1176 0x824 + #define SSB_DEV_ARM_7TDMI 0x825 +@@ -673,6 +2358,214 @@ + + /* Vendor-ID values */ + #define SSB_VENDOR_BROADCOM 0x4243 ++@@ -260,13 +340,61 @@ enum ssb_bustype { ++ #define SSB_BOARDVENDOR_DELL 0x1028 /* Dell */ ++ #define SSB_BOARDVENDOR_HP 0x0E11 /* HP */ ++ /* board_type */ +++#define SSB_BOARD_BCM94301CB 0x0406 +++#define SSB_BOARD_BCM94301MP 0x0407 +++#define SSB_BOARD_BU4309 0x040A +++#define SSB_BOARD_BCM94309CB 0x040B +++#define SSB_BOARD_BCM4309MP 0x040C +++#define SSB_BOARD_BU4306 0x0416 ++ #define SSB_BOARD_BCM94306MP 0x0418 ++ #define SSB_BOARD_BCM4309G 0x0421 ++ #define SSB_BOARD_BCM4306CB 0x0417 ++-#define SSB_BOARD_BCM4309MP 0x040C +++#define SSB_BOARD_BCM94306PC 0x0425 /* pcmcia 3.3v 4306 card */ +++#define SSB_BOARD_BCM94306CBSG 0x042B /* with SiGe PA */ +++#define SSB_BOARD_PCSG94306 0x042D /* with SiGe PA */ +++#define SSB_BOARD_BU4704SD 0x042E /* with sdram */ +++#define SSB_BOARD_BCM94704AGR 0x042F /* dual 11a/11g Router */ +++#define SSB_BOARD_BCM94308MP 0x0430 /* 11a-only minipci */ +++#define SSB_BOARD_BU4318 0x0447 +++#define SSB_BOARD_CB4318 0x0448 +++#define SSB_BOARD_MPG4318 0x0449 ++ #define SSB_BOARD_MP4318 0x044A ++-#define SSB_BOARD_BU4306 0x0416 ++-#define SSB_BOARD_BU4309 0x040A +++#define SSB_BOARD_SD4318 0x044B +++#define SSB_BOARD_BCM94306P 0x044C /* with SiGe */ +++#define SSB_BOARD_BCM94303MP 0x044E +++#define SSB_BOARD_BCM94306MPM 0x0450 +++#define SSB_BOARD_BCM94306MPL 0x0453 +++#define SSB_BOARD_PC4303 0x0454 /* pcmcia */ +++#define SSB_BOARD_BCM94306MPLNA 0x0457 +++#define SSB_BOARD_BCM94306MPH 0x045B +++#define SSB_BOARD_BCM94306PCIV 0x045C +++#define SSB_BOARD_BCM94318MPGH 0x0463 +++#define SSB_BOARD_BU4311 0x0464 +++#define SSB_BOARD_BCM94311MC 0x0465 +++#define SSB_BOARD_BCM94311MCAG 0x0466 +++/* 4321 boards */ +++#define SSB_BOARD_BU4321 0x046B +++#define SSB_BOARD_BU4321E 0x047C +++#define SSB_BOARD_MP4321 0x046C +++#define SSB_BOARD_CB2_4321 0x046D +++#define SSB_BOARD_CB2_4321_AG 0x0066 +++#define SSB_BOARD_MC4321 0x046E +++/* 4325 boards */ +++#define SSB_BOARD_BCM94325DEVBU 0x0490 +++#define SSB_BOARD_BCM94325BGABU 0x0491 +++#define SSB_BOARD_BCM94325SDGWB 0x0492 +++#define SSB_BOARD_BCM94325SDGMDL 0x04AA +++#define SSB_BOARD_BCM94325SDGMDL2 0x04C6 +++#define SSB_BOARD_BCM94325SDGMDL3 0x04C9 +++#define SSB_BOARD_BCM94325SDABGWBA 0x04E1 +++/* 4322 boards */ +++#define SSB_BOARD_BCM94322MC 0x04A4 +++#define SSB_BOARD_BCM94322USB 0x04A8 /* dualband */ +++#define SSB_BOARD_BCM94322HM 0x04B0 +++#define SSB_BOARD_BCM94322USB2D 0x04Bf /* single band discrete front end */ +++/* 4312 boards */ +++#define SSB_BOARD_BU4312 0x048A +++#define SSB_BOARD_BCM4312MCGSG 0x04B5 ++ /* chip_package */ ++ #define SSB_CHIPPACK_BCM4712S 1 /* Small 200pin 4712 */ ++ #define SSB_CHIPPACK_BCM4712M 2 /* Medium 225pin 4712 */ ++@@ -354,7 +482,11 @@ struct ssb_bus { ++ #ifdef CONFIG_SSB_EMBEDDED ++ /* Lock for GPIO register access. */ ++ spinlock_t gpio_lock; +++ struct platform_device *watchdog; ++ #endif /* EMBEDDED */ +++#ifdef CONFIG_SSB_DRIVER_GPIO +++ struct gpio_chip gpio; +++#endif /* DRIVER_GPIO */ ++ ++ /* Internal-only stuff follows. Do not touch. */ ++ struct list_head list; ++--- a/include/linux/ssb/ssb_driver_chipcommon.h +++++ b/include/linux/ssb/ssb_driver_chipcommon.h ++@@ -219,6 +219,7 @@ ++ #define SSB_CHIPCO_PMU_CTL 0x0600 /* PMU control */ ++ #define SSB_CHIPCO_PMU_CTL_ILP_DIV 0xFFFF0000 /* ILP div mask */ ++ #define SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT 16 +++#define SSB_CHIPCO_PMU_CTL_PLL_UPD 0x00000400 ++ #define SSB_CHIPCO_PMU_CTL_NOILPONW 0x00000200 /* No ILP on wait */ ++ #define SSB_CHIPCO_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */ ++ #define SSB_CHIPCO_PMU_CTL_ALPREQEN 0x00000080 /* ALP req enable */ ++@@ -588,7 +589,10 @@ struct ssb_chipcommon { ++ u32 status; ++ /* Fast Powerup Delay constant */ ++ u16 fast_pwrup_delay; +++ spinlock_t gpio_lock; ++ struct ssb_chipcommon_pmu pmu; +++ u32 ticks_per_ms; +++ u32 max_timer_ms; ++ }; ++ ++ static inline bool ssb_chipco_available(struct ssb_chipcommon *cc) ++@@ -628,8 +632,7 @@ enum ssb_clkmode { ++ extern void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc, ++ enum ssb_clkmode mode); ++ ++-extern void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, ++- u32 ticks); +++extern u32 ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks); ++ ++ void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value); ++ ++@@ -642,6 +645,8 @@ u32 ssb_chipco_gpio_outen(struct ssb_chi ++ u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value); ++ u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value); ++ u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value); +++u32 ssb_chipco_gpio_pullup(struct ssb_chipcommon *cc, u32 mask, u32 value); +++u32 ssb_chipco_gpio_pulldown(struct ssb_chipcommon *cc, u32 mask, u32 value); ++ ++ #ifdef CONFIG_SSB_SERIAL ++ extern int ssb_chipco_serial_init(struct ssb_chipcommon *cc, ++@@ -661,5 +666,6 @@ enum ssb_pmu_ldo_volt_id { ++ void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc, ++ enum ssb_pmu_ldo_volt_id id, u32 voltage); ++ void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on); +++void ssb_pmu_spuravoid_pllupdate(struct ssb_chipcommon *cc, int spuravoid); ++ ++ #endif /* LINUX_SSB_CHIPCO_H_ */ ++--- a/include/linux/ssb/ssb_driver_extif.h +++++ b/include/linux/ssb/ssb_driver_extif.h ++@@ -152,12 +152,16 @@ ++ /* watchdog */ ++ #define SSB_EXTIF_WATCHDOG_CLK 48000000 /* Hz */ ++ +++#define SSB_EXTIF_WATCHDOG_MAX_TIMER ((1 << 28) - 1) +++#define SSB_EXTIF_WATCHDOG_MAX_TIMER_MS (SSB_EXTIF_WATCHDOG_MAX_TIMER \ +++ / (SSB_EXTIF_WATCHDOG_CLK / 1000)) ++ ++ ++ #ifdef CONFIG_SSB_DRIVER_EXTIF ++ ++ struct ssb_extif { ++ struct ssb_device *dev; +++ spinlock_t gpio_lock; ++ }; ++ ++ static inline bool ssb_extif_available(struct ssb_extif *extif) ++@@ -171,8 +175,7 @@ extern void ssb_extif_get_clockcontrol(s ++ extern void ssb_extif_timing_init(struct ssb_extif *extif, ++ unsigned long ns); ++ ++-extern void ssb_extif_watchdog_timer_set(struct ssb_extif *extif, ++- u32 ticks); +++extern u32 ssb_extif_watchdog_timer_set(struct ssb_extif *extif, u32 ticks); ++ ++ /* Extif GPIO pin access */ ++ u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask); ++@@ -205,10 +208,52 @@ void ssb_extif_get_clockcontrol(struct s ++ } ++ ++ static inline ++-void ssb_extif_watchdog_timer_set(struct ssb_extif *extif, ++- u32 ticks) +++void ssb_extif_timing_init(struct ssb_extif *extif, unsigned long ns) ++ { ++ } ++ +++static inline +++u32 ssb_extif_watchdog_timer_set(struct ssb_extif *extif, u32 ticks) +++{ +++ return 0; +++} +++ +++static inline u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask) +++{ +++ return 0; +++} +++ +++static inline u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, +++ u32 value) +++{ +++ return 0; +++} +++ +++static inline u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, +++ u32 value) +++{ +++ return 0; +++} +++ +++static inline u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask, +++ u32 value) +++{ +++ return 0; +++} +++ +++static inline u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask, +++ u32 value) +++{ +++ return 0; +++} +++ +++#ifdef CONFIG_SSB_SERIAL +++static inline int ssb_extif_serial_init(struct ssb_extif *extif, +++ struct ssb_serial_port *ports) +++{ +++ return 0; +++} +++#endif /* CONFIG_SSB_SERIAL */ +++ ++ #endif /* CONFIG_SSB_DRIVER_EXTIF */ ++ #endif /* LINUX_SSB_EXTIFCORE_H_ */ + --- a/include/linux/ssb/ssb_driver_gige.h + +++ b/include/linux/ssb/ssb_driver_gige.h + @@ -2,6 +2,7 @@ +@@ -683,9 +2576,71 @@ + #include + #include + ++@@ -96,21 +97,16 @@ static inline bool ssb_gige_must_flush_p ++ return 0; ++ } ++ ++-#ifdef CONFIG_BCM47XX ++-#include ++ /* Get the device MAC address */ ++-static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr) ++-{ ++- char buf[20]; ++- if (nvram_getenv("et0macaddr", buf, sizeof(buf)) < 0) ++- return; ++- nvram_parse_macaddr(buf, macaddr); ++-} ++-#else ++-static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr) +++static inline int ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr) ++ { +++ struct ssb_gige *dev = pdev_to_ssb_gige(pdev); +++ if (!dev) +++ return -ENODEV; +++ +++ memcpy(macaddr, dev->dev->bus->sprom.et0mac, 6); +++ return 0; ++ } ++-#endif ++ ++ extern int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev, ++ struct pci_dev *pdev); ++@@ -174,6 +170,10 @@ static inline bool ssb_gige_must_flush_p ++ { ++ return 0; ++ } +++static inline int ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr) +++{ +++ return -ENODEV; +++} ++ ++ #endif /* CONFIG_SSB_DRIVER_GIGE */ ++ #endif /* LINUX_SSB_DRIVER_GIGE_H_ */ ++--- a/include/linux/ssb/ssb_driver_mips.h +++++ b/include/linux/ssb/ssb_driver_mips.h ++@@ -41,6 +41,11 @@ void ssb_mipscore_init(struct ssb_mipsco ++ { ++ } ++ +++static inline unsigned int ssb_mips_irq(struct ssb_device *dev) +++{ +++ return 0; +++} +++ ++ #endif /* CONFIG_SSB_DRIVER_MIPS */ ++ ++ #endif /* LINUX_SSB_MIPSCORE_H_ */ + --- a/include/linux/ssb/ssb_regs.h + +++ b/include/linux/ssb/ssb_regs.h +-@@ -228,6 +228,7 @@ ++@@ -172,6 +172,7 @@ ++ #define SSB_SPROMSIZE_WORDS_R4 220 ++ #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_SPROM_BASE1 0x1000 ++ #define SSB_SPROM_BASE31 0x0800 ++ #define SSB_SPROM_REVISION 0x007E ++@@ -228,6 +229,7 @@ + #define SSB_SPROM1_AGAIN_BG_SHIFT 0 + #define SSB_SPROM1_AGAIN_A 0xFF00 /* A-PHY */ + #define SSB_SPROM1_AGAIN_A_SHIFT 8 +@@ -693,7 +2648,7 @@ + + /* SPROM Revision 2 (inherits from rev 1) */ + #define SSB_SPROM2_BFLHI 0x0038 /* Boardflags (high 16 bits) */ +-@@ -267,6 +268,7 @@ ++@@ -267,6 +269,7 @@ + #define SSB_SPROM3_OFDMGPO 0x107A /* G-PHY OFDM Power Offset (4 bytes, BigEndian) */ + + /* SPROM Revision 4 */ +@@ -701,7 +2656,24 @@ + #define SSB_SPROM4_BFLLO 0x0044 /* Boardflags (low 16 bits) */ + #define SSB_SPROM4_BFLHI 0x0046 /* Board Flags Hi */ + #define SSB_SPROM4_BFL2LO 0x0048 /* Board flags 2 (low 16 bits) */ +-@@ -389,6 +391,11 @@ ++@@ -287,11 +290,11 @@ ++ #define SSB_SPROM4_ETHPHY_ET1A_SHIFT 5 ++ #define SSB_SPROM4_ETHPHY_ET0M (1<<14) /* MDIO for enet0 */ ++ #define SSB_SPROM4_ETHPHY_ET1M (1<<15) /* MDIO for enet1 */ ++-#define SSB_SPROM4_ANTAVAIL 0x005D /* Antenna available bitfields */ ++-#define SSB_SPROM4_ANTAVAIL_A 0x00FF /* A-PHY bitfield */ ++-#define SSB_SPROM4_ANTAVAIL_A_SHIFT 0 ++-#define SSB_SPROM4_ANTAVAIL_BG 0xFF00 /* B-PHY and G-PHY bitfield */ ++-#define SSB_SPROM4_ANTAVAIL_BG_SHIFT 8 +++#define SSB_SPROM4_ANTAVAIL 0x005C /* Antenna available bitfields */ +++#define SSB_SPROM4_ANTAVAIL_BG 0x00FF /* B-PHY and G-PHY bitfield */ +++#define SSB_SPROM4_ANTAVAIL_BG_SHIFT 0 +++#define SSB_SPROM4_ANTAVAIL_A 0xFF00 /* A-PHY bitfield */ +++#define SSB_SPROM4_ANTAVAIL_A_SHIFT 8 ++ #define SSB_SPROM4_AGAIN01 0x005E /* Antenna Gain (in dBm Q5.2) */ ++ #define SSB_SPROM4_AGAIN0 0x00FF /* Antenna 0 */ ++ #define SSB_SPROM4_AGAIN0_SHIFT 0 ++@@ -389,6 +392,11 @@ + #define SSB_SPROM8_GPIOB_P2 0x00FF /* Pin 2 */ + #define SSB_SPROM8_GPIOB_P3 0xFF00 /* Pin 3 */ + #define SSB_SPROM8_GPIOB_P3_SHIFT 8 +@@ -713,7 +2685,7 @@ + #define SSB_SPROM8_ANTAVAIL 0x009C /* Antenna available bitfields*/ + #define SSB_SPROM8_ANTAVAIL_A 0xFF00 /* A-PHY bitfield */ + #define SSB_SPROM8_ANTAVAIL_A_SHIFT 8 +-@@ -404,6 +411,13 @@ ++@@ -404,6 +412,13 @@ + #define SSB_SPROM8_AGAIN2_SHIFT 0 + #define SSB_SPROM8_AGAIN3 0xFF00 /* Antenna 3 */ + #define SSB_SPROM8_AGAIN3_SHIFT 8 +@@ -727,7 +2699,7 @@ + #define SSB_SPROM8_RSSIPARM2G 0x00A4 /* RSSI params for 2GHz */ + #define SSB_SPROM8_RSSISMF2G 0x000F + #define SSB_SPROM8_RSSISMC2G 0x00F0 +-@@ -430,6 +444,7 @@ ++@@ -430,6 +445,7 @@ + #define SSB_SPROM8_TRI5GH_SHIFT 8 + #define SSB_SPROM8_RXPO 0x00AC /* RX power offsets */ + #define SSB_SPROM8_RXPO2G 0x00FF /* 2GHz RX power offset */ +@@ -735,7 +2707,7 @@ + #define SSB_SPROM8_RXPO5G 0xFF00 /* 5GHz RX power offset */ + #define SSB_SPROM8_RXPO5G_SHIFT 8 + #define SSB_SPROM8_FEM2G 0x00AE +-@@ -445,10 +460,71 @@ ++@@ -445,10 +461,71 @@ + #define SSB_SROM8_FEM_ANTSWLUT 0xF800 + #define SSB_SROM8_FEM_ANTSWLUT_SHIFT 11 + #define SSB_SPROM8_THERMAL 0x00B2 +@@ -768,7 +2740,7 @@ + +#define SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT 4 + +#define SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL 0x0020 + +#define SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT 5 +-+#define SSB_SPROM8_TEMPDELTA 0x00BA +++#define SSB_SPROM8_TEMPDELTA 0x00BC + +#define SSB_SPROM8_TEMPDELTA_PHYCAL 0x00ff + +#define SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT 0 + +#define SSB_SPROM8_TEMPDELTA_PERIOD 0x0f00 +@@ -811,7 +2783,7 @@ + #define SSB_SPROM8_MAXP_BG 0x00C0 /* Max Power 2GHz in path 1 */ + #define SSB_SPROM8_MAXP_BG_MASK 0x00FF /* Mask for Max Power 2GHz */ + #define SSB_SPROM8_ITSSI_BG 0xFF00 /* Mask for path 1 itssi_bg */ +-@@ -473,12 +549,23 @@ ++@@ -473,12 +550,23 @@ + #define SSB_SPROM8_PA1HIB0 0x00D8 /* 5.8GHz power amp settings */ + #define SSB_SPROM8_PA1HIB1 0x00DA + #define SSB_SPROM8_PA1HIB2 0x00DC +@@ -835,3 +2807,37 @@ + /* Values for boardflags_lo read from SPROM */ + #define SSB_BFL_BTCOEXIST 0x0001 /* implements Bluetooth coexistance */ + #define SSB_BFL_PACTRL 0x0002 /* GPIO 9 controlling the PA */ ++--- /dev/null +++++ b/include/linux/bcm47xx_wdt.h ++@@ -0,0 +1,19 @@ +++#ifndef LINUX_BCM47XX_WDT_H_ +++#define LINUX_BCM47XX_WDT_H_ +++ +++#include +++ +++ +++struct bcm47xx_wdt { +++ u32 (*timer_set)(struct bcm47xx_wdt *, u32); +++ u32 (*timer_set_ms)(struct bcm47xx_wdt *, u32); +++ u32 max_timer_ms; +++ +++ void *driver_data; +++}; +++ +++static inline void *bcm47xx_wdt_get_drvdata(struct bcm47xx_wdt *wdt) +++{ +++ return wdt->driver_data; +++} +++#endif /* LINUX_BCM47XX_WDT_H_ */ ++--- a/drivers/net/wireless/b43/phy_n.c +++++ b/drivers/net/wireless/b43/phy_n.c ++@@ -4259,7 +4259,8 @@ static void b43_nphy_pmu_spur_avoid(stru ++ #endif ++ #ifdef CONFIG_B43_SSB ++ case B43_BUS_SSB: ++- /* FIXME */ +++ ssb_pmu_spuravoid_pllupdate(&dev->dev->sdev->bus->chipco, +++ avoid); ++ break; ++ #endif ++ } +Index: patches-3.3/080-prot-release-cb.patch +=================================================================== +--- patches-3.3/080-prot-release-cb.patch (Revision 35298) ++++ patches-3.3/080-prot-release-cb.patch (Revision 37768) +@@ -3,8 +3,8 @@ + + --- a/include/net/sock.h + +++ b/include/net/sock.h +-@@ -858,6 +858,8 @@ struct proto { +- int (*backlog_rcv) (struct sock *sk, ++@@ -810,6 +810,8 @@ struct proto { ++ int (*backlog_rcv) (struct sock *sk, + struct sk_buff *skb); + + + void (*release_cb)(struct sock *sk); +@@ -14,7 +14,7 @@ + void (*unhash)(struct sock *sk); + --- a/net/core/sock.c + +++ b/net/core/sock.c +-@@ -2159,6 +2159,10 @@ void release_sock(struct sock *sk) ++@@ -2138,6 +2138,10 @@ void release_sock(struct sock *sk) + spin_lock_bh(&sk->sk_lock.slock); + if (sk->sk_backlog.tail) + __release_sock(sk); +Index: patches-3.3/668-ipv6-fix-handling-of-throw-routes.patch +=================================================================== +--- patches-3.3/668-ipv6-fix-handling-of-throw-routes.patch (Revision 0) ++++ patches-3.3/668-ipv6-fix-handling-of-throw-routes.patch (Revision 37768) +@@ -0,0 +1,32 @@ ++--- a/net/ipv6/route.c +++++ b/net/ipv6/route.c ++@@ -1341,6 +1341,9 @@ int ip6_route_add(struct fib6_config *cf ++ case RTN_PROHIBIT: ++ rt->dst.error = -EACCES; ++ break; +++ case RTN_THROW: +++ rt->dst.error = -EAGAIN; +++ break; ++ default: ++ rt->dst.error = -ENETUNREACH; ++ break; ++@@ -2279,7 +2282,8 @@ static int rtm_to_fib6_config(struct sk_ ++ ++ if (rtm->rtm_type == RTN_UNREACHABLE || ++ rtm->rtm_type == RTN_BLACKHOLE || ++- rtm->rtm_type == RTN_PROHIBIT) +++ rtm->rtm_type == RTN_PROHIBIT || +++ rtm->rtm_type == RTN_THROW) ++ cfg->fc_flags |= RTF_REJECT; ++ ++ if (rtm->rtm_type == RTN_LOCAL) ++@@ -2417,6 +2421,9 @@ static int rt6_fill_node(struct net *net ++ case -EACCES: ++ rtm->rtm_type = RTN_PROHIBIT; ++ break; +++ case -EAGAIN: +++ rtm->rtm_type = RTN_THROW; +++ break; ++ default: ++ rtm->rtm_type = RTN_UNREACHABLE; ++ break; +Index: patches-3.3/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch +=================================================================== +--- patches-3.3/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch (Revision 0) ++++ patches-3.3/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch (Revision 37768) +@@ -0,0 +1,241 @@ ++--- a/include/net/netns/ipv6.h +++++ b/include/net/netns/ipv6.h ++@@ -50,6 +50,7 @@ struct netns_ipv6 { ++ unsigned long ip6_rt_last_gc; ++ #ifdef CONFIG_IPV6_MULTIPLE_TABLES ++ struct rt6_info *ip6_prohibit_entry; +++ struct rt6_info *ip6_failed_policy_entry; ++ struct rt6_info *ip6_blk_hole_entry; ++ struct fib6_table *fib6_local_tbl; ++ struct fib_rules_ops *fib6_rules_ops; ++--- a/include/linux/fib_rules.h +++++ b/include/linux/fib_rules.h ++@@ -64,6 +64,10 @@ enum { ++ FR_ACT_BLACKHOLE, /* Drop without notification */ ++ FR_ACT_UNREACHABLE, /* Drop with ENETUNREACH */ ++ FR_ACT_PROHIBIT, /* Drop with EACCES */ +++ FR_ACT_RES9, +++ FR_ACT_RES10, +++ FR_ACT_RES11, +++ FR_ACT_FAILED_POLICY, /* Drop with EPERM */ ++ __FR_ACT_MAX, ++ }; ++ ++--- a/include/linux/icmpv6.h +++++ b/include/linux/icmpv6.h ++@@ -123,6 +123,7 @@ static inline struct icmp6hdr *icmp6_hdr ++ #define ICMPV6_NOT_NEIGHBOUR 2 ++ #define ICMPV6_ADDR_UNREACH 3 ++ #define ICMPV6_PORT_UNREACH 4 +++#define ICMPV6_FAILED_POLICY 5 ++ ++ /* ++ * Codes for Time Exceeded ++--- a/include/linux/rtnetlink.h +++++ b/include/linux/rtnetlink.h ++@@ -191,6 +191,7 @@ enum { ++ RTN_THROW, /* Not in this table */ ++ RTN_NAT, /* Translate this address */ ++ RTN_XRESOLVE, /* Use external resolver */ +++ RTN_FAILED_POLICY, /* Failed ingress/egress policy */ ++ __RTN_MAX ++ }; ++ ++--- a/net/ipv4/fib_rules.c +++++ b/net/ipv4/fib_rules.c ++@@ -87,6 +87,10 @@ static int fib4_rule_action(struct fib_r ++ err = -EACCES; ++ goto errout; ++ +++ case FR_ACT_FAILED_POLICY: +++ err = -EPERM; +++ goto errout; +++ ++ case FR_ACT_BLACKHOLE: ++ default: ++ err = -EINVAL; ++--- a/net/ipv4/fib_semantics.c +++++ b/net/ipv4/fib_semantics.c ++@@ -139,6 +139,10 @@ const struct fib_prop fib_props[RTN_MAX ++ .error = -EINVAL, ++ .scope = RT_SCOPE_NOWHERE, ++ }, +++ [RTN_FAILED_POLICY] = { +++ .error = -EPERM, +++ .scope = RT_SCOPE_UNIVERSE, +++ }, ++ }; ++ ++ /* Release a nexthop info record */ ++--- a/net/ipv4/fib_trie.c +++++ b/net/ipv4/fib_trie.c ++@@ -2349,6 +2349,7 @@ static const char *const rtn_type_names[ ++ [RTN_THROW] = "THROW", ++ [RTN_NAT] = "NAT", ++ [RTN_XRESOLVE] = "XRESOLVE", +++ [RTN_FAILED_POLICY] = "FAILED_POLICY", ++ }; ++ ++ static inline const char *rtn_type(char *buf, size_t len, unsigned int t) ++--- a/net/ipv4/ipmr.c +++++ b/net/ipv4/ipmr.c ++@@ -176,6 +176,7 @@ static int ipmr_rule_action(struct fib_r ++ case FR_ACT_UNREACHABLE: ++ return -ENETUNREACH; ++ case FR_ACT_PROHIBIT: +++ case FR_ACT_FAILED_POLICY: ++ return -EACCES; ++ case FR_ACT_BLACKHOLE: ++ default: ++--- a/net/ipv6/fib6_rules.c +++++ b/net/ipv6/fib6_rules.c ++@@ -70,6 +70,9 @@ static int fib6_rule_action(struct fib_r ++ case FR_ACT_PROHIBIT: ++ rt = net->ipv6.ip6_prohibit_entry; ++ goto discard_pkt; +++ case FR_ACT_FAILED_POLICY: +++ rt = net->ipv6.ip6_failed_policy_entry; +++ goto discard_pkt; ++ } ++ ++ table = fib6_get_table(net, rule->table); ++--- a/net/ipv6/ip6mr.c +++++ b/net/ipv6/ip6mr.c ++@@ -164,6 +164,8 @@ static int ip6mr_rule_action(struct fib_ ++ return -ENETUNREACH; ++ case FR_ACT_PROHIBIT: ++ return -EACCES; +++ case FR_ACT_FAILED_POLICY: +++ return -EPERM; ++ case FR_ACT_BLACKHOLE: ++ default: ++ return -EINVAL; ++--- a/net/ipv6/route.c +++++ b/net/ipv6/route.c ++@@ -228,6 +228,24 @@ static struct rt6_info ip6_prohibit_entr ++ .rt6i_ref = ATOMIC_INIT(1), ++ }; ++ +++static int ip6_pkt_failed_policy(struct sk_buff *skb); +++static int ip6_pkt_failed_policy_out(struct sk_buff *skb); +++ +++static const struct rt6_info ip6_failed_policy_entry_template = { +++ .dst = { +++ .__refcnt = ATOMIC_INIT(1), +++ .__use = 1, +++ .obsolete = -1, +++ .error = -EPERM, +++ .input = ip6_pkt_failed_policy, +++ .output = ip6_pkt_failed_policy_out, +++ }, +++ .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), +++ .rt6i_protocol = RTPROT_KERNEL, +++ .rt6i_metric = ~(u32) 0, +++ .rt6i_ref = ATOMIC_INIT(1), +++}; +++ ++ static struct rt6_info ip6_blk_hole_entry_template = { ++ .dst = { ++ .__refcnt = ATOMIC_INIT(1), ++@@ -1344,6 +1362,9 @@ int ip6_route_add(struct fib6_config *cf ++ case RTN_THROW: ++ rt->dst.error = -EAGAIN; ++ break; +++ case RTN_FAILED_POLICY: +++ rt->dst.error = -EPERM; +++ break; ++ default: ++ rt->dst.error = -ENETUNREACH; ++ break; ++@@ -2068,6 +2089,17 @@ static int ip6_pkt_prohibit_out(struct s ++ return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); ++ } ++ +++static int ip6_pkt_failed_policy(struct sk_buff *skb) +++{ +++ return ip6_pkt_drop(skb, ICMPV6_FAILED_POLICY, IPSTATS_MIB_INNOROUTES); +++} +++ +++static int ip6_pkt_failed_policy_out(struct sk_buff *skb) +++{ +++ skb->dev = skb_dst(skb)->dev; +++ return ip6_pkt_drop(skb, ICMPV6_FAILED_POLICY, IPSTATS_MIB_OUTNOROUTES); +++} +++ ++ #endif ++ ++ /* ++@@ -2283,7 +2315,8 @@ static int rtm_to_fib6_config(struct sk_ ++ if (rtm->rtm_type == RTN_UNREACHABLE || ++ rtm->rtm_type == RTN_BLACKHOLE || ++ rtm->rtm_type == RTN_PROHIBIT || ++- rtm->rtm_type == RTN_THROW) +++ rtm->rtm_type == RTN_THROW || +++ rtm->rtm_type == RTN_FAILED_POLICY) ++ cfg->fc_flags |= RTF_REJECT; ++ ++ if (rtm->rtm_type == RTN_LOCAL) ++@@ -2421,6 +2454,9 @@ static int rt6_fill_node(struct net *net ++ case -EACCES: ++ rtm->rtm_type = RTN_PROHIBIT; ++ break; +++ case -EPERM: +++ rtm->rtm_type = RTN_FAILED_POLICY; +++ break; ++ case -EAGAIN: ++ rtm->rtm_type = RTN_THROW; ++ break; ++@@ -2665,6 +2701,8 @@ static int ip6_route_dev_notify(struct n ++ #ifdef CONFIG_IPV6_MULTIPLE_TABLES ++ net->ipv6.ip6_prohibit_entry->dst.dev = dev; ++ net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); +++ net->ipv6.ip6_failed_policy_entry->dst.dev = dev; +++ net->ipv6.ip6_failed_policy_entry->rt6i_idev = in6_dev_get(dev); ++ net->ipv6.ip6_blk_hole_entry->dst.dev = dev; ++ net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); ++ #endif ++@@ -2925,6 +2963,17 @@ static int __net_init ip6_route_net_init ++ net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; ++ dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst, ++ ip6_template_metrics, true); +++ +++ net->ipv6.ip6_failed_policy_entry = +++ kmemdup(&ip6_failed_policy_entry_template, +++ sizeof(*net->ipv6.ip6_failed_policy_entry), GFP_KERNEL); +++ if (!net->ipv6.ip6_failed_policy_entry) +++ goto out_ip6_blk_hole_entry; +++ net->ipv6.ip6_failed_policy_entry->dst.path = +++ (struct dst_entry *)net->ipv6.ip6_failed_policy_entry; +++ net->ipv6.ip6_failed_policy_entry->dst.ops = &net->ipv6.ip6_dst_ops; +++ dst_init_metrics(&net->ipv6.ip6_failed_policy_entry->dst, +++ ip6_template_metrics, true); ++ #endif ++ ++ net->ipv6.sysctl.flush_delay = 0; ++@@ -2947,6 +2996,8 @@ out: ++ return ret; ++ ++ #ifdef CONFIG_IPV6_MULTIPLE_TABLES +++out_ip6_blk_hole_entry: +++ kfree(net->ipv6.ip6_blk_hole_entry); ++ out_ip6_prohibit_entry: ++ kfree(net->ipv6.ip6_prohibit_entry); ++ out_ip6_null_entry: ++@@ -2968,6 +3019,7 @@ static void __net_exit ip6_route_net_exi ++ #ifdef CONFIG_IPV6_MULTIPLE_TABLES ++ kfree(net->ipv6.ip6_prohibit_entry); ++ kfree(net->ipv6.ip6_blk_hole_entry); +++ kfree(net->ipv6.ip6_failed_policy_entry); ++ #endif ++ dst_entries_destroy(&net->ipv6.ip6_dst_ops); ++ } ++@@ -3013,6 +3065,9 @@ int __init ip6_route_init(void) ++ init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); ++ init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; ++ init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); +++ init_net.ipv6.ip6_failed_policy_entry->dst.dev = init_net.loopback_dev; +++ init_net.ipv6.ip6_failed_policy_entry->rt6i_idev = +++ in6_dev_get(init_net.loopback_dev); ++ #endif ++ ret = fib6_init(); ++ if (ret) +Index: patches-3.3/665-ipv6-fix-handling-of-blackhole-and-prohibit-routes.patch +=================================================================== +--- patches-3.3/665-ipv6-fix-handling-of-blackhole-and-prohibit-routes.patch (Revision 0) ++++ patches-3.3/665-ipv6-fix-handling-of-blackhole-and-prohibit-routes.patch (Revision 37768) +@@ -0,0 +1,67 @@ ++--- a/include/net/ip6_fib.h +++++ b/include/net/ip6_fib.h ++@@ -37,6 +37,7 @@ struct fib6_config { ++ int fc_ifindex; ++ u32 fc_flags; ++ u32 fc_protocol; +++ u32 fc_type; /* only 8 bits are used */ ++ ++ struct in6_addr fc_dst; ++ struct in6_addr fc_src; ++--- a/net/ipv6/route.c +++++ b/net/ipv6/route.c ++@@ -1333,8 +1333,18 @@ int ip6_route_add(struct fib6_config *cf ++ } ++ rt->dst.output = ip6_pkt_discard_out; ++ rt->dst.input = ip6_pkt_discard; ++- rt->dst.error = -ENETUNREACH; ++ rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP; +++ switch (cfg->fc_type) { +++ case RTN_BLACKHOLE: +++ rt->dst.error = -EINVAL; +++ break; +++ case RTN_PROHIBIT: +++ rt->dst.error = -EACCES; +++ break; +++ default: +++ rt->dst.error = -ENETUNREACH; +++ break; +++ } ++ goto install_route; ++ } ++ ++@@ -2265,8 +2275,11 @@ static int rtm_to_fib6_config(struct sk_ ++ cfg->fc_src_len = rtm->rtm_src_len; ++ cfg->fc_flags = RTF_UP; ++ cfg->fc_protocol = rtm->rtm_protocol; +++ cfg->fc_type = rtm->rtm_type; ++ ++- if (rtm->rtm_type == RTN_UNREACHABLE) +++ if (rtm->rtm_type == RTN_UNREACHABLE || +++ rtm->rtm_type == RTN_BLACKHOLE || +++ rtm->rtm_type == RTN_PROHIBIT) ++ cfg->fc_flags |= RTF_REJECT; ++ ++ if (rtm->rtm_type == RTN_LOCAL) ++@@ -2396,8 +2409,19 @@ static int rt6_fill_node(struct net *net ++ table = RT6_TABLE_UNSPEC; ++ rtm->rtm_table = table; ++ NLA_PUT_U32(skb, RTA_TABLE, table); ++- if (rt->rt6i_flags & RTF_REJECT) ++- rtm->rtm_type = RTN_UNREACHABLE; +++ if (rt->rt6i_flags & RTF_REJECT) { +++ switch (rt->dst.error) { +++ case -EINVAL: +++ rtm->rtm_type = RTN_BLACKHOLE; +++ break; +++ case -EACCES: +++ rtm->rtm_type = RTN_PROHIBIT; +++ break; +++ default: +++ rtm->rtm_type = RTN_UNREACHABLE; +++ break; +++ } +++ } ++ else if (rt->rt6i_flags & RTF_LOCAL) ++ rtm->rtm_type = RTN_LOCAL; ++ else if (rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK)) +Index: patches-3.3/721-phy_packets.patch +=================================================================== +--- patches-3.3/721-phy_packets.patch (Revision 35298) ++++ patches-3.3/721-phy_packets.patch (Revision 37768) +@@ -145,7 +145,7 @@ + + struct sk_buff *skb = __netdev_alloc_skb(dev, length + NET_IP_ALIGN, gfp); + + + +#ifdef CONFIG_ETHERNET_PACKET_MANGLE +-+ if (dev->priv_flags & IFF_NO_IP_ALIGN) +++ if (dev && (dev->priv_flags & IFF_NO_IP_ALIGN)) + + return skb; + +#endif + + +Index: patches-3.3/729-phy-tantos.patch +=================================================================== +--- patches-3.3/729-phy-tantos.patch (Revision 35298) ++++ patches-3.3/729-phy-tantos.patch (Revision 37768) +@@ -1,6 +1,6 @@ + --- a/drivers/net/phy/Kconfig + +++ b/drivers/net/phy/Kconfig +-@@ -206,3 +206,8 @@ endif # PHYLIB ++@@ -210,3 +210,8 @@ endif # PHYLIB + config MICREL_KS8995MA + tristate "Micrel KS8995MA 5-ports 10/100 managed Ethernet switch" + depends on SPI +@@ -11,8 +11,8 @@ + + select ETHERNET_PACKET_MANGLE + --- a/drivers/net/phy/Makefile + +++ b/drivers/net/phy/Makefile +-@@ -28,6 +28,7 @@ obj-$(CONFIG_RTL8366RB_PHY) += rtl8366rb +- obj-$(CONFIG_RTL8367_PHY) += rtl8367.o ++@@ -29,6 +29,7 @@ obj-$(CONFIG_RTL8367_PHY) += rtl8367.o ++ obj-$(CONFIG_RTL8367B_PHY) += rtl8367b.o + obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o + obj-$(CONFIG_MICREL_PHY) += micrel.o + +obj-$(CONFIG_PSB6970_PHY) += psb6970.o +Index: patches-3.3/090-CVE-2013-1763.patch +=================================================================== +--- patches-3.3/090-CVE-2013-1763.patch (Revision 0) ++++ patches-3.3/090-CVE-2013-1763.patch (Revision 37768) +@@ -0,0 +1,27 @@ ++From 6e601a53566d84e1ffd25e7b6fe0b6894ffd79c0 Mon Sep 17 00:00:00 2001 ++From: Mathias Krause ++Date: Sat, 23 Feb 2013 01:13:47 +0000 ++Subject: sock_diag: Fix out-of-bounds access to sock_diag_handlers[] ++ ++Userland can send a netlink message requesting SOCK_DIAG_BY_FAMILY ++with a family greater or equal then AF_MAX -- the array size of ++sock_diag_handlers[]. The current code does not test for this ++condition therefore is vulnerable to an out-of-bound access opening ++doors for a privilege escalation. ++ ++Signed-off-by: Mathias Krause ++Acked-by: Eric Dumazet ++Signed-off-by: David S. Miller ++--- ++--- a/net/core/sock_diag.c +++++ b/net/core/sock_diag.c ++@@ -126,6 +126,9 @@ static int __sock_diag_rcv_msg(struct sk ++ if (nlmsg_len(nlh) < sizeof(*req)) ++ return -EINVAL; ++ +++ if (req->sdiag_family >= AF_MAX) +++ return -EINVAL; +++ ++ hndl = sock_diag_lock_handler(req->sdiag_family); ++ if (hndl == NULL) ++ err = -ENOENT; +Index: patches-3.3/605-netfilter_conntrack_flush.patch +=================================================================== +--- patches-3.3/605-netfilter_conntrack_flush.patch (Revision 0) ++++ patches-3.3/605-netfilter_conntrack_flush.patch (Revision 37768) +@@ -0,0 +1,46 @@ ++--- a/net/netfilter/nf_conntrack_standalone.c +++++ b/net/netfilter/nf_conntrack_standalone.c ++@@ -267,10 +267,34 @@ static int ct_open(struct inode *inode, ++ sizeof(struct ct_iter_state)); ++ } ++ +++static int kill_all(struct nf_conn *i, void *data) +++{ +++ return 1; +++} +++ +++static ssize_t ct_file_write(struct file *file, const char __user *buf, +++ size_t count, loff_t *ppos) +++{ +++ struct seq_file *seq = file->private_data; +++ struct net *net = seq_file_net(seq); +++ +++ if (count) { +++ char c; +++ +++ if (get_user(c, buf)) +++ return -EFAULT; +++ +++ if (c == 'f') +++ nf_ct_iterate_cleanup(net, kill_all, NULL); +++ } +++ return count; +++} +++ ++ static const struct file_operations ct_file_ops = { ++ .owner = THIS_MODULE, ++ .open = ct_open, ++ .read = seq_read, +++ .write = ct_file_write, ++ .llseek = seq_lseek, ++ .release = seq_release_net, ++ }; ++@@ -372,7 +396,7 @@ static int nf_conntrack_standalone_init_ ++ { ++ struct proc_dir_entry *pde; ++ ++- pde = proc_net_fops_create(net, "nf_conntrack", 0440, &ct_file_ops); +++ pde = proc_net_fops_create(net, "nf_conntrack", 0660, &ct_file_ops); ++ if (!pde) ++ goto out_nf_conntrack; ++ +Index: patches-3.3/025-bcma_backport.patch +=================================================================== +--- patches-3.3/025-bcma_backport.patch (Revision 35298) ++++ patches-3.3/025-bcma_backport.patch (Revision 37768) +@@ -1,6 +1,32 @@ ++--- a/arch/mips/bcm47xx/serial.c +++++ b/arch/mips/bcm47xx/serial.c ++@@ -62,7 +62,7 @@ static int __init uart8250_init_bcma(voi ++ ++ p->mapbase = (unsigned int) bcma_port->regs; ++ p->membase = (void *) bcma_port->regs; ++- p->irq = bcma_port->irq + 2; +++ p->irq = bcma_port->irq; ++ p->uartclk = bcma_port->baud_base; ++ p->regshift = bcma_port->reg_shift; ++ p->iotype = UPIO_MEM; ++--- a/arch/mips/bcm47xx/gpio.c +++++ b/arch/mips/bcm47xx/gpio.c ++@@ -94,7 +94,7 @@ int gpio_to_irq(unsigned gpio) ++ #endif ++ #ifdef CONFIG_BCM47XX_BCMA ++ case BCM47XX_BUS_TYPE_BCMA: ++- return bcma_core_mips_irq(bcm47xx_bus.bcma.bus.drv_cc.core) + 2; +++ return bcma_core_irq(bcm47xx_bus.bcma.bus.drv_cc.core); ++ #endif ++ } ++ return -EINVAL; + --- a/drivers/bcma/Kconfig + +++ b/drivers/bcma/Kconfig +-@@ -29,7 +29,7 @@ config BCMA_HOST_PCI ++@@ -26,10 +26,11 @@ config BCMA_HOST_PCI_POSSIBLE ++ config BCMA_HOST_PCI ++ bool "Support for BCMA on PCI-host bus" ++ depends on BCMA_HOST_PCI_POSSIBLE +++ default y + + config BCMA_DRIVER_PCI_HOSTMODE + bool "Driver for PCI core working in hostmode" +@@ -9,7 +35,7 @@ + help + PCI core hostmode operation (external PCI bus). + +-@@ -46,6 +46,15 @@ config BCMA_DRIVER_MIPS ++@@ -46,6 +47,23 @@ config BCMA_DRIVER_MIPS + + If unsure, say N + +@@ -22,22 +48,31 @@ + + + + If unsure, say N + + +++config BCMA_DRIVER_GPIO +++ bool "BCMA GPIO driver" +++ depends on BCMA && GPIOLIB +++ help +++ Driver to provide access to the GPIO pins of the bcma bus. +++ +++ If unsure, say N +++ + config BCMA_DEBUG + bool "BCMA debugging" + depends on BCMA + --- a/drivers/bcma/Makefile + +++ b/drivers/bcma/Makefile +-@@ -3,6 +3,7 @@ bcma-y += driver_chipcommon.o driver ++@@ -3,6 +3,8 @@ bcma-y += driver_chipcommon.o driver + 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_DRIVER_GMAC_CMN) += driver_gmac_cmn.o +++bcma-$(CONFIG_BCMA_DRIVER_GPIO) += driver_gpio.o + bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o + bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o + obj-$(CONFIG_BCMA) += bcma.o + --- a/drivers/bcma/bcma_private.h + +++ b/drivers/bcma/bcma_private.h +-@@ -10,10 +10,19 @@ ++@@ -10,10 +10,21 @@ + + #define BCMA_CORE_SIZE 0x1000 + +@@ -54,35 +89,128 @@ + + /* main.c */ + -int bcma_bus_register(struct bcma_bus *bus); +++bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value, +++ int timeout); + +int __devinit 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, +-@@ -48,8 +57,12 @@ extern int __init bcma_host_pci_init(voi ++@@ -22,6 +33,8 @@ int __init bcma_bus_early_register(struc ++ int bcma_bus_suspend(struct bcma_bus *bus); ++ int bcma_bus_resume(struct bcma_bus *bus); ++ #endif +++struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid, +++ u8 unit); ++ ++ /* scan.c */ ++ int bcma_bus_scan(struct bcma_bus *bus); ++@@ -39,8 +52,8 @@ void bcma_chipco_serial_init(struct bcma ++ #endif /* CONFIG_BCMA_DRIVER_MIPS */ ++ ++ /* driver_chipcommon_pmu.c */ ++-u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc); ++-u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc); +++u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc); +++u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc); ++ ++ #ifdef CONFIG_BCMA_HOST_PCI ++ /* host_pci.c */ ++@@ -48,8 +61,29 @@ extern int __init bcma_host_pci_init(voi + extern void __exit bcma_host_pci_exit(void); + #endif /* CONFIG_BCMA_HOST_PCI */ + + +/* driver_pci.c */ + +u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address); + + +++extern int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc); +++ + #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE + -void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); + +bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc); + +void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); + #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ + +++#ifdef CONFIG_BCMA_DRIVER_GPIO +++/* driver_gpio.c */ +++int bcma_gpio_init(struct bcma_drv_cc *cc); +++int bcma_gpio_unregister(struct bcma_drv_cc *cc); +++#else +++static inline int bcma_gpio_init(struct bcma_drv_cc *cc) +++{ +++ return -ENOTSUPP; +++} +++static inline int bcma_gpio_unregister(struct bcma_drv_cc *cc) +++{ +++ return 0; +++} +++#endif /* CONFIG_BCMA_DRIVER_GPIO */ +++ + #endif + --- a/drivers/bcma/core.c + +++ b/drivers/bcma/core.c +-@@ -30,6 +30,7 @@ void bcma_core_disable(struct bcma_devic +- udelay(10); ++@@ -9,6 +9,25 @@ ++ #include ++ #include + +++static bool bcma_core_wait_value(struct bcma_device *core, u16 reg, u32 mask, +++ u32 value, int timeout) +++{ +++ unsigned long deadline = jiffies + timeout; +++ u32 val; +++ +++ do { +++ val = bcma_aread32(core, reg); +++ if ((val & mask) == value) +++ return true; +++ cpu_relax(); +++ udelay(10); +++ } while (!time_after_eq(jiffies, deadline)); +++ +++ bcma_warn(core->bus, "Timeout waiting for register 0x%04X!\n", reg); +++ +++ return false; +++} +++ ++ bool bcma_core_is_enabled(struct bcma_device *core) ++ { ++ if ((bcma_aread32(core, BCMA_IOCTL) & (BCMA_IOCTL_CLK | BCMA_IOCTL_FGC)) ++@@ -25,12 +44,15 @@ void bcma_core_disable(struct bcma_devic ++ if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET) ++ return; ++ ++- bcma_awrite32(core, BCMA_IOCTL, flags); ++- bcma_aread32(core, BCMA_IOCTL); ++- udelay(10); +++ bcma_core_wait_value(core, BCMA_RESET_ST, ~0, 0, 300); ++ + bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET); + + bcma_aread32(core, BCMA_RESET_CTL); + udelay(1); +++ +++ bcma_awrite32(core, BCMA_IOCTL, flags); +++ bcma_aread32(core, BCMA_IOCTL); +++ udelay(10); + } + EXPORT_SYMBOL_GPL(bcma_core_disable); +-@@ -74,10 +75,10 @@ void bcma_core_set_clockmode(struct bcma ++ ++@@ -42,6 +64,7 @@ int bcma_core_enable(struct bcma_device ++ bcma_aread32(core, BCMA_IOCTL); ++ ++ bcma_awrite32(core, BCMA_RESET_CTL, 0); +++ bcma_aread32(core, BCMA_RESET_CTL); ++ udelay(1); ++ ++ bcma_awrite32(core, BCMA_IOCTL, (BCMA_IOCTL_CLK | flags)); ++@@ -64,7 +87,7 @@ void bcma_core_set_clockmode(struct bcma ++ switch (clkmode) { ++ case BCMA_CLKMODE_FAST: ++ bcma_set32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT); ++- udelay(64); +++ usleep_range(64, 300); ++ for (i = 0; i < 1500; i++) { ++ if (bcma_read32(core, BCMA_CLKCTLST) & ++ BCMA_CLKCTLST_HAVEHT) { ++@@ -74,10 +97,10 @@ void bcma_core_set_clockmode(struct bcma + udelay(10); + } + if (i) +@@ -95,7 +223,7 @@ + break; + } + } +-@@ -101,9 +102,9 @@ void bcma_core_pll_ctl(struct bcma_devic ++@@ -101,9 +124,15 @@ void bcma_core_pll_ctl(struct bcma_devic + udelay(10); + } + if (i) +@@ -103,11 +231,17 @@ + + bcma_err(core->bus, "PLL enable timeout\n"); + } else { + - pr_warn("Disabling PLL not supported yet!\n"); +-+ bcma_warn(core->bus, "Disabling PLL not supported yet!\n"); +++ /* +++ * Mask the PLL but don't wait for it to be disabled. PLL may be +++ * shared between cores and will be still up if there is another +++ * core using it. +++ */ +++ bcma_mask32(core, BCMA_CLKCTLST, ~req); +++ bcma_read32(core, BCMA_CLKCTLST); + } + } + EXPORT_SYMBOL_GPL(bcma_core_pll_ctl); +-@@ -119,8 +120,8 @@ u32 bcma_core_dma_translation(struct bcm ++@@ -119,8 +148,8 @@ u32 bcma_core_dma_translation(struct bcm + else + return BCMA_DMA_TRANSLATION_DMA32_CMT; + default: +@@ -120,7 +254,158 @@ + } + --- a/drivers/bcma/driver_chipcommon.c + +++ b/drivers/bcma/driver_chipcommon.c +-@@ -44,7 +44,7 @@ void bcma_core_chipcommon_init(struct bc ++@@ -4,12 +4,15 @@ ++ * ++ * Copyright 2005, Broadcom Corporation ++ * Copyright 2006, 2007, Michael Buesch +++ * Copyright 2012, Hauke Mehrtens ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++ #include "bcma_private.h" +++#include ++ #include +++#include ++ #include ++ ++ static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, ++@@ -22,29 +25,136 @@ static inline u32 bcma_cc_write32_masked ++ return value; ++ } ++ ++-void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) +++u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc) ++ { ++- u32 leddc_on = 10; ++- u32 leddc_off = 90; +++ if (cc->capabilities & BCMA_CC_CAP_PMU) +++ return bcma_pmu_get_alp_clock(cc); ++ ++- if (cc->setup_done) +++ return 20000000; +++} +++EXPORT_SYMBOL_GPL(bcma_chipco_get_alp_clock); +++ +++static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc) +++{ +++ struct bcma_bus *bus = cc->core->bus; +++ u32 nb; +++ +++ if (cc->capabilities & BCMA_CC_CAP_PMU) { +++ if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) +++ nb = 32; +++ else if (cc->core->id.rev < 26) +++ nb = 16; +++ else +++ nb = (cc->core->id.rev >= 37) ? 32 : 24; +++ } else { +++ nb = 28; +++ } +++ if (nb == 32) +++ return 0xffffffff; +++ else +++ return (1 << nb) - 1; +++} +++ +++static u32 bcma_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, +++ u32 ticks) +++{ +++ struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt); +++ +++ return bcma_chipco_watchdog_timer_set(cc, ticks); +++} +++ +++static u32 bcma_chipco_watchdog_timer_set_ms_wdt(struct bcm47xx_wdt *wdt, +++ u32 ms) +++{ +++ struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt); +++ u32 ticks; +++ +++ ticks = bcma_chipco_watchdog_timer_set(cc, cc->ticks_per_ms * ms); +++ return ticks / cc->ticks_per_ms; +++} +++ +++static int bcma_chipco_watchdog_ticks_per_ms(struct bcma_drv_cc *cc) +++{ +++ struct bcma_bus *bus = cc->core->bus; +++ +++ 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 */ +++ return bcma_chipco_get_alp_clock(cc) / 4000; +++ else +++ /* based on 32KHz ILP clock */ +++ return 32; +++ } else { +++ return bcma_chipco_get_alp_clock(cc) / 1000; +++ } +++} +++ +++int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc) +++{ +++ struct bcm47xx_wdt wdt = {}; +++ struct platform_device *pdev; +++ +++ 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; +++ +++ pdev = platform_device_register_data(NULL, "bcm47xx-wdt", +++ cc->core->bus->num, &wdt, +++ sizeof(wdt)); +++ if (IS_ERR(pdev)) +++ return PTR_ERR(pdev); +++ +++ cc->watchdog = pdev; +++ +++ return 0; +++} +++ +++void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc) +++{ +++ if (cc->early_setup_done) ++ return; ++ +++ spin_lock_init(&cc->gpio_lock); +++ ++ if (cc->core->id.rev >= 11) ++ cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); ++ cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP); ++ if (cc->core->id.rev >= 35) ++ cc->capabilities_ext = bcma_cc_read32(cc, BCMA_CC_CAP_EXT); ++ +++ if (cc->capabilities & BCMA_CC_CAP_PMU) +++ bcma_pmu_early_init(cc); +++ +++ cc->early_setup_done = true; +++} +++ +++void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) +++{ +++ u32 leddc_on = 10; +++ u32 leddc_off = 90; +++ +++ if (cc->setup_done) +++ return; +++ +++ bcma_core_chipcommon_early_init(cc); +++ ++ if (cc->core->id.rev >= 20) { ++- bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, 0); ++- bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, 0); +++ u32 pullup = 0, pulldown = 0; +++ +++ if (cc->core->bus->chipinfo.id == BCMA_CHIP_ID_BCM43142) { +++ pullup = 0x402e0; +++ pulldown = 0x20500; +++ } +++ +++ bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, pullup); +++ bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, pulldown); ++ } ++ + if (cc->capabilities & BCMA_CC_CAP_PMU) + bcma_pmu_init(cc); + if (cc->capabilities & BCMA_CC_CAP_PCTL) +@@ -129,7 +414,159 @@ + + if (cc->core->id.rev >= 16) { + if (cc->core->bus->sprom.leddc_on_time && +-@@ -137,8 +137,7 @@ void bcma_chipco_serial_init(struct bcma ++@@ -56,15 +166,33 @@ void bcma_core_chipcommon_init(struct bc ++ ((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) | ++ (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT))); ++ } +++ cc->ticks_per_ms = bcma_chipco_watchdog_ticks_per_ms(cc); ++ ++ cc->setup_done = true; ++ } ++ ++ /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */ ++-void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks) +++u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks) ++ { ++- /* instant NMI */ ++- bcma_cc_write32(cc, BCMA_CC_WATCHDOG, ticks); +++ u32 maxt; +++ enum bcma_clkmode clkmode; +++ +++ maxt = bcma_chipco_watchdog_get_max_timer(cc); +++ if (cc->capabilities & BCMA_CC_CAP_PMU) { +++ if (ticks == 1) +++ ticks = 2; +++ else if (ticks > maxt) +++ 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); +++ if (ticks > maxt) +++ ticks = maxt; +++ /* instant NMI */ +++ bcma_cc_write32(cc, BCMA_CC_WATCHDOG, ticks); +++ } +++ return ticks; ++ } ++ ++ void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value) ++@@ -84,28 +212,99 @@ u32 bcma_chipco_gpio_in(struct bcma_drv_ ++ ++ u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value) ++ { ++- return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value); +++ unsigned long flags; +++ u32 res; +++ +++ spin_lock_irqsave(&cc->gpio_lock, flags); +++ res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value); +++ spin_unlock_irqrestore(&cc->gpio_lock, flags); +++ +++ return res; ++ } +++EXPORT_SYMBOL_GPL(bcma_chipco_gpio_out); ++ ++ u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value) ++ { ++- return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value); +++ unsigned long flags; +++ u32 res; +++ +++ spin_lock_irqsave(&cc->gpio_lock, flags); +++ res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value); +++ spin_unlock_irqrestore(&cc->gpio_lock, flags); +++ +++ return res; ++ } +++EXPORT_SYMBOL_GPL(bcma_chipco_gpio_outen); ++ +++/* +++ * If the bit is set to 0, chipcommon controlls this GPIO, +++ * if the bit is set to 1, it is used by some part of the chip and not our code. +++ */ ++ u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value) ++ { ++- return bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value); +++ unsigned long flags; +++ u32 res; +++ +++ spin_lock_irqsave(&cc->gpio_lock, flags); +++ res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value); +++ spin_unlock_irqrestore(&cc->gpio_lock, flags); +++ +++ return res; ++ } ++ EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control); ++ ++ u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value) ++ { ++- return bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value); +++ unsigned long flags; +++ u32 res; +++ +++ spin_lock_irqsave(&cc->gpio_lock, flags); +++ res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value); +++ spin_unlock_irqrestore(&cc->gpio_lock, flags); +++ +++ return res; ++ } ++ ++ u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value) ++ { ++- return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value); +++ unsigned long flags; +++ u32 res; +++ +++ spin_lock_irqsave(&cc->gpio_lock, flags); +++ res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value); +++ spin_unlock_irqrestore(&cc->gpio_lock, flags); +++ +++ return res; +++} +++ +++u32 bcma_chipco_gpio_pullup(struct bcma_drv_cc *cc, u32 mask, u32 value) +++{ +++ unsigned long flags; +++ u32 res; +++ +++ if (cc->core->id.rev < 20) +++ return 0; +++ +++ spin_lock_irqsave(&cc->gpio_lock, flags); +++ res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLUP, mask, value); +++ spin_unlock_irqrestore(&cc->gpio_lock, flags); +++ +++ return res; +++} +++ +++u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value) +++{ +++ unsigned long flags; +++ u32 res; +++ +++ if (cc->core->id.rev < 20) +++ return 0; +++ +++ spin_lock_irqsave(&cc->gpio_lock, flags); +++ res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLDOWN, mask, value); +++ spin_unlock_irqrestore(&cc->gpio_lock, flags); +++ +++ return res; ++ } ++ ++ #ifdef CONFIG_BCMA_DRIVER_MIPS ++@@ -118,8 +317,7 @@ void bcma_chipco_serial_init(struct bcma ++ struct bcma_serial_port *ports = cc->serial_ports; ++ ++ if (ccrev >= 11 && ccrev != 15) { ++- /* Fixed ALP clock */ ++- baud_base = bcma_pmu_alp_clock(cc); +++ baud_base = bcma_chipco_get_alp_clock(cc); ++ if (ccrev >= 21) { ++ /* Turn off UART clock before switching clocksource. */ ++ bcma_cc_write32(cc, BCMA_CC_CORECTL, ++@@ -137,12 +335,11 @@ void bcma_chipco_serial_init(struct bcma + | BCMA_CC_CORECTL_UARTCLKEN); + } + } else { +@@ -139,6 +576,11 @@ + return; + } + ++- irq = bcma_core_mips_irq(cc->core); +++ irq = bcma_core_irq(cc->core); ++ ++ /* Determine the registers of the UARTs */ ++ cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART); + --- a/drivers/bcma/driver_chipcommon_pmu.c + +++ b/drivers/bcma/driver_chipcommon_pmu.c + @@ -3,7 +3,8 @@ +@@ -151,29 +593,136 @@ + * + * Licensed under the GNU/GPL. See COPYING for details. + */ +-@@ -54,38 +55,19 @@ void bcma_chipco_regctl_maskset(struct b ++@@ -12,12 +13,13 @@ ++ #include ++ #include ++ ++-static u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset) +++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); + } +++EXPORT_SYMBOL_GPL(bcma_chipco_pll_read); ++ ++ void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value) ++ { ++@@ -54,19 +56,106 @@ void bcma_chipco_regctl_maskset(struct b ++ } + EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset); + +--static void bcma_pmu_pll_init(struct bcma_drv_cc *cc) +--{ +-- struct bcma_bus *bus = cc->core->bus; +-- +-- switch (bus->chipinfo.id) { +++static u32 bcma_pmu_xtalfreq(struct bcma_drv_cc *cc) +++{ +++ u32 ilp_ctl, alp_hz; +++ +++ if (!(bcma_cc_read32(cc, BCMA_CC_PMU_STAT) & +++ BCMA_CC_PMU_STAT_EXT_LPO_AVAIL)) +++ return 0; +++ +++ bcma_cc_write32(cc, BCMA_CC_PMU_XTAL_FREQ, +++ BIT(BCMA_CC_PMU_XTAL_FREQ_MEASURE_SHIFT)); +++ usleep_range(1000, 2000); +++ +++ ilp_ctl = bcma_cc_read32(cc, BCMA_CC_PMU_XTAL_FREQ); +++ ilp_ctl &= BCMA_CC_PMU_XTAL_FREQ_ILPCTL_MASK; +++ +++ bcma_cc_write32(cc, BCMA_CC_PMU_XTAL_FREQ, 0); +++ +++ alp_hz = ilp_ctl * 32768 / 4; +++ return (alp_hz + 50000) / 100000 * 100; +++} +++ +++static void bcma_pmu2_pll_init0(struct bcma_drv_cc *cc, u32 xtalfreq) +++{ +++ struct bcma_bus *bus = cc->core->bus; +++ u32 freq_tgt_target = 0, freq_tgt_current; +++ u32 pll0, mask; +++ +++ switch (bus->chipinfo.id) { +++ case BCMA_CHIP_ID_BCM43142: +++ /* pmu2_xtaltab0_adfll_485 */ +++ switch (xtalfreq) { +++ case 12000: +++ freq_tgt_target = 0x50D52; +++ break; +++ case 20000: +++ freq_tgt_target = 0x307FE; +++ break; +++ case 26000: +++ freq_tgt_target = 0x254EA; +++ break; +++ case 37400: +++ freq_tgt_target = 0x19EF8; +++ break; +++ case 52000: +++ freq_tgt_target = 0x12A75; +++ break; +++ } +++ break; +++ } +++ +++ if (!freq_tgt_target) { +++ bcma_err(bus, "Unknown TGT frequency for xtalfreq %d\n", +++ xtalfreq); +++ return; +++ } +++ +++ pll0 = bcma_chipco_pll_read(cc, BCMA_CC_PMU15_PLL_PLLCTL0); +++ freq_tgt_current = (pll0 & BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK) >> +++ BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT; +++ +++ if (freq_tgt_current == freq_tgt_target) { +++ bcma_debug(bus, "Target TGT frequency already set\n"); +++ return; +++ } +++ +++ /* Turn off PLL */ +++ switch (bus->chipinfo.id) { +++ case BCMA_CHIP_ID_BCM43142: +++ mask = (u32)~(BCMA_RES_4314_HT_AVAIL | +++ BCMA_RES_4314_MACPHY_CLK_AVAIL); +++ +++ bcma_cc_mask32(cc, BCMA_CC_PMU_MINRES_MSK, mask); +++ bcma_cc_mask32(cc, BCMA_CC_PMU_MAXRES_MSK, mask); +++ bcma_wait_value(cc->core, BCMA_CLKCTLST, +++ BCMA_CLKCTLST_HAVEHT, 0, 20000); +++ break; +++ } +++ +++ pll0 &= ~BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK; +++ pll0 |= freq_tgt_target << BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT; +++ bcma_chipco_pll_write(cc, BCMA_CC_PMU15_PLL_PLLCTL0, pll0); +++ +++ /* Flush */ +++ if (cc->pmu.rev >= 2) +++ bcma_cc_set32(cc, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD); +++ +++ /* TODO: Do we need to update OTP? */ +++} +++ ++ static void bcma_pmu_pll_init(struct bcma_drv_cc *cc) ++ { ++ struct bcma_bus *bus = cc->core->bus; +++ u32 xtalfreq = bcma_pmu_xtalfreq(cc); ++ ++ switch (bus->chipinfo.id) { + - case 0x4313: + - case 0x4331: + - case 43224: + - case 43225: +-- break; +++ case BCMA_CHIP_ID_BCM43142: +++ if (xtalfreq == 0) +++ xtalfreq = 20000; +++ bcma_pmu2_pll_init0(cc, xtalfreq); ++ break; + - default: + - pr_err("PLL init unknown for device 0x%04X\n", + - bus->chipinfo.id); +-- } +--} +-- +- static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) +- { +- struct bcma_bus *bus = cc->core->bus; ++ } ++ } ++ ++@@ -76,16 +165,32 @@ static void bcma_pmu_resources_init(stru + u32 min_msk = 0, max_msk = 0; + + switch (bus->chipinfo.id) { +@@ -184,7 +733,25 @@ + break; + - case 43224: + - case 43225: +-- break; +++ case BCMA_CHIP_ID_BCM43142: +++ min_msk = BCMA_RES_4314_LPLDO_PU | +++ BCMA_RES_4314_PMU_SLEEP_DIS | +++ BCMA_RES_4314_PMU_BG_PU | +++ BCMA_RES_4314_CBUCK_LPOM_PU | +++ BCMA_RES_4314_CBUCK_PFM_PU | +++ BCMA_RES_4314_CLDO_PU | +++ BCMA_RES_4314_LPLDO2_LVM | +++ BCMA_RES_4314_WL_PMU_PU | +++ BCMA_RES_4314_LDO3P3_PU | +++ BCMA_RES_4314_OTP_PU | +++ BCMA_RES_4314_WL_PWRSW_PU | +++ BCMA_RES_4314_LQ_AVAIL | +++ BCMA_RES_4314_LOGIC_RET | +++ BCMA_RES_4314_MEM_SLEEP | +++ BCMA_RES_4314_MACPHY_RET | +++ BCMA_RES_4314_WL_CORE_READY; +++ max_msk = 0x3FFFFFFF; ++ break; + default: + - pr_err("PMU resource config unknown for device 0x%04X\n", + - bus->chipinfo.id); +@@ -193,16 +760,16 @@ + } + + /* Set the resource masks. */ +-@@ -93,22 +75,9 @@ static void bcma_pmu_resources_init(stru ++@@ -93,22 +198,12 @@ static void bcma_pmu_resources_init(stru + bcma_cc_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk); + if (max_msk) + bcma_cc_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk); + -} +-- ++ + -void bcma_pmu_swreg_init(struct bcma_drv_cc *cc) + -{ + - struct bcma_bus *bus = cc->core->bus; +- ++- + - switch (bus->chipinfo.id) { + - case 0x4313: + - case 0x4331: +@@ -213,12 +780,15 @@ + - pr_err("PMU switch/regulators init unknown for device " + - "0x%04X\n", bus->chipinfo.id); + - } +-+ /* Add some delay; allow resources to come up and settle. */ +++ /* +++ * Add some delay; allow resources to come up and settle. +++ * Delay is required for SoC (early init). +++ */ + + mdelay(2); + } + + /* Disable to allow reading SPROM. Don't know the adventages of enabling it. */ +-@@ -122,8 +91,11 @@ void bcma_chipco_bcm4331_ext_pa_lines_ct ++@@ -122,51 +217,69 @@ void bcma_chipco_bcm4331_ext_pa_lines_ct + val |= BCMA_CHIPCTL_4331_EXTPA_EN; + if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11) + val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; +@@ -230,7 +800,11 @@ + val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; + } + bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val); +-@@ -134,26 +106,38 @@ void bcma_pmu_workarounds(struct bcma_dr ++ } ++ ++-void bcma_pmu_workarounds(struct bcma_drv_cc *cc) +++static void bcma_pmu_workarounds(struct bcma_drv_cc *cc) ++ { + struct bcma_bus *bus = cc->core->bus; + + switch (bus->chipinfo.id) { +@@ -240,7 +814,7 @@ + + /* enable 12 mA drive strenth for 4313 and set chipControl + + register bit 1 */ + + bcma_chipco_chipctl_maskset(cc, 0, +-+ BCMA_CCTRL_4313_12MA_LED_DRIVE, +++ ~BCMA_CCTRL_4313_12MA_LED_DRIVE, + + BCMA_CCTRL_4313_12MA_LED_DRIVE); + break; + - case 0x4331: +@@ -260,15 +834,15 @@ + - "implemented\n"); + - bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x00F000F0); + + bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL, +-+ BCMA_CCTRL_43224_GPIO_TOGGLE, +++ ~BCMA_CCTRL_43224_GPIO_TOGGLE, + + BCMA_CCTRL_43224_GPIO_TOGGLE); + + bcma_chipco_chipctl_maskset(cc, 0, +-+ BCMA_CCTRL_43224A0_12MA_LED_DRIVE, +++ ~BCMA_CCTRL_43224A0_12MA_LED_DRIVE, + + BCMA_CCTRL_43224A0_12MA_LED_DRIVE); + } else { + - bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0); + + bcma_chipco_chipctl_maskset(cc, 0, +-+ BCMA_CCTRL_43224B0_12MA_LED_DRIVE, +++ ~BCMA_CCTRL_43224B0_12MA_LED_DRIVE, + + BCMA_CCTRL_43224B0_12MA_LED_DRIVE); + } + break; +@@ -282,7 +856,11 @@ + } + } + +-@@ -164,8 +148,8 @@ void bcma_pmu_init(struct bcma_drv_cc *c ++-void bcma_pmu_init(struct bcma_drv_cc *cc) +++void bcma_pmu_early_init(struct bcma_drv_cc *cc) ++ { ++ u32 pmucap; ++ + pmucap = bcma_cc_read32(cc, BCMA_CC_PMU_CAP); + cc->pmu.rev = (pmucap & BCMA_CC_PMU_CAP_REVISION); + +@@ -290,23 +868,29 @@ + - pmucap); + + bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n", + + cc->pmu.rev, pmucap); +++} + +++void bcma_pmu_init(struct bcma_drv_cc *cc) +++{ + if (cc->pmu.rev == 1) + bcma_cc_mask32(cc, BCMA_CC_PMU_CTL, +-@@ -174,12 +158,7 @@ void bcma_pmu_init(struct bcma_drv_cc *c ++ ~BCMA_CC_PMU_CTL_NOILPONW); ++@@ -174,37 +287,48 @@ void bcma_pmu_init(struct bcma_drv_cc *c + bcma_cc_set32(cc, BCMA_CC_PMU_CTL, + BCMA_CC_PMU_CTL_NOILPONW); + + - if (cc->core->id.id == 0x4329 && cc->core->id.rev == 2) + - pr_err("Fix for 4329b0 bad LPOM state not implemented!\n"); + - +-- bcma_pmu_pll_init(cc); ++ bcma_pmu_pll_init(cc); + bcma_pmu_resources_init(cc); + - bcma_pmu_swreg_init(cc); + bcma_pmu_workarounds(cc); + } + +-@@ -188,23 +167,22 @@ u32 bcma_pmu_alp_clock(struct bcma_drv_c ++-u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc) +++u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc) ++ { + struct bcma_bus *bus = cc->core->bus; + + switch (bus->chipinfo.id) { +@@ -317,21 +901,37 @@ + - case 0x5357: + - case 0x4749: + - case 53572: +++ case BCMA_CHIP_ID_BCM4313: +++ case BCMA_CHIP_ID_BCM43224: +++ case BCMA_CHIP_ID_BCM43225: +++ case BCMA_CHIP_ID_BCM43227: +++ case BCMA_CHIP_ID_BCM43228: +++ case BCMA_CHIP_ID_BCM4331: +++ case BCMA_CHIP_ID_BCM43421: +++ case BCMA_CHIP_ID_BCM43428: +++ case BCMA_CHIP_ID_BCM43431: + + case BCMA_CHIP_ID_BCM4716: +++ case BCMA_CHIP_ID_BCM47162: + + case BCMA_CHIP_ID_BCM4748: +-+ case BCMA_CHIP_ID_BCM47162: +-+ case BCMA_CHIP_ID_BCM4313: +++ case BCMA_CHIP_ID_BCM4749: + + case BCMA_CHIP_ID_BCM5357: +-+ case BCMA_CHIP_ID_BCM4749: + + case BCMA_CHIP_ID_BCM53572: +++ case BCMA_CHIP_ID_BCM6362: + /* always 20Mhz */ + return 20000 * 1000; + - case 0x5356: + - case 0x5300: +++ case BCMA_CHIP_ID_BCM4706: + + case BCMA_CHIP_ID_BCM5356: +-+ case BCMA_CHIP_ID_BCM4706: + /* always 25Mhz */ + return 25000 * 1000; +++ case BCMA_CHIP_ID_BCM43460: +++ case BCMA_CHIP_ID_BCM4352: +++ case BCMA_CHIP_ID_BCM4360: +++ if (cc->status & BCMA_CC_CHIPST_4360_XTAL_40MZ) +++ return 40000 * 1000; +++ else +++ return 20000 * 1000; + default: + - pr_warn("No ALP clock specified for %04X device, " + - "pmu rev. %d, using default %d Hz\n", +@@ -341,7 +941,16 @@ + } + return BCMA_CC_PMU_ALP_CLOCK; + } +-@@ -221,7 +199,8 @@ static u32 bcma_pmu_clock(struct bcma_dr ++@@ -212,7 +336,7 @@ u32 bcma_pmu_alp_clock(struct bcma_drv_c ++ /* 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) +++static u32 bcma_pmu_pll_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m) ++ { ++ u32 tmp, div, ndiv, p1, p2, fc; ++ struct bcma_bus *bus = cc->core->bus; ++@@ -221,7 +345,8 @@ static u32 bcma_pmu_clock(struct bcma_dr + + BUG_ON(!m || m > 4); + +@@ -351,11 +960,19 @@ + /* Detect failure in clock setting */ + tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); + if (tmp & 0x40000) +-@@ -247,33 +226,62 @@ static u32 bcma_pmu_clock(struct bcma_dr ++@@ -240,60 +365,96 @@ static u32 bcma_pmu_clock(struct bcma_dr ++ ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT; ++ ++ /* Do calculation in Mhz */ ++- fc = bcma_pmu_alp_clock(cc) / 1000000; +++ fc = bcma_pmu_get_alp_clock(cc) / 1000000; ++ fc = (p1 * ndiv * fc) / p2; ++ ++ /* Return clock in Hertz */ + return (fc / div) * 1000000; + } + +-+static u32 bcma_pmu_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m) +++static u32 bcma_pmu_pll_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m) + +{ + + u32 tmp, ndiv, p1div, p2div; + + u32 clock; +@@ -386,7 +1003,8 @@ + +} + + + /* query bus clock frequency for PMU-enabled chipcommon */ +- u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc) ++-u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc) +++u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc) + { + struct bcma_bus *bus = cc->core->bus; + +@@ -394,40 +1012,51 @@ + - case 0x4716: + - case 0x4748: + - case 47162: +-+ case BCMA_CHIP_ID_BCM4716: +-+ case BCMA_CHIP_ID_BCM4748: +-+ case BCMA_CHIP_ID_BCM47162: +- return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0, +- BCMA_CC_PMU5_MAINPLL_SSB); ++- return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0, ++- BCMA_CC_PMU5_MAINPLL_SSB); + - case 0x5356: +-+ case BCMA_CHIP_ID_BCM5356: +- return bcma_pmu_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0, +- BCMA_CC_PMU5_MAINPLL_SSB); ++- return bcma_pmu_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0, ++- BCMA_CC_PMU5_MAINPLL_SSB); + - case 0x5357: + - case 0x4749: +-+ case BCMA_CHIP_ID_BCM5357: +-+ case BCMA_CHIP_ID_BCM4749: +- return bcma_pmu_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0, +- BCMA_CC_PMU5_MAINPLL_SSB); ++- return bcma_pmu_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0, ++- BCMA_CC_PMU5_MAINPLL_SSB); + - case 0x5300: + - return bcma_pmu_clock(cc, BCMA_CC_PMU4706_MAINPLL_PLL0, + - BCMA_CC_PMU5_MAINPLL_SSB); + - case 53572: +++ case BCMA_CHIP_ID_BCM4716: +++ case BCMA_CHIP_ID_BCM4748: +++ case BCMA_CHIP_ID_BCM47162: +++ return bcma_pmu_pll_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0, +++ BCMA_CC_PMU5_MAINPLL_SSB); +++ case BCMA_CHIP_ID_BCM5356: +++ return bcma_pmu_pll_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0, +++ BCMA_CC_PMU5_MAINPLL_SSB); +++ case BCMA_CHIP_ID_BCM5357: +++ case BCMA_CHIP_ID_BCM4749: +++ return bcma_pmu_pll_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0, +++ BCMA_CC_PMU5_MAINPLL_SSB); + + case BCMA_CHIP_ID_BCM4706: +-+ return bcma_pmu_clock_bcm4706(cc, BCMA_CC_PMU4706_MAINPLL_PLL0, +-+ BCMA_CC_PMU5_MAINPLL_SSB); +++ return bcma_pmu_pll_clock_bcm4706(cc, +++ BCMA_CC_PMU4706_MAINPLL_PLL0, +++ BCMA_CC_PMU5_MAINPLL_SSB); + + case BCMA_CHIP_ID_BCM53572: + return 75000000; + 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); +-+ bcma_warn(bus, "No backplane clock specified for %04X device, pmu rev. %d, using default %d Hz\n", +++ bcma_warn(bus, "No bus 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; + } +-@@ -283,17 +291,21 @@ u32 bcma_pmu_get_clockcpu(struct bcma_dr +++EXPORT_SYMBOL_GPL(bcma_pmu_get_bus_clock); ++ ++ /* query cpu clock frequency for PMU-enabled chipcommon */ ++-u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc) +++u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc) + { + struct bcma_bus *bus = cc->core->bus; + +@@ -435,12 +1064,13 @@ + + if (bus->chipinfo.id == BCMA_CHIP_ID_BCM53572) + return 300000000; + +++ /* New PMUs can have different clock for bus and CPU */ + if (cc->pmu.rev >= 5) { + u32 pll; + switch (bus->chipinfo.id) { + - case 0x5356: + + case BCMA_CHIP_ID_BCM4706: +-+ return bcma_pmu_clock_bcm4706(cc, +++ return bcma_pmu_pll_clock_bcm4706(cc, + + BCMA_CC_PMU4706_MAINPLL_PLL0, + + BCMA_CC_PMU5_MAINPLL_CPU); + + case BCMA_CHIP_ID_BCM5356: +@@ -453,18 +1083,20 @@ + pll = BCMA_CC_PMU5357_MAINPLL_PLL0; + break; + default: +-@@ -301,10 +313,188 @@ u32 bcma_pmu_get_clockcpu(struct bcma_dr ++@@ -301,10 +462,189 @@ u32 bcma_pmu_get_clockcpu(struct bcma_dr + break; + } + + - /* TODO: if (bus->chipinfo.id == 0x5300) + - return si_4706_pmu_clock(sih, osh, cc, PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_CPU); */ +- return bcma_pmu_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU); +- } +- +- return bcma_pmu_get_clockcontrol(cc); +- } ++- return bcma_pmu_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU); +++ return bcma_pmu_pll_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU); +++ } + + +++ /* On old PMUs CPU has the same clock as the bus */ +++ return bcma_pmu_get_bus_clock(cc); +++} +++ + +static void bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc *cc, u32 offset, + + u32 value) + +{ +@@ -508,7 +1140,7 @@ + + tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT; + + bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp); + + +-+ tmp = 1 << 10; +++ tmp = BCMA_CC_PMU_CTL_PLL_UPD; + + break; + + + + case BCMA_CHIP_ID_BCM4331: +@@ -529,7 +1161,7 @@ + + bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, + + 0x03000a08); + + } +-+ tmp = 1 << 10; +++ tmp = BCMA_CC_PMU_CTL_PLL_UPD; + + break; + + + + case BCMA_CHIP_ID_BCM43224: +@@ -562,7 +1194,7 @@ + + bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, + + 0x88888815); + + } +-+ tmp = 1 << 10; +++ tmp = BCMA_CC_PMU_CTL_PLL_UPD; + + break; + + + + case BCMA_CHIP_ID_BCM4716: +@@ -596,7 +1228,7 @@ + + 0x88888815); + + } + + +-+ tmp = 3 << 9; +++ tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW; + + break; + + + + case BCMA_CHIP_ID_BCM43227: +@@ -632,17 +1264,18 @@ + + bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, + + 0x88888815); + + } +-+ tmp = 1 << 10; +++ tmp = BCMA_CC_PMU_CTL_PLL_UPD; + + break; + + default: + + bcma_err(bus, "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n", + + bus->chipinfo.id); + + break; +-+ } +-+ ++ } ++ ++- return bcma_pmu_get_clockcontrol(cc); + + tmp |= bcma_cc_read32(cc, BCMA_CC_PMU_CTL); + + bcma_cc_write32(cc, BCMA_CC_PMU_CTL, tmp); +-+} ++ } + +EXPORT_SYMBOL_GPL(bcma_pmu_spuravoid_pllupdate); + --- /dev/null + +++ b/drivers/bcma/driver_gmac_cmn.c +@@ -661,6 +1294,123 @@ + +{ + + mutex_init(&gc->phy_mutex); + +} ++--- /dev/null +++++ b/drivers/bcma/driver_gpio.c ++@@ -0,0 +1,114 @@ +++/* +++ * Broadcom specific AMBA +++ * GPIO driver +++ * +++ * Copyright 2011, Broadcom Corporation +++ * Copyright 2012, Hauke Mehrtens +++ * +++ * Licensed under the GNU/GPL. See COPYING for details. +++ */ +++ +++#include +++#include +++#include +++ +++#include "bcma_private.h" +++ +++static inline struct bcma_drv_cc *bcma_gpio_get_cc(struct gpio_chip *chip) +++{ +++ return container_of(chip, struct bcma_drv_cc, gpio); +++} +++ +++static int bcma_gpio_get_value(struct gpio_chip *chip, unsigned gpio) +++{ +++ struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); +++ +++ return !!bcma_chipco_gpio_in(cc, 1 << gpio); +++} +++ +++static void bcma_gpio_set_value(struct gpio_chip *chip, unsigned gpio, +++ int value) +++{ +++ struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); +++ +++ bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0); +++} +++ +++static int bcma_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) +++{ +++ struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); +++ +++ bcma_chipco_gpio_outen(cc, 1 << gpio, 0); +++ return 0; +++} +++ +++static int bcma_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, +++ int value) +++{ +++ struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); +++ +++ bcma_chipco_gpio_outen(cc, 1 << gpio, 1 << gpio); +++ bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0); +++ return 0; +++} +++ +++static int bcma_gpio_request(struct gpio_chip *chip, unsigned gpio) +++{ +++ struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); +++ +++ bcma_chipco_gpio_control(cc, 1 << gpio, 0); +++ /* clear pulldown */ +++ bcma_chipco_gpio_pulldown(cc, 1 << gpio, 0); +++ /* Set pullup */ +++ bcma_chipco_gpio_pullup(cc, 1 << gpio, 1 << gpio); +++ +++ return 0; +++} +++ +++static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio) +++{ +++ struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); +++ +++ /* clear pullup */ +++ bcma_chipco_gpio_pullup(cc, 1 << gpio, 0); +++} +++ +++static int bcma_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) +++{ +++ struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); +++ +++ if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC) +++ return bcma_core_irq(cc->core); +++ else +++ return -EINVAL; +++} +++ +++int bcma_gpio_init(struct bcma_drv_cc *cc) +++{ +++ struct gpio_chip *chip = &cc->gpio; +++ +++ chip->label = "bcma_gpio"; +++ chip->owner = THIS_MODULE; +++ chip->request = bcma_gpio_request; +++ chip->free = bcma_gpio_free; +++ chip->get = bcma_gpio_get_value; +++ chip->set = bcma_gpio_set_value; +++ chip->direction_input = bcma_gpio_direction_input; +++ chip->direction_output = bcma_gpio_direction_output; +++ chip->to_irq = bcma_gpio_to_irq; +++ chip->ngpio = 16; +++ /* There is just one SoC in one device and its GPIO addresses should be +++ * deterministic to address them more easily. The other buses could get +++ * a random base number. */ +++ if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC) +++ chip->base = 0; +++ else +++ chip->base = -1; +++ +++ return gpiochip_add(chip); +++} +++ +++int bcma_gpio_unregister(struct bcma_drv_cc *cc) +++{ +++ return gpiochip_remove(&cc->gpio); +++} + --- a/drivers/bcma/driver_mips.c + +++ b/drivers/bcma/driver_mips.c + @@ -22,15 +22,15 @@ +@@ -683,27 +1433,144 @@ + dev->bus->chipinfo.pkg == 11 && + dev->id.id == BCMA_CORE_USB20_HOST; + } +-@@ -143,8 +143,8 @@ static void bcma_core_mips_set_irq(struc ++@@ -74,28 +74,41 @@ static u32 bcma_core_mips_irqflag(struct ++ return dev->core_index; ++ flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30); ++ ++- return flag & 0x1F; +++ if (flag) +++ return flag & 0x1F; +++ else +++ return 0x3f; ++ } ++ ++ /* Get the MIPS IRQ assignment for a specified device. ++ * If unassigned, 0 is returned. +++ * If disabled, 5 is returned. +++ * If not supported, 6 is returned. ++ */ ++-unsigned int bcma_core_mips_irq(struct bcma_device *dev) +++static 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); +++ if (irqflag == 0x3f) +++ return 6; ++ ++- for (irq = 1; irq <= 4; irq++) +++ for (irq = 0; irq <= 4; irq++) ++ if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) & ++ (1 << irqflag)) ++ return irq; ++ ++- return 0; +++ return 5; +++} +++ +++unsigned int bcma_core_irq(struct bcma_device *dev) +++{ +++ unsigned int mips_irq = bcma_core_mips_irq(dev); +++ return mips_irq <= 4 ? mips_irq + 2 : 0; ++ } ++-EXPORT_SYMBOL(bcma_core_mips_irq); +++EXPORT_SYMBOL(bcma_core_irq); ++ ++ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq) ++ { ++@@ -114,8 +127,8 @@ static void bcma_core_mips_set_irq(struc ++ 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); +++ else if (oldirq != 5) +++ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0); ++ ++ /* assign the new one */ ++ if (irq == 0) { ++@@ -123,17 +136,17 @@ static void bcma_core_mips_set_irq(struc ++ bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) | ++ (1 << irqflag)); ++ } else { ++- u32 oldirqflag = bcma_read32(mdev, ++- BCMA_MIPS_MIPS74K_INTMASK(irq)); ++- if (oldirqflag) { +++ u32 irqinitmask = bcma_read32(mdev, +++ BCMA_MIPS_MIPS74K_INTMASK(irq)); +++ if (irqinitmask) { ++ 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) { +++ list_for_each_entry(core, &bus->cores, list) { ++ if ((1 << bcma_core_mips_irqflag(core)) == ++- oldirqflag) { +++ irqinitmask) { ++ bcma_core_mips_set_irq(core, 0); ++ break; ++ } ++@@ -143,15 +156,31 @@ static void bcma_core_mips_set_irq(struc + 1 << irqflag); + } + + - pr_info("set_irq: core 0x%04x, irq %d => %d\n", + - dev->id.id, oldirq + 2, irq + 2); +-+ bcma_info(bus, "set_irq: core 0x%04x, irq %d => %d\n", +-+ dev->id.id, oldirq + 2, irq + 2); +++ bcma_debug(bus, "set_irq: core 0x%04x, irq %d => %d\n", +++ dev->id.id, oldirq <= 4 ? oldirq + 2 : 0, irq + 2); +++} +++ +++static void bcma_core_mips_set_irq_name(struct bcma_bus *bus, unsigned int irq, +++ u16 coreid, u8 unit) +++{ +++ struct bcma_device *core; +++ +++ core = bcma_find_core_unit(bus, coreid, unit); +++ if (!core) { +++ bcma_warn(bus, +++ "Can not find core (id: 0x%x, unit %i) for IRQ configuration.\n", +++ coreid, unit); +++ return; +++ } +++ +++ bcma_core_mips_set_irq(core, irq); + } + + static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq) +-@@ -173,7 +173,7 @@ u32 bcma_cpu_clock(struct bcma_drv_mips ++ { ++ 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); +++ printk(KERN_DEBUG 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"); ++@@ -161,7 +190,7 @@ static void bcma_core_mips_dump_irq(stru ++ { ++ struct bcma_device *core; ++ ++- list_for_each_entry_reverse(core, &bus->cores, list) { +++ list_for_each_entry(core, &bus->cores, list) { ++ bcma_core_mips_print_irq(core, bcma_core_mips_irq(core)); ++ } ++ } ++@@ -171,9 +200,9 @@ u32 bcma_cpu_clock(struct bcma_drv_mips ++ struct bcma_bus *bus = mcore->core->bus; ++ + if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU) +- return bcma_pmu_get_clockcpu(&bus->drv_cc); ++- return bcma_pmu_get_clockcpu(&bus->drv_cc); +++ return bcma_pmu_get_cpu_clock(&bus->drv_cc); + + - pr_err("No PMU available, need this to get the cpu clock\n"); + + bcma_err(bus, "No PMU available, need this to get the cpu clock\n"); + return 0; + } + EXPORT_SYMBOL(bcma_cpu_clock); +-@@ -185,10 +185,10 @@ static void bcma_core_mips_flash_detect( ++@@ -185,10 +214,10 @@ static void bcma_core_mips_flash_detect( + switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) { + case BCMA_CC_FLASHT_STSER: + case BCMA_CC_FLASHT_ATSER: +@@ -716,33 +1583,151 @@ + bus->drv_cc.pflash.window = 0x1c000000; + bus->drv_cc.pflash.window_size = 0x02000000; + +-@@ -199,7 +199,7 @@ static void bcma_core_mips_flash_detect( ++@@ -199,7 +228,46 @@ static void bcma_core_mips_flash_detect( + bus->drv_cc.pflash.buswidth = 2; + break; + default: + - pr_err("flash not supported.\n"); + + bcma_err(bus, "flash not supported.\n"); +++ } +++} +++ +++void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) +++{ +++ struct bcma_bus *bus = mcore->core->bus; +++ +++ if (mcore->early_setup_done) +++ return; +++ +++ bcma_chipco_serial_init(&bus->drv_cc); +++ bcma_core_mips_flash_detect(mcore); +++ +++ mcore->early_setup_done = true; +++} +++ +++static void bcma_fix_i2s_irqflag(struct bcma_bus *bus) +++{ +++ struct bcma_device *cpu, *pcie, *i2s; +++ +++ /* Fixup the interrupts in 4716/4748 for i2s core (2010 Broadcom SDK) +++ * (IRQ flags > 7 are ignored when setting the interrupt masks) +++ */ +++ if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4716 && +++ bus->chipinfo.id != BCMA_CHIP_ID_BCM4748) +++ return; +++ +++ cpu = bcma_find_core(bus, BCMA_CORE_MIPS_74K); +++ pcie = bcma_find_core(bus, BCMA_CORE_PCIE); +++ i2s = bcma_find_core(bus, BCMA_CORE_I2S); +++ if (cpu && pcie && i2s && +++ bcma_aread32(cpu, BCMA_MIPS_OOBSELINA74) == 0x08060504 && +++ bcma_aread32(pcie, BCMA_MIPS_OOBSELINA74) == 0x08060504 && +++ bcma_aread32(i2s, BCMA_MIPS_OOBSELOUTA30) == 0x88) { +++ bcma_awrite32(cpu, BCMA_MIPS_OOBSELINA74, 0x07060504); +++ bcma_awrite32(pcie, BCMA_MIPS_OOBSELINA74, 0x07060504); +++ bcma_awrite32(i2s, BCMA_MIPS_OOBSELOUTA30, 0x87); +++ bcma_debug(bus, +++ "Moved i2s interrupt to oob line 7 instead of 8\n"); + } + } + +-@@ -209,7 +209,7 @@ void bcma_core_mips_init(struct bcma_drv ++@@ -209,48 +277,59 @@ void bcma_core_mips_init(struct bcma_drv + struct bcma_device *core; + bus = mcore->core->bus; + + - pr_info("Initializing MIPS core...\n"); +-+ bcma_info(bus, "Initializing MIPS core...\n"); +++ if (mcore->setup_done) +++ return; +++ +++ bcma_debug(bus, "Initializing MIPS core...\n"); + +- if (!mcore->setup_done) +- mcore->assigned_irqs = 1; +-@@ -244,7 +244,7 @@ void bcma_core_mips_init(struct bcma_drv +- break; ++- if (!mcore->setup_done) ++- mcore->assigned_irqs = 1; +++ bcma_core_mips_early_init(mcore); ++ ++- /* 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; +++ bcma_fix_i2s_irqflag(bus); +++ +++ switch (bus->chipinfo.id) { +++ case BCMA_CHIP_ID_BCM4716: +++ case BCMA_CHIP_ID_BCM4748: +++ bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0); +++ bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0); +++ bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0); +++ bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_PCIE, 0); +++ bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0); +++ bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0); +++ break; +++ case BCMA_CHIP_ID_BCM5356: +++ case BCMA_CHIP_ID_BCM47162: +++ case BCMA_CHIP_ID_BCM53572: +++ bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0); +++ bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0); +++ bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0); +++ break; +++ case BCMA_CHIP_ID_BCM5357: +++ case BCMA_CHIP_ID_BCM4749: +++ bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0); +++ bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0); +++ bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0); +++ bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0); +++ bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0); +++ break; +++ case BCMA_CHIP_ID_BCM4706: +++ bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_PCIE, 0); +++ bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_4706_MAC_GBIT, +++ 0); +++ bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_PCIE, 1); +++ bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_USB20_HOST, 0); +++ bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_4706_CHIPCOMMON, +++ 0); +++ break; +++ default: +++ list_for_each_entry(core, &bus->cores, list) { +++ core->irq = bcma_core_irq(core); + } +++ bcma_err(bus, +++ "Unknown device (0x%x) found, can not configure IRQs\n", +++ bus->chipinfo.id); + } + - pr_info("IRQ reconfiguration done\n"); +-+ bcma_info(bus, "IRQ reconfiguration done\n"); +++ bcma_debug(bus, "IRQ reconfiguration done\n"); + bcma_core_mips_dump_irq(bus); + +- if (mcore->setup_done) ++- if (mcore->setup_done) ++- return; ++- ++- bcma_chipco_serial_init(&bus->drv_cc); ++- bcma_core_mips_flash_detect(mcore); ++ mcore->setup_done = true; ++ } + --- a/drivers/bcma/driver_pci.c + +++ b/drivers/bcma/driver_pci.c + @@ -2,8 +2,9 @@ +@@ -756,7 +1741,7 @@ + * + * Licensed under the GNU/GPL. See COPYING for details. + */ +-@@ -16,40 +17,39 @@ ++@@ -16,120 +17,124 @@ + * R/W ops. + **************************************************/ + +@@ -812,9 +1797,10 @@ + + v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL); + + if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE) + break; +- msleep(1); ++- msleep(1); +++ usleep_range(1000, 2000); + } +-@@ -57,79 +57,84 @@ static void bcma_pcie_mdio_set_phy(struc ++ } + + static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address) + { +@@ -868,7 +1854,8 @@ + + ret = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_DATA); + break; + } +- msleep(1); ++- msleep(1); +++ usleep_range(1000, 2000); + } + - pcicore_write32(pc, mdio_control, 0); + + pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0); +@@ -923,7 +1910,8 @@ + + v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL); + + if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE) + break; +- msleep(1); ++- msleep(1); +++ usleep_range(1000, 2000); + } + - pcicore_write32(pc, mdio_control, 0); + + pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0); +@@ -1103,7 +2091,7 @@ + +EXPORT_SYMBOL_GPL(bcma_core_pci_extend_L1timer); + --- a/drivers/bcma/driver_pci_host.c + +++ b/drivers/bcma/driver_pci_host.c +-@@ -2,13 +2,592 @@ ++@@ -2,13 +2,616 @@ + * Broadcom specific AMBA + * PCI Core in hostmode + * +@@ -1140,11 +2128,6 @@ + + chipid_top != 0x5300) + + return false; + + +-+ if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) { +-+ bcma_info(bus, "This PCI core is disabled and not working\n"); +-+ return false; +-+ } +-+ + + bcma_core_enable(pc->core, 0); + + + + return !mips_busprobe32(tmp, pc->core->io_addr); +@@ -1189,13 +2172,11 @@ + +out: + + return addr; + +} +- +--void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) +++ + +static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev, + + unsigned int func, unsigned int off, + + void *buf, int len) +- { +-- pr_err("No support for PCI core in hostmode yet\n"); +++{ + + int err = -EINVAL; + + u32 addr, val; + + void __iomem *mmio = 0; +@@ -1206,19 +2187,19 @@ + + if (dev == 0) { + + /* we support only two functions on device 0 */ + + if (func > 1) +-+ return -EINVAL; +++ goto out; + + + + /* accesses to config registers with offsets >= 256 + + * requires indirect access. + + */ + + if (off >= PCI_CONFIG_SPACE_SIZE) { + + addr = (func << 12); +-+ addr |= (off & 0x0FFF); +++ addr |= (off & 0x0FFC); + + val = bcma_pcie_read_config(pc, addr); + + } else { + + addr = BCMA_CORE_PCI_PCICFG0; + + addr |= (func << 8); +-+ addr |= (off & 0xfc); +++ addr |= (off & 0xFC); + + val = pcicore_read32(pc, addr); + + } + + } else { +@@ -1231,11 +2212,9 @@ + + goto out; + + + + if (mips_busprobe32(val, mmio)) { +-+ val = 0xffffffff; +++ val = 0xFFFFFFFF; + + goto unmap; + + } +-+ +-+ val = readl(mmio); + + } + + val >>= (8 * (off & 3)); + + +@@ -1257,13 +2236,15 @@ + +out: + + return err; + +} +-+ ++ ++-void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) + +static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev, + + unsigned int func, unsigned int off, + + const void *buf, int len) +-+{ ++ { ++- pr_err("No support for PCI core in hostmode yet\n"); + + int err = -EINVAL; +-+ u32 addr = 0, val = 0; +++ u32 addr, val; + + void __iomem *mmio = 0; + + u16 chipid = pc->core->bus->chipinfo.id; + + +@@ -1271,16 +2252,22 @@ + + if (unlikely(len != 1 && len != 2 && len != 4)) + + goto out; + + if (dev == 0) { +++ /* we support only two functions on device 0 */ +++ if (func > 1) +++ goto out; +++ + + /* accesses to config registers with offsets >= 256 + + * requires indirect access. + + */ +-+ if (off < PCI_CONFIG_SPACE_SIZE) { +-+ addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0; +++ if (off >= PCI_CONFIG_SPACE_SIZE) { +++ addr = (func << 12); +++ addr |= (off & 0x0FFC); +++ val = bcma_pcie_read_config(pc, addr); +++ } else { +++ addr = BCMA_CORE_PCI_PCICFG0; + + addr |= (func << 8); +-+ addr |= (off & 0xfc); +-+ mmio = ioremap_nocache(addr, sizeof(val)); +-+ if (!mmio) +-+ goto out; +++ addr |= (off & 0xFC); +++ val = pcicore_read32(pc, addr); + + } + + } else { + + addr = bcma_get_cfgspace_addr(pc, dev, func, off); +@@ -1292,19 +2279,17 @@ + + goto out; + + + + if (mips_busprobe32(val, mmio)) { +-+ val = 0xffffffff; +++ val = 0xFFFFFFFF; + + goto unmap; + + } + + } + + + + switch (len) { + + case 1: +-+ val = readl(mmio); + + val &= ~(0xFF << (8 * (off & 3))); + + val |= *((const u8 *)buf) << (8 * (off & 3)); + + break; + + case 2: +-+ val = readl(mmio); + + val &= ~(0xFFFF << (8 * (off & 3))); + + val |= *((const u16 *)buf) << (8 * (off & 3)); + + break; +@@ -1312,13 +2297,14 @@ + + val = *((const u32 *)buf); + + break; + + } +-+ if (dev == 0 && !addr) { +++ if (dev == 0) { + + /* accesses to config registers with offsets >= 256 + + * requires indirect access. + + */ +-+ addr = (func << 12); +-+ addr |= (off & 0x0FFF); +-+ bcma_pcie_write_config(pc, addr, val); +++ if (off >= PCI_CONFIG_SPACE_SIZE) +++ bcma_pcie_write_config(pc, addr, val); +++ else +++ pcicore_write32(pc, addr, val); + + } else { + + writel(val, mmio); + + +@@ -1389,7 +2375,7 @@ + + /* check for Header type 0 */ + + bcma_extpci_read_config(pc, dev, func, PCI_HEADER_TYPE, &byte_val, + + sizeof(u8)); +-+ if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL) +++ if ((byte_val & 0x7F) != PCI_HEADER_TYPE_NORMAL) + + return cap_ptr; + + + + /* check if the capability pointer field exists */ +@@ -1503,12 +2489,19 @@ + + + + bcma_info(bus, "PCIEcore in host mode found\n"); + + +++ if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) { +++ bcma_info(bus, "This PCIE core is disabled and not working\n"); +++ return; +++ } +++ + + pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL); + + if (!pc_host) { + + bcma_err(bus, "can not allocate memory"); + + return; + + } + + +++ spin_lock_init(&pc_host->cfgspace_lock); +++ + + pc->host_controller = pc_host; + + pc_host->pci_controller.io_resource = &pc_host->io_resource; + + pc_host->pci_controller.mem_resource = &pc_host->mem_resource; +@@ -1532,9 +2525,9 @@ + + pc_host->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED; + + + + /* Reset RC */ +-+ udelay(3000); +++ usleep_range(3000, 5000); + + pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE); +-+ udelay(1000); +++ msleep(50); + + pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST | + + BCMA_CORE_PCI_CTL_RST_OE); + + +@@ -1559,6 +2552,8 @@ + + pc_host->mem_resource.start = BCMA_SOC_PCI_MEM; + + pc_host->mem_resource.end = BCMA_SOC_PCI_MEM + + + BCMA_SOC_PCI_MEM_SZ - 1; +++ pc_host->io_resource.start = 0x100; +++ pc_host->io_resource.end = 0x47F; + + pci_membase_1G = BCMA_SOC_PCIE_DMA_H32; + + pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, + + tmp | BCMA_SOC_PCI_MEM); +@@ -1566,6 +2561,8 @@ + + pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM; + + pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM + + + BCMA_SOC_PCI_MEM_SZ - 1; +++ pc_host->io_resource.start = 0x480; +++ pc_host->io_resource.end = 0x7FF; + + pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32; + + pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG; + + pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, +@@ -1588,10 +2585,21 @@ + + * before issuing configuration requests to PCI Express + + * devices. + + */ +-+ udelay(100000); +++ msleep(100); + + + + bcma_core_pci_enable_crs(pc); + + +++ if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706 || +++ bus->chipinfo.id == BCMA_CHIP_ID_BCM4716) { +++ u16 val16; +++ bcma_extpci_read_config(pc, 0, 0, BCMA_CORE_PCI_CFG_DEVCTRL, +++ &val16, sizeof(val16)); +++ val16 |= (2 << 5); /* Max payload size of 512 */ +++ val16 |= (2 << 12); /* MRRS 512 */ +++ bcma_extpci_write_config(pc, 0, 0, BCMA_CORE_PCI_CFG_DEVCTRL, +++ &val16, sizeof(val16)); +++ } +++ + + /* Enable PCI bridge BAR0 memory & master access */ + + tmp = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + + bcma_extpci_write_config(pc, 0, 0, PCI_COMMAND, &tmp, sizeof(tmp)); +@@ -1608,7 +2616,7 @@ + + set_io_port_base(pc_host->pci_controller.io_map_base); + + /* Give some time to the PCI controller to configure itself with the new + + * values. Not waiting at this point causes crashes of the machine. */ +-+ mdelay(10); +++ usleep_range(10000, 15000); + + register_pci_controller(&pc_host->pci_controller); + + return; + +} +@@ -1641,7 +2649,7 @@ + +static void bcma_core_pci_fixup_addresses(struct pci_dev *dev) + +{ + + struct resource *res; +-+ int pos; +++ int pos, err; + + + + if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { + + /* This is not a device on the PCI-core bridge. */ +@@ -1654,8 +2662,12 @@ + + + + for (pos = 0; pos < 6; pos++) { + + res = &dev->resource[pos]; +-+ if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM)) +-+ pci_assign_resource(dev, pos); +++ if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM)) { +++ err = pci_assign_resource(dev, pos); +++ if (err) +++ pr_err("PCI: Problem fixing up the addresses on %s\n", +++ pci_name(dev)); +++ } + + } + +} + +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_addresses); +@@ -1676,7 +2688,7 @@ + + pr_info("PCI: Fixing up device %s\n", pci_name(dev)); + + + + /* Fix up interrupt lines */ +-+ dev->irq = bcma_core_mips_irq(pc_host->pdev->core) + 2; +++ dev->irq = bcma_core_irq(pc_host->pdev->core); + + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + + + + return 0; +@@ -1695,7 +2707,7 @@ + + + + pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host, + + pci_ops); +-+ return bcma_core_mips_irq(pc_host->pdev->core) + 2; +++ return bcma_core_irq(pc_host->pdev->core); + } + +EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq); + --- a/drivers/bcma/host_pci.c +@@ -1709,7 +2721,39 @@ + } + + /* Provides access to the requested core. Returns base offset that has to be +-@@ -154,8 +154,8 @@ const struct bcma_host_ops bcma_host_pci ++@@ -77,8 +77,8 @@ static void bcma_host_pci_write32(struct ++ } ++ ++ #ifdef CONFIG_BCMA_BLOCKIO ++-void bcma_host_pci_block_read(struct bcma_device *core, void *buffer, ++- size_t count, u16 offset, u8 reg_width) +++static void bcma_host_pci_block_read(struct bcma_device *core, void *buffer, +++ size_t count, u16 offset, u8 reg_width) ++ { ++ void __iomem *addr = core->bus->mmio + offset; ++ if (core->bus->mapped_core != core) ++@@ -100,8 +100,9 @@ void bcma_host_pci_block_read(struct bcm ++ } ++ } ++ ++-void bcma_host_pci_block_write(struct bcma_device *core, const void *buffer, ++- size_t count, u16 offset, u8 reg_width) +++static void bcma_host_pci_block_write(struct bcma_device *core, +++ const void *buffer, size_t count, +++ u16 offset, u8 reg_width) ++ { ++ void __iomem *addr = core->bus->mmio + offset; ++ if (core->bus->mapped_core != core) ++@@ -139,7 +140,7 @@ static void bcma_host_pci_awrite32(struc ++ iowrite32(value, core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset); ++ } ++ ++-const struct bcma_host_ops bcma_host_pci_ops = { +++static const struct bcma_host_ops bcma_host_pci_ops = { ++ .read8 = bcma_host_pci_read8, ++ .read16 = bcma_host_pci_read16, ++ .read32 = bcma_host_pci_read32, ++@@ -154,8 +155,8 @@ const struct bcma_host_ops bcma_host_pci + .awrite32 = bcma_host_pci_awrite32, + }; + +@@ -1720,7 +2764,7 @@ + { + struct bcma_bus *bus; + int err = -ENOMEM; +-@@ -188,7 +188,7 @@ static int bcma_host_pci_probe(struct pc ++@@ -188,7 +189,7 @@ static int bcma_host_pci_probe(struct pc + + /* SSB needed additional powering up, do we have any AMBA PCI cards? */ + if (!pci_is_pcie(dev)) +@@ -1729,7 +2773,7 @@ + + /* Map MMIO */ + err = -ENOMEM; +-@@ -201,6 +201,9 @@ static int bcma_host_pci_probe(struct pc ++@@ -201,6 +202,9 @@ static int bcma_host_pci_probe(struct pc + bus->hosttype = BCMA_HOSTTYPE_PCI; + bus->ops = &bcma_host_pci_ops; + +@@ -1739,7 +2783,7 @@ + /* Register */ + err = bcma_bus_register(bus); + if (err) +-@@ -222,7 +225,7 @@ err_kfree_bus: ++@@ -222,7 +226,7 @@ err_kfree_bus: + return err; + } + +@@ -1748,15 +2792,40 @@ + { + struct bcma_bus *bus = pci_get_drvdata(dev); + +-@@ -265,6 +268,7 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bc ++@@ -234,7 +238,7 @@ static void bcma_host_pci_remove(struct ++ pci_set_drvdata(dev, NULL); ++ } + ++-#ifdef CONFIG_PM +++#ifdef CONFIG_PM_SLEEP ++ static int bcma_host_pci_suspend(struct device *dev) ++ { ++ struct pci_dev *pdev = to_pci_dev(dev); ++@@ -257,17 +261,21 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bc ++ bcma_host_pci_resume); ++ #define BCMA_PM_OPS (&bcma_pm_ops) ++ ++-#else /* CONFIG_PM */ +++#else /* CONFIG_PM_SLEEP */ ++ ++ #define BCMA_PM_OPS NULL ++ ++-#endif /* CONFIG_PM */ +++#endif /* CONFIG_PM_SLEEP */ ++ + static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, + + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, +-@@ -277,7 +281,7 @@ static struct pci_driver bcma_pci_bridge +++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4358) }, +++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) }, +++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4365) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, ++ { 0, }, ++ }; ++@@ -277,7 +285,7 @@ static struct pci_driver bcma_pci_bridge + .name = "bcma-pci-bridge", + .id_table = bcma_pci_bridge_tbl, + .probe = bcma_host_pci_probe, +@@ -1765,6 +2834,17 @@ + .driver.pm = BCMA_PM_OPS, + }; + ++--- a/drivers/bcma/host_soc.c +++++ b/drivers/bcma/host_soc.c ++@@ -143,7 +143,7 @@ static void bcma_host_soc_awrite32(struc ++ writel(value, core->io_wrap + offset); ++ } ++ ++-const struct bcma_host_ops bcma_host_soc_ops = { +++static const struct bcma_host_ops bcma_host_soc_ops = { ++ .read8 = bcma_host_soc_read8, ++ .read16 = bcma_host_soc_read16, ++ .read32 = bcma_host_soc_read32, + --- a/drivers/bcma/main.c + +++ b/drivers/bcma/main.c + @@ -13,6 +13,12 @@ +@@ -1796,15 +2876,46 @@ + { + struct bcma_device *core; + +-@@ -65,6 +78,7 @@ static struct bcma_device *bcma_find_cor ++@@ -65,6 +78,38 @@ static struct bcma_device *bcma_find_cor + } + return NULL; + } + +EXPORT_SYMBOL_GPL(bcma_find_core); +++ +++struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid, +++ u8 unit) +++{ +++ struct bcma_device *core; +++ +++ list_for_each_entry(core, &bus->cores, list) { +++ if (core->id.id == coreid && core->core_unit == unit) +++ return core; +++ } +++ return NULL; +++} +++ +++bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value, +++ int timeout) +++{ +++ unsigned long deadline = jiffies + timeout; +++ u32 val; +++ +++ do { +++ val = bcma_read32(core, reg); +++ if ((val & mask) == value) +++ return true; +++ cpu_relax(); +++ udelay(10); +++ } while (!time_after_eq(jiffies, deadline)); +++ +++ bcma_warn(core->bus, "Timeout waiting for register 0x%04X!\n", reg); +++ +++ return false; +++} + + static void bcma_release_core_dev(struct device *dev) + { +-@@ -84,16 +98,18 @@ static int bcma_register_cores(struct bc ++@@ -84,16 +129,23 @@ static int bcma_register_cores(struct bc + list_for_each_entry(core, &bus->cores, list) { + /* We support that cores ourself */ + switch (core->id.id) { +@@ -1817,6 +2928,11 @@ + continue; + } + +++ /* Only first GMAC core on BCM4706 is connected and working */ +++ if (core->id.id == BCMA_CORE_4706_MAC_GBIT && +++ core->core_unit > 0) +++ continue; +++ + core->dev.release = bcma_release_core_dev; + core->dev.bus = &bcma_bus_type; + - dev_set_name(&core->dev, "bcma%d:%d", 0/*bus->num*/, dev_id); +@@ -1824,7 +2940,7 @@ + + switch (bus->hosttype) { + case BCMA_HOSTTYPE_PCI: +-@@ -111,8 +127,9 @@ static int bcma_register_cores(struct bc ++@@ -111,41 +163,75 @@ static int bcma_register_cores(struct bc + + err = device_register(&core->dev); + if (err) { +@@ -1836,10 +2952,39 @@ + continue; + } + core->dev_registered = true; +-@@ -132,20 +149,24 @@ static void bcma_unregister_cores(struct ++ dev_id++; + } ++ +++ err = bcma_gpio_init(&bus->drv_cc); +++ if (err == -ENOTSUPP) +++ bcma_debug(bus, "GPIO driver not activated\n"); +++ else if (err) +++ bcma_err(bus, "Error registering GPIO driver: %i\n", err); +++ +++ if (bus->hosttype == BCMA_HOSTTYPE_SOC) { +++ err = bcma_chipco_watchdog_register(&bus->drv_cc); +++ if (err) +++ bcma_err(bus, "Error registering watchdog driver\n"); +++ } +++ ++ return 0; + } + ++ static void bcma_unregister_cores(struct bcma_bus *bus) ++ { ++- struct bcma_device *core; +++ struct bcma_device *core, *tmp; ++ ++- list_for_each_entry(core, &bus->cores, list) { +++ list_for_each_entry_safe(core, tmp, &bus->cores, list) { +++ list_del(&core->list); ++ if (core->dev_registered) ++ device_unregister(&core->dev); ++ } +++ if (bus->hosttype == BCMA_HOSTTYPE_SOC) +++ platform_device_unregister(bus->drv_cc.watchdog); ++ } ++ + -int bcma_bus_register(struct bcma_bus *bus) + +int __devinit bcma_bus_register(struct bcma_bus *bus) + { +@@ -1858,31 +3003,58 @@ + return -1; + } + +++ /* Early init CC core */ +++ core = bcma_find_core(bus, bcma_cc_core_id(bus)); +++ if (core) { +++ bus->drv_cc.core = core; +++ bcma_core_chipcommon_early_init(&bus->drv_cc); +++ } +++ +++ /* Try to get SPROM */ +++ err = bcma_sprom_get(bus); +++ if (err == -ENOENT) { +++ bcma_err(bus, "No SPROM available\n"); +++ } else if (err) +++ bcma_err(bus, "Failed to get SPROM: %d\n", err); +++ + /* Init CC core */ + - core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON); + + core = bcma_find_core(bus, bcma_cc_core_id(bus)); + if (core) { + bus->drv_cc.core = core; + bcma_core_chipcommon_init(&bus->drv_cc); +-@@ -165,17 +186,24 @@ int bcma_bus_register(struct bcma_bus *b +- bcma_core_pci_init(&bus->drv_pci); ++@@ -159,30 +245,54 @@ int bcma_bus_register(struct bcma_bus *b + } + ++ /* Init PCIE core */ ++- core = bcma_find_core(bus, BCMA_CORE_PCIE); +++ core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 0); ++ if (core) { ++- bus->drv_pci.core = core; ++- bcma_core_pci_init(&bus->drv_pci); +++ bus->drv_pci[0].core = core; +++ bcma_core_pci_init(&bus->drv_pci[0]); ++ } ++ ++- /* Try to get SPROM */ ++- err = bcma_sprom_get(bus); ++- if (err == -ENOENT) { ++- pr_err("No SPROM available\n"); ++- } else if (err) ++- pr_err("Failed to get SPROM: %d\n", err); +++ /* Init PCIE core */ +++ core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 1); +++ if (core) { +++ bus->drv_pci[1].core = core; +++ bcma_core_pci_init(&bus->drv_pci[1]); +++ } +++ + + /* Init GBIT MAC COMMON core */ + + core = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON); + + if (core) { + + bus->drv_gmac_cmn.core = core; + + bcma_core_gmac_cmn_init(&bus->drv_gmac_cmn); + + } +-+ +- /* Try to get SPROM */ +- err = bcma_sprom_get(bus); +- if (err == -ENOENT) { +-- pr_err("No SPROM available\n"); +-+ bcma_err(bus, "No SPROM available\n"); +- } else if (err) +-- pr_err("Failed to get SPROM: %d\n", err); +-+ bcma_err(bus, "Failed to get SPROM: %d\n", err); + + /* Register found cores */ + bcma_register_cores(bus); +@@ -1892,7 +3064,31 @@ + + return 0; + } +-@@ -196,14 +224,14 @@ int __init bcma_bus_early_register(struc ++ ++ void bcma_bus_unregister(struct bcma_bus *bus) ++ { +++ struct bcma_device *cores[3]; +++ int err; +++ +++ err = bcma_gpio_unregister(&bus->drv_cc); +++ if (err == -EBUSY) +++ bcma_err(bus, "Some GPIOs are still in use.\n"); +++ else if (err) +++ bcma_err(bus, "Can not unregister GPIO driver: %i\n", err); +++ +++ 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, ++@@ -196,14 +306,14 @@ int __init bcma_bus_early_register(struc + bcma_init_bus(bus); + + match.manuf = BCMA_MANUF_BCM; +@@ -1909,7 +3105,7 @@ + return -1; + } + +-@@ -215,12 +243,12 @@ int __init bcma_bus_early_register(struc ++@@ -215,25 +325,25 @@ int __init bcma_bus_early_register(struc + /* Scan for mips core */ + err = bcma_bus_scan_early(bus, &match, core_mips); + if (err) { +@@ -1918,22 +3114,31 @@ + return -1; + } + +- /* Init CC core */ ++- /* Init CC core */ + - core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON); +++ /* Early init CC core */ + + core = bcma_find_core(bus, bcma_cc_core_id(bus)); + if (core) { + bus->drv_cc.core = core; +- bcma_core_chipcommon_init(&bus->drv_cc); +-@@ -233,7 +261,7 @@ int __init bcma_bus_early_register(struc +- bcma_core_mips_init(&bus->drv_mips); ++- bcma_core_chipcommon_init(&bus->drv_cc); +++ bcma_core_chipcommon_early_init(&bus->drv_cc); + } + ++- /* Init MIPS core */ +++ /* Early 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); +++ bcma_core_mips_early_init(&bus->drv_mips); ++ } ++ + - pr_info("Early bus registered\n"); + + bcma_info(bus, "Early bus registered\n"); + + return 0; + } +-@@ -259,8 +287,7 @@ int bcma_bus_resume(struct bcma_bus *bus ++@@ -259,8 +369,7 @@ int bcma_bus_resume(struct bcma_bus *bus + struct bcma_device *core; + + /* Init CC core */ +@@ -1999,8 +3204,12 @@ + { BCMA_CORE_MAC_GBIT, "GBit MAC" }, + { BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" }, + { BCMA_CORE_PCIE_RC, "PCIe Root Complex" }, +-@@ -79,16 +86,41 @@ struct bcma_device_id_name bcma_device_n ++@@ -77,18 +84,45 @@ struct bcma_device_id_name bcma_device_n ++ { BCMA_CORE_I2S, "I2S" }, ++ { BCMA_CORE_SDR_DDR1_MEM_CTL, "SDR/DDR1 Memory Controller" }, + { BCMA_CORE_SHIM, "SHIM" }, +++ { BCMA_CORE_PCIE2, "PCIe Gen2" }, +++ { BCMA_CORE_ARM_CR4, "ARM CR4" }, + { BCMA_CORE_DEFAULT, "Default" }, + }; + -const char *bcma_device_name(struct bcma_device_id *id) +@@ -2038,17 +3247,84 @@ + + break; + + default: + + return "UNKNOWN"; +-+ } ++ } + + + + for (i = 0; i < size; i++) { + + if (names[i].id == id->id) + + return names[i].name; +- } +++ } + + + return "UNKNOWN"; + } + +-@@ -212,6 +244,17 @@ static struct bcma_device *bcma_find_cor ++@@ -105,19 +139,19 @@ static void bcma_scan_switch_core(struct ++ addr); ++ } ++ ++-static u32 bcma_erom_get_ent(struct bcma_bus *bus, u32 **eromptr) +++static u32 bcma_erom_get_ent(struct bcma_bus *bus, u32 __iomem **eromptr) ++ { ++ u32 ent = readl(*eromptr); ++ (*eromptr)++; ++ return ent; ++ } ++ ++-static void bcma_erom_push_ent(u32 **eromptr) +++static void bcma_erom_push_ent(u32 __iomem **eromptr) ++ { ++ (*eromptr)--; ++ } ++ ++-static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 **eromptr) +++static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 __iomem **eromptr) ++ { ++ u32 ent = bcma_erom_get_ent(bus, eromptr); ++ if (!(ent & SCAN_ER_VALID)) ++@@ -127,14 +161,14 @@ static s32 bcma_erom_get_ci(struct bcma_ ++ return ent; ++ } ++ ++-static bool bcma_erom_is_end(struct bcma_bus *bus, u32 **eromptr) +++static bool bcma_erom_is_end(struct bcma_bus *bus, u32 __iomem **eromptr) ++ { ++ u32 ent = bcma_erom_get_ent(bus, eromptr); ++ bcma_erom_push_ent(eromptr); ++ return (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID)); ++ } ++ ++-static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 **eromptr) +++static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 __iomem **eromptr) ++ { ++ u32 ent = bcma_erom_get_ent(bus, eromptr); ++ bcma_erom_push_ent(eromptr); ++@@ -143,7 +177,7 @@ static bool bcma_erom_is_bridge(struct b ++ ((ent & SCAN_ADDR_TYPE) == SCAN_ADDR_TYPE_BRIDGE)); ++ } ++ ++-static void bcma_erom_skip_component(struct bcma_bus *bus, u32 **eromptr) +++static void bcma_erom_skip_component(struct bcma_bus *bus, u32 __iomem **eromptr) ++ { ++ u32 ent; ++ while (1) { ++@@ -157,7 +191,7 @@ static void bcma_erom_skip_component(str ++ bcma_erom_push_ent(eromptr); ++ } ++ ++-static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 **eromptr) +++static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 __iomem **eromptr) ++ { ++ u32 ent = bcma_erom_get_ent(bus, eromptr); ++ if (!(ent & SCAN_ER_VALID)) ++@@ -167,7 +201,7 @@ static s32 bcma_erom_get_mst_port(struct ++ return ent; ++ } ++ ++-static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr, +++static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 __iomem **eromptr, ++ u32 type, u8 port) ++ { ++ u32 addrl, addrh, sizel, sizeh = 0; ++@@ -212,6 +246,17 @@ static struct bcma_device *bcma_find_cor + return NULL; + } + +@@ -2066,7 +3342,7 @@ + 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) +-@@ -252,11 +295,15 @@ static int bcma_get_next_core(struct bcm ++@@ -252,11 +297,15 @@ static int bcma_get_next_core(struct bcm + + /* check if component is a core at all */ + if (wrappers[0] + wrappers[1] == 0) { +@@ -2087,7 +3363,7 @@ + } + + if (bcma_erom_is_bridge(bus, eromptr)) { +-@@ -286,6 +333,23 @@ static int bcma_get_next_core(struct bcm ++@@ -286,6 +335,23 @@ static int bcma_get_next_core(struct bcm + return -EILSEQ; + } + +@@ -2111,7 +3387,7 @@ + /* get & parse slave ports */ + for (i = 0; i < ports[1]; i++) { + for (j = 0; ; j++) { +-@@ -298,7 +362,7 @@ static int bcma_get_next_core(struct bcm ++@@ -298,7 +364,7 @@ static int bcma_get_next_core(struct bcm + break; + } else { + if (i == 0 && j == 0) +@@ -2120,7 +3396,7 @@ + } + } + } +-@@ -353,6 +417,7 @@ static int bcma_get_next_core(struct bcm ++@@ -353,6 +419,7 @@ static int bcma_get_next_core(struct bcm + void bcma_init_bus(struct bcma_bus *bus) + { + s32 tmp; +@@ -2128,7 +3404,7 @@ + + if (bus->init_done) + return; +-@@ -363,9 +428,12 @@ void bcma_init_bus(struct bcma_bus *bus) ++@@ -363,9 +430,12 @@ void bcma_init_bus(struct bcma_bus *bus) + bcma_scan_switch_core(bus, BCMA_ADDR_BASE); + + tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID); +@@ -2144,16 +3420,29 @@ + bus->init_done = true; + } + +-@@ -392,6 +460,7 @@ int bcma_bus_scan(struct bcma_bus *bus) ++@@ -392,9 +462,12 @@ int bcma_bus_scan(struct bcma_bus *bus) + bcma_scan_switch_core(bus, erombase); + + while (eromptr < eromend) { + + struct bcma_device *other_core; + struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL); +- if (!core) +- return -ENOMEM; +-@@ -414,14 +483,15 @@ int bcma_bus_scan(struct bcma_bus *bus) ++- if (!core) ++- return -ENOMEM; +++ if (!core) { +++ err = -ENOMEM; +++ goto out; +++ } ++ INIT_LIST_HEAD(&core->list); ++ core->bus = bus; + ++@@ -409,25 +482,28 @@ int bcma_bus_scan(struct bcma_bus *bus) ++ } else if (err == -ESPIPE) { ++ break; ++ } ++- return err; +++ goto out; ++ } ++ + core->core_index = core_num++; + bus->nr_cores++; + + other_core = bcma_find_core_reverse(bus, core->id.id); +@@ -2173,9 +3462,23 @@ + + list_add_tail(&core->list, &bus->cores); + } + +++ err = 0; +++out: + if (bus->hosttype == BCMA_HOSTTYPE_SOC) +-@@ -471,13 +541,12 @@ int __init bcma_bus_scan_early(struct bc ++ iounmap(eromptr); + ++- return 0; +++ return err; ++ } ++ ++ int __init bcma_bus_scan_early(struct bcma_bus *bus, ++@@ -467,21 +543,21 @@ int __init bcma_bus_scan_early(struct bc ++ else if (err == -ESPIPE) ++ break; ++ else if (err < 0) ++- return err; +++ goto out; ++ + core->core_index = core_num++; + bus->nr_cores++; + - pr_info("Core %d found: %s " +@@ -2193,6 +3496,11 @@ + err = 0; + break; + } ++ +++out: ++ if (bus->hosttype == BCMA_HOSTTYPE_SOC) ++ iounmap(eromptr); ++ + --- a/drivers/bcma/scan.h + +++ b/drivers/bcma/scan.h + @@ -27,7 +27,7 @@ +@@ -2215,7 +3523,7 @@ + * Licensed under the GNU/GPL. See COPYING for details. + */ + +-@@ -14,7 +16,57 @@ ++@@ -14,18 +16,68 @@ + #include + #include + +@@ -2274,7 +3582,88 @@ + + /************************************************** + * R/W ops. +-@@ -124,10 +176,37 @@ static int bcma_sprom_valid(const u16 *s ++ **************************************************/ ++ ++-static void bcma_sprom_read(struct bcma_bus *bus, u16 offset, u16 *sprom) +++static void bcma_sprom_read(struct bcma_bus *bus, u16 offset, u16 *sprom, +++ size_t words) ++ { ++ int i; ++- for (i = 0; i < SSB_SPROMSIZE_WORDS_R4; i++) ++- sprom[i] = bcma_read16(bus->drv_cc.core, ++- offset + (i * 2)); +++ for (i = 0; i < words; i++) +++ sprom[i] = bcma_read16(bus->drv_cc.core, offset + (i * 2)); ++ } ++ ++ /************************************************** ++@@ -72,29 +124,29 @@ static inline u8 bcma_crc8(u8 crc, u8 da ++ return t[crc ^ data]; ++ } ++ ++-static u8 bcma_sprom_crc(const u16 *sprom) +++static u8 bcma_sprom_crc(const u16 *sprom, size_t words) ++ { ++ int word; ++ u8 crc = 0xFF; ++ ++- for (word = 0; word < SSB_SPROMSIZE_WORDS_R4 - 1; word++) { +++ for (word = 0; word < words - 1; word++) { ++ crc = bcma_crc8(crc, sprom[word] & 0x00FF); ++ crc = bcma_crc8(crc, (sprom[word] & 0xFF00) >> 8); ++ } ++- crc = bcma_crc8(crc, sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & 0x00FF); +++ crc = bcma_crc8(crc, sprom[words - 1] & 0x00FF); ++ crc ^= 0xFF; ++ ++ return crc; ++ } ++ ++-static int bcma_sprom_check_crc(const u16 *sprom) +++static int bcma_sprom_check_crc(const u16 *sprom, size_t words) ++ { ++ u8 crc; ++ u8 expected_crc; ++ u16 tmp; ++ ++- crc = bcma_sprom_crc(sprom); ++- tmp = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_CRC; +++ crc = bcma_sprom_crc(sprom, words); +++ tmp = sprom[words - 1] & SSB_SPROM_REVISION_CRC; ++ expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT; ++ if (crc != expected_crc) ++ return -EPROTO; ++@@ -102,21 +154,25 @@ static int bcma_sprom_check_crc(const u1 ++ return 0; ++ } ++ ++-static int bcma_sprom_valid(const u16 *sprom) +++static int bcma_sprom_valid(struct bcma_bus *bus, const u16 *sprom, +++ size_t words) ++ { ++ u16 revision; ++ int err; ++ ++- err = bcma_sprom_check_crc(sprom); +++ err = bcma_sprom_check_crc(sprom, words); ++ if (err) ++ return err; ++ ++- revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_REV; ++- if (revision != 8 && revision != 9) { +++ revision = sprom[words - 1] & SSB_SPROM_REVISION_REV; +++ if (revision != 8 && revision != 9 && revision != 10) { ++ pr_err("Unsupported SPROM revision: %d\n", revision); ++ return -ENOENT; ++ } ++ +++ bus->sprom.revision = revision; +++ bcma_debug(bus, "Found SPROM revision %d\n", revision); +++ ++ return 0; ++ } ++ ++@@ -124,124 +180,439 @@ static int bcma_sprom_valid(const u16 *s + * SPROM extraction. + **************************************************/ + +@@ -2304,6 +3693,9 @@ + - u16 v; + + u16 v, o; + int i; ++- ++- bus->sprom.revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & ++- SSB_SPROM_REVISION_REV; + + u16 pwr_info_offset[] = { + + SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1, + + SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3 +@@ -2311,79 +3703,15 @@ + + BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) != + + ARRAY_SIZE(bus->sprom.core_pwr_info)); + +- bus->sprom.revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & +- SSB_SPROM_REVISION_REV; +-@@ -137,102 +216,378 @@ static void bcma_sprom_extract_r8(struct ++ for (i = 0; i < 3; i++) { ++ v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i]; + *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v); + } + + - bus->sprom.board_rev = sprom[SPOFF(SSB_SPROM8_BOARDREV)]; + + SPEX(board_rev, SSB_SPROM8_BOARDREV, ~0, 0); +- +-- bus->sprom.txpid2g[0] = (sprom[SPOFF(SSB_SPROM4_TXPID2G01)] & +-- SSB_SPROM4_TXPID2G0) >> SSB_SPROM4_TXPID2G0_SHIFT; +-- bus->sprom.txpid2g[1] = (sprom[SPOFF(SSB_SPROM4_TXPID2G01)] & +-- SSB_SPROM4_TXPID2G1) >> SSB_SPROM4_TXPID2G1_SHIFT; +-- bus->sprom.txpid2g[2] = (sprom[SPOFF(SSB_SPROM4_TXPID2G23)] & +-- SSB_SPROM4_TXPID2G2) >> SSB_SPROM4_TXPID2G2_SHIFT; +-- bus->sprom.txpid2g[3] = (sprom[SPOFF(SSB_SPROM4_TXPID2G23)] & +-- SSB_SPROM4_TXPID2G3) >> SSB_SPROM4_TXPID2G3_SHIFT; +-- +-- bus->sprom.txpid5gl[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL01)] & +-- SSB_SPROM4_TXPID5GL0) >> SSB_SPROM4_TXPID5GL0_SHIFT; +-- bus->sprom.txpid5gl[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL01)] & +-- SSB_SPROM4_TXPID5GL1) >> SSB_SPROM4_TXPID5GL1_SHIFT; +-- bus->sprom.txpid5gl[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL23)] & +-- SSB_SPROM4_TXPID5GL2) >> SSB_SPROM4_TXPID5GL2_SHIFT; +-- bus->sprom.txpid5gl[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL23)] & +-- SSB_SPROM4_TXPID5GL3) >> SSB_SPROM4_TXPID5GL3_SHIFT; +-- +-- bus->sprom.txpid5g[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5G01)] & +-- SSB_SPROM4_TXPID5G0) >> SSB_SPROM4_TXPID5G0_SHIFT; +-- bus->sprom.txpid5g[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5G01)] & +-- SSB_SPROM4_TXPID5G1) >> SSB_SPROM4_TXPID5G1_SHIFT; +-- bus->sprom.txpid5g[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5G23)] & +-- SSB_SPROM4_TXPID5G2) >> SSB_SPROM4_TXPID5G2_SHIFT; +-- bus->sprom.txpid5g[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5G23)] & +-- SSB_SPROM4_TXPID5G3) >> SSB_SPROM4_TXPID5G3_SHIFT; +-- +-- bus->sprom.txpid5gh[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH01)] & +-- SSB_SPROM4_TXPID5GH0) >> SSB_SPROM4_TXPID5GH0_SHIFT; +-- bus->sprom.txpid5gh[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH01)] & +-- SSB_SPROM4_TXPID5GH1) >> SSB_SPROM4_TXPID5GH1_SHIFT; +-- bus->sprom.txpid5gh[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH23)] & +-- SSB_SPROM4_TXPID5GH2) >> SSB_SPROM4_TXPID5GH2_SHIFT; +-- bus->sprom.txpid5gh[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH23)] & +-- SSB_SPROM4_TXPID5GH3) >> SSB_SPROM4_TXPID5GH3_SHIFT; +-- +-- bus->sprom.boardflags_lo = sprom[SPOFF(SSB_SPROM8_BFLLO)]; +-- bus->sprom.boardflags_hi = sprom[SPOFF(SSB_SPROM8_BFLHI)]; +-- bus->sprom.boardflags2_lo = sprom[SPOFF(SSB_SPROM8_BFL2LO)]; +-- bus->sprom.boardflags2_hi = sprom[SPOFF(SSB_SPROM8_BFL2HI)]; +-- +-- bus->sprom.country_code = sprom[SPOFF(SSB_SPROM8_CCODE)]; +-- +-- bus->sprom.fem.ghz2.tssipos = (sprom[SPOFF(SSB_SPROM8_FEM2G)] & +-- SSB_SROM8_FEM_TSSIPOS) >> SSB_SROM8_FEM_TSSIPOS_SHIFT; +-- bus->sprom.fem.ghz2.extpa_gain = (sprom[SPOFF(SSB_SPROM8_FEM2G)] & +-- SSB_SROM8_FEM_EXTPA_GAIN) >> SSB_SROM8_FEM_EXTPA_GAIN_SHIFT; +-- bus->sprom.fem.ghz2.pdet_range = (sprom[SPOFF(SSB_SPROM8_FEM2G)] & +-- SSB_SROM8_FEM_PDET_RANGE) >> SSB_SROM8_FEM_PDET_RANGE_SHIFT; +-- bus->sprom.fem.ghz2.tr_iso = (sprom[SPOFF(SSB_SPROM8_FEM2G)] & +-- SSB_SROM8_FEM_TR_ISO) >> SSB_SROM8_FEM_TR_ISO_SHIFT; +-- bus->sprom.fem.ghz2.antswlut = (sprom[SPOFF(SSB_SPROM8_FEM2G)] & +-- SSB_SROM8_FEM_ANTSWLUT) >> SSB_SROM8_FEM_ANTSWLUT_SHIFT; +-- +-- bus->sprom.fem.ghz5.tssipos = (sprom[SPOFF(SSB_SPROM8_FEM5G)] & +-- SSB_SROM8_FEM_TSSIPOS) >> SSB_SROM8_FEM_TSSIPOS_SHIFT; +-- bus->sprom.fem.ghz5.extpa_gain = (sprom[SPOFF(SSB_SPROM8_FEM5G)] & +-- SSB_SROM8_FEM_EXTPA_GAIN) >> SSB_SROM8_FEM_EXTPA_GAIN_SHIFT; +-- bus->sprom.fem.ghz5.pdet_range = (sprom[SPOFF(SSB_SPROM8_FEM5G)] & +-- SSB_SROM8_FEM_PDET_RANGE) >> SSB_SROM8_FEM_PDET_RANGE_SHIFT; +-- bus->sprom.fem.ghz5.tr_iso = (sprom[SPOFF(SSB_SPROM8_FEM5G)] & +-- SSB_SROM8_FEM_TR_ISO) >> SSB_SROM8_FEM_TR_ISO_SHIFT; +-- bus->sprom.fem.ghz5.antswlut = (sprom[SPOFF(SSB_SPROM8_FEM5G)] & +-- SSB_SROM8_FEM_ANTSWLUT) >> SSB_SROM8_FEM_ANTSWLUT_SHIFT; +++ SPEX(board_type, SSB_SPROM1_SPID, ~0, 0); +++ + + SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0, + + SSB_SPROM4_TXPID2G0_SHIFT); + + SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G1, +@@ -2641,7 +3969,71 @@ + + case BCMA_CHIP_ID_BCM4331: + + present_mask = BCMA_CC_CHIPST_4331_SPROM_PRESENT; + + break; +-+ ++ ++- bus->sprom.txpid2g[0] = (sprom[SPOFF(SSB_SPROM4_TXPID2G01)] & ++- SSB_SPROM4_TXPID2G0) >> SSB_SPROM4_TXPID2G0_SHIFT; ++- bus->sprom.txpid2g[1] = (sprom[SPOFF(SSB_SPROM4_TXPID2G01)] & ++- SSB_SPROM4_TXPID2G1) >> SSB_SPROM4_TXPID2G1_SHIFT; ++- bus->sprom.txpid2g[2] = (sprom[SPOFF(SSB_SPROM4_TXPID2G23)] & ++- SSB_SPROM4_TXPID2G2) >> SSB_SPROM4_TXPID2G2_SHIFT; ++- bus->sprom.txpid2g[3] = (sprom[SPOFF(SSB_SPROM4_TXPID2G23)] & ++- SSB_SPROM4_TXPID2G3) >> SSB_SPROM4_TXPID2G3_SHIFT; ++- ++- bus->sprom.txpid5gl[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL01)] & ++- SSB_SPROM4_TXPID5GL0) >> SSB_SPROM4_TXPID5GL0_SHIFT; ++- bus->sprom.txpid5gl[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL01)] & ++- SSB_SPROM4_TXPID5GL1) >> SSB_SPROM4_TXPID5GL1_SHIFT; ++- bus->sprom.txpid5gl[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL23)] & ++- SSB_SPROM4_TXPID5GL2) >> SSB_SPROM4_TXPID5GL2_SHIFT; ++- bus->sprom.txpid5gl[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL23)] & ++- SSB_SPROM4_TXPID5GL3) >> SSB_SPROM4_TXPID5GL3_SHIFT; ++- ++- bus->sprom.txpid5g[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5G01)] & ++- SSB_SPROM4_TXPID5G0) >> SSB_SPROM4_TXPID5G0_SHIFT; ++- bus->sprom.txpid5g[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5G01)] & ++- SSB_SPROM4_TXPID5G1) >> SSB_SPROM4_TXPID5G1_SHIFT; ++- bus->sprom.txpid5g[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5G23)] & ++- SSB_SPROM4_TXPID5G2) >> SSB_SPROM4_TXPID5G2_SHIFT; ++- bus->sprom.txpid5g[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5G23)] & ++- SSB_SPROM4_TXPID5G3) >> SSB_SPROM4_TXPID5G3_SHIFT; ++- ++- bus->sprom.txpid5gh[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH01)] & ++- SSB_SPROM4_TXPID5GH0) >> SSB_SPROM4_TXPID5GH0_SHIFT; ++- bus->sprom.txpid5gh[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH01)] & ++- SSB_SPROM4_TXPID5GH1) >> SSB_SPROM4_TXPID5GH1_SHIFT; ++- bus->sprom.txpid5gh[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH23)] & ++- SSB_SPROM4_TXPID5GH2) >> SSB_SPROM4_TXPID5GH2_SHIFT; ++- bus->sprom.txpid5gh[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH23)] & ++- SSB_SPROM4_TXPID5GH3) >> SSB_SPROM4_TXPID5GH3_SHIFT; ++- ++- bus->sprom.boardflags_lo = sprom[SPOFF(SSB_SPROM8_BFLLO)]; ++- bus->sprom.boardflags_hi = sprom[SPOFF(SSB_SPROM8_BFLHI)]; ++- bus->sprom.boardflags2_lo = sprom[SPOFF(SSB_SPROM8_BFL2LO)]; ++- bus->sprom.boardflags2_hi = sprom[SPOFF(SSB_SPROM8_BFL2HI)]; ++- ++- bus->sprom.country_code = sprom[SPOFF(SSB_SPROM8_CCODE)]; ++- ++- bus->sprom.fem.ghz2.tssipos = (sprom[SPOFF(SSB_SPROM8_FEM2G)] & ++- SSB_SROM8_FEM_TSSIPOS) >> SSB_SROM8_FEM_TSSIPOS_SHIFT; ++- bus->sprom.fem.ghz2.extpa_gain = (sprom[SPOFF(SSB_SPROM8_FEM2G)] & ++- SSB_SROM8_FEM_EXTPA_GAIN) >> SSB_SROM8_FEM_EXTPA_GAIN_SHIFT; ++- bus->sprom.fem.ghz2.pdet_range = (sprom[SPOFF(SSB_SPROM8_FEM2G)] & ++- SSB_SROM8_FEM_PDET_RANGE) >> SSB_SROM8_FEM_PDET_RANGE_SHIFT; ++- bus->sprom.fem.ghz2.tr_iso = (sprom[SPOFF(SSB_SPROM8_FEM2G)] & ++- SSB_SROM8_FEM_TR_ISO) >> SSB_SROM8_FEM_TR_ISO_SHIFT; ++- bus->sprom.fem.ghz2.antswlut = (sprom[SPOFF(SSB_SPROM8_FEM2G)] & ++- SSB_SROM8_FEM_ANTSWLUT) >> SSB_SROM8_FEM_ANTSWLUT_SHIFT; ++- ++- bus->sprom.fem.ghz5.tssipos = (sprom[SPOFF(SSB_SPROM8_FEM5G)] & ++- SSB_SROM8_FEM_TSSIPOS) >> SSB_SROM8_FEM_TSSIPOS_SHIFT; ++- bus->sprom.fem.ghz5.extpa_gain = (sprom[SPOFF(SSB_SPROM8_FEM5G)] & ++- SSB_SROM8_FEM_EXTPA_GAIN) >> SSB_SROM8_FEM_EXTPA_GAIN_SHIFT; ++- bus->sprom.fem.ghz5.pdet_range = (sprom[SPOFF(SSB_SPROM8_FEM5G)] & ++- SSB_SROM8_FEM_PDET_RANGE) >> SSB_SROM8_FEM_PDET_RANGE_SHIFT; ++- bus->sprom.fem.ghz5.tr_iso = (sprom[SPOFF(SSB_SPROM8_FEM5G)] & ++- SSB_SROM8_FEM_TR_ISO) >> SSB_SROM8_FEM_TR_ISO_SHIFT; ++- bus->sprom.fem.ghz5.antswlut = (sprom[SPOFF(SSB_SPROM8_FEM5G)] & ++- SSB_SROM8_FEM_ANTSWLUT) >> SSB_SROM8_FEM_ANTSWLUT_SHIFT; + + default: + + return true; + + } +@@ -2667,13 +4059,17 @@ + + case BCMA_CHIP_ID_BCM4331: + + present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT; + + break; +-+ +++ case BCMA_CHIP_ID_BCM43142: + + case BCMA_CHIP_ID_BCM43224: + + case BCMA_CHIP_ID_BCM43225: + + /* for these chips OTP is always available */ + + present = true; + + break; +-+ +++ case BCMA_CHIP_ID_BCM43227: +++ case BCMA_CHIP_ID_BCM43228: +++ case BCMA_CHIP_ID_BCM43428: +++ present = chip_status & BCMA_CC_CHIPST_43228_OTP_PRESENT; +++ break; + + default: + + present = false; + + break; +@@ -2712,7 +4108,10 @@ + - u16 offset; + + u16 offset = BCMA_CC_SPROM; + u16 *sprom; +- int err = 0; ++- int err = 0; +++ size_t sprom_sizes[] = { SSB_SPROMSIZE_WORDS_R4, +++ SSB_SPROMSIZE_WORDS_R10, }; +++ int i, err = 0; + + if (!bus->drv_cc.core) + return -EOPNOTSUPP; +@@ -2721,7 +4120,11 @@ + - return -ENOENT; + + if (!bcma_sprom_ext_available(bus)) { + + bool sprom_onchip; +-+ ++ ++- sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), ++- GFP_KERNEL); ++- if (!sprom) ++- return -ENOMEM; + + /* + + * External SPROM takes precedence so check + + * on-chip OTP only when no external SPROM +@@ -2743,11 +4146,6 @@ + + } + + } + +- sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), +- GFP_KERNEL); +- if (!sprom) +- return -ENOMEM; +- + - if (bus->chipinfo.id == 0x4331) + + if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 || + + bus->chipinfo.id == BCMA_CHIP_ID_BCM43431) +@@ -2758,25 +4156,59 @@ + - * TODO: understand this condition and use it */ + - offset = (bus->chipinfo.id == 0x4331) ? BCMA_CC_SPROM : + - BCMA_CC_SPROM_PCIE6; ++- bcma_sprom_read(bus, offset, sprom); + + bcma_debug(bus, "SPROM offset 0x%x\n", offset); +- bcma_sprom_read(bus, offset, sprom); +++ for (i = 0; i < ARRAY_SIZE(sprom_sizes); i++) { +++ size_t words = sprom_sizes[i]; +++ +++ sprom = kcalloc(words, sizeof(u16), GFP_KERNEL); +++ if (!sprom) +++ return -ENOMEM; +++ +++ bcma_sprom_read(bus, offset, sprom, words); +++ err = bcma_sprom_valid(bus, sprom, words); +++ if (!err) +++ break; + + - if (bus->chipinfo.id == 0x4331) ++- bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true); +++ kfree(sprom); +++ } ++ ++- err = bcma_sprom_valid(sprom); ++- if (err) ++- goto out; + + if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 || + + bus->chipinfo.id == BCMA_CHIP_ID_BCM43431) +- bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true); +++ bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true); + +- err = bcma_sprom_valid(sprom); ++- bcma_sprom_extract_r8(bus, sprom); +++ if (err) { +++ bcma_warn(bus, "Invalid SPROM read from the PCIe card, trying to use fallback SPROM\n"); +++ err = bcma_fill_sprom_with_fallback(bus, &bus->sprom); +++ } else { +++ bcma_sprom_extract_r8(bus, sprom); +++ kfree(sprom); +++ } ++ ++-out: ++- kfree(sprom); ++ return err; ++ } + --- a/include/linux/bcma/bcma.h + +++ b/include/linux/bcma/bcma.h +-@@ -7,6 +7,7 @@ ++@@ -7,9 +7,10 @@ + #include + #include + #include + +#include + #include /* SPROM sharing */ + +- #include "bcma_regs.h" ++-#include "bcma_regs.h" +++#include ++ ++ struct bcma_device; ++ struct bcma_bus; + @@ -26,6 +27,11 @@ struct bcma_chipinfo { + u8 pkg; + }; +@@ -2803,12 +4235,21 @@ + #define BCMA_CORE_INVALID 0x700 + #define BCMA_CORE_CHIPCOMMON 0x800 + #define BCMA_CORE_ILINE20 0x801 +-@@ -125,6 +138,36 @@ struct bcma_host_ops { ++@@ -121,10 +134,104 @@ struct bcma_host_ops { ++ #define BCMA_CORE_I2S 0x834 ++ #define BCMA_CORE_SDR_DDR1_MEM_CTL 0x835 /* SDR/DDR1 memory controller core */ ++ #define BCMA_CORE_SHIM 0x837 /* SHIM component in ubus/6362 */ +++#define BCMA_CORE_PHY_AC 0x83B +++#define BCMA_CORE_PCIE2 0x83C /* PCI Express Gen2 */ +++#define BCMA_CORE_USB30_DEV 0x83D +++#define BCMA_CORE_ARM_CR4 0x83E ++ #define BCMA_CORE_DEFAULT 0xFFF + + #define BCMA_MAX_NR_CORES 16 + + +/* Chip IDs of PCIe devices */ + +#define BCMA_CHIP_ID_BCM4313 0x4313 +++#define BCMA_CHIP_ID_BCM43142 43142 + +#define BCMA_CHIP_ID_BCM43224 43224 + +#define BCMA_PKG_ID_BCM43224_FAB_CSM 0x8 + +#define BCMA_PKG_ID_BCM43224_FAB_SMIC 0xa +@@ -2826,6 +4267,7 @@ + + + +/* Chip IDs of SoCs */ + +#define BCMA_CHIP_ID_BCM4706 0x5300 +++#define BCMA_PKG_ID_BCM4706L 1 + +#define BCMA_CHIP_ID_BCM4716 0x4716 + +#define BCMA_PKG_ID_BCM4716 8 + +#define BCMA_PKG_ID_BCM4717 9 +@@ -2835,12 +4277,70 @@ + +#define BCMA_CHIP_ID_BCM4749 0x4749 + +#define BCMA_CHIP_ID_BCM5356 0x5356 + +#define BCMA_CHIP_ID_BCM5357 0x5357 +++#define BCMA_PKG_ID_BCM5358 9 +++#define BCMA_PKG_ID_BCM47186 10 +++#define BCMA_PKG_ID_BCM5357 11 + +#define BCMA_CHIP_ID_BCM53572 53572 +++#define BCMA_PKG_ID_BCM47188 9 + + +++/* Board types (on PCI usually equals to the subsystem dev id) */ +++/* BCM4313 */ +++#define BCMA_BOARD_TYPE_BCM94313BU 0X050F +++#define BCMA_BOARD_TYPE_BCM94313HM 0X0510 +++#define BCMA_BOARD_TYPE_BCM94313EPA 0X0511 +++#define BCMA_BOARD_TYPE_BCM94313HMG 0X051C +++/* BCM4716 */ +++#define BCMA_BOARD_TYPE_BCM94716NR2 0X04CD +++/* BCM43224 */ +++#define BCMA_BOARD_TYPE_BCM943224X21 0X056E +++#define BCMA_BOARD_TYPE_BCM943224X21_FCC 0X00D1 +++#define BCMA_BOARD_TYPE_BCM943224X21B 0X00E9 +++#define BCMA_BOARD_TYPE_BCM943224M93 0X008B +++#define BCMA_BOARD_TYPE_BCM943224M93A 0X0090 +++#define BCMA_BOARD_TYPE_BCM943224X16 0X0093 +++#define BCMA_BOARD_TYPE_BCM94322X9 0X008D +++#define BCMA_BOARD_TYPE_BCM94322M35E 0X008E +++/* BCM43228 */ +++#define BCMA_BOARD_TYPE_BCM943228BU8 0X0540 +++#define BCMA_BOARD_TYPE_BCM943228BU9 0X0541 +++#define BCMA_BOARD_TYPE_BCM943228BU 0X0542 +++#define BCMA_BOARD_TYPE_BCM943227HM4L 0X0543 +++#define BCMA_BOARD_TYPE_BCM943227HMB 0X0544 +++#define BCMA_BOARD_TYPE_BCM943228HM4L 0X0545 +++#define BCMA_BOARD_TYPE_BCM943228SD 0X0573 +++/* BCM4331 */ +++#define BCMA_BOARD_TYPE_BCM94331X19 0X00D6 +++#define BCMA_BOARD_TYPE_BCM94331X28 0X00E4 +++#define BCMA_BOARD_TYPE_BCM94331X28B 0X010E +++#define BCMA_BOARD_TYPE_BCM94331PCIEBT3AX 0X00E4 +++#define BCMA_BOARD_TYPE_BCM94331X12_2G 0X00EC +++#define BCMA_BOARD_TYPE_BCM94331X12_5G 0X00ED +++#define BCMA_BOARD_TYPE_BCM94331X29B 0X00EF +++#define BCMA_BOARD_TYPE_BCM94331CSAX 0X00EF +++#define BCMA_BOARD_TYPE_BCM94331X19C 0X00F5 +++#define BCMA_BOARD_TYPE_BCM94331X33 0X00F4 +++#define BCMA_BOARD_TYPE_BCM94331BU 0X0523 +++#define BCMA_BOARD_TYPE_BCM94331S9BU 0X0524 +++#define BCMA_BOARD_TYPE_BCM94331MC 0X0525 +++#define BCMA_BOARD_TYPE_BCM94331MCI 0X0526 +++#define BCMA_BOARD_TYPE_BCM94331PCIEBT4 0X0527 +++#define BCMA_BOARD_TYPE_BCM94331HM 0X0574 +++#define BCMA_BOARD_TYPE_BCM94331PCIEDUAL 0X059B +++#define BCMA_BOARD_TYPE_BCM94331MCH5 0X05A9 +++#define BCMA_BOARD_TYPE_BCM94331CS 0X05C6 +++#define BCMA_BOARD_TYPE_BCM94331CD 0X05DA +++/* BCM53572 */ +++#define BCMA_BOARD_TYPE_BCM953572BU 0X058D +++#define BCMA_BOARD_TYPE_BCM953572NR2 0X058E +++#define BCMA_BOARD_TYPE_BCM947188NR2 0X058F +++#define BCMA_BOARD_TYPE_BCM953572SDRNR2 0X0590 +++/* BCM43142 */ +++#define BCMA_BOARD_TYPE_BCM943142HM 0X05E0 +++ + struct bcma_device { + struct bcma_bus *bus; + struct bcma_device_id id; +-@@ -136,8 +179,10 @@ struct bcma_device { ++@@ -136,8 +243,10 @@ struct bcma_device { + bool dev_registered; + + u8 core_index; +@@ -2851,7 +4351,7 @@ + u32 wrap; + + void __iomem *io_addr; +-@@ -175,6 +220,12 @@ int __bcma_driver_register(struct bcma_d ++@@ -175,6 +284,12 @@ int __bcma_driver_register(struct bcma_d + + extern void bcma_driver_unregister(struct bcma_driver *drv); + +@@ -2864,7 +4364,7 @@ + struct bcma_bus { + /* The MMIO area. */ + void __iomem *mmio; +-@@ -191,14 +242,18 @@ struct bcma_bus { ++@@ -191,14 +306,18 @@ struct bcma_bus { + + struct bcma_chipinfo chipinfo; + +@@ -2877,13 +4377,14 @@ + + u8 num; + + struct bcma_drv_cc drv_cc; +- struct bcma_drv_pci drv_pci; ++- struct bcma_drv_pci drv_pci; +++ struct bcma_drv_pci drv_pci[2]; + struct bcma_drv_mips drv_mips; + + struct bcma_drv_gmac_cmn drv_gmac_cmn; + + /* We decided to share SPROM struct with SSB as long as we do not need + * any hacks for BCMA. This simplifies drivers code. */ +-@@ -282,6 +337,7 @@ static inline void bcma_maskset16(struct ++@@ -282,6 +401,7 @@ static inline void bcma_maskset16(struct + bcma_write16(cc, offset, (bcma_read16(cc, offset) & mask) | set); + } + +@@ -2891,9 +4392,44 @@ + extern bool bcma_core_is_enabled(struct bcma_device *core); + extern void bcma_core_disable(struct bcma_device *core, u32 flags); + extern int bcma_core_enable(struct bcma_device *core, u32 flags); ++@@ -289,6 +409,7 @@ extern void bcma_core_set_clockmode(stru ++ enum bcma_clkmode clkmode); ++ extern void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, ++ bool on); +++extern u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset); ++ #define BCMA_DMA_TRANSLATION_MASK 0xC0000000 ++ #define BCMA_DMA_TRANSLATION_NONE 0x00000000 ++ #define BCMA_DMA_TRANSLATION_DMA32_CMT 0x40000000 /* Client Mode Translation for 32-bit DMA */ + --- a/include/linux/bcma/bcma_driver_chipcommon.h + +++ b/include/linux/bcma/bcma_driver_chipcommon.h +-@@ -56,6 +56,9 @@ ++@@ -1,6 +1,9 @@ ++ #ifndef LINUX_BCMA_DRIVER_CC_H_ ++ #define LINUX_BCMA_DRIVER_CC_H_ ++ +++#include +++#include +++ ++ /** ChipCommon core registers. **/ ++ #define BCMA_CC_ID 0x0000 ++ #define BCMA_CC_ID_ID 0x0000FFFF ++@@ -24,7 +27,7 @@ ++ #define BCMA_CC_FLASHT_NONE 0x00000000 /* No flash */ ++ #define BCMA_CC_FLASHT_STSER 0x00000100 /* ST serial flash */ ++ #define BCMA_CC_FLASHT_ATSER 0x00000200 /* Atmel serial flash */ ++-#define BCMA_CC_FLASHT_NFLASH 0x00000200 +++#define BCMA_CC_FLASHT_NAND 0x00000300 /* NAND flash */ ++ #define BCMA_CC_FLASHT_PARA 0x00000700 /* Parallel flash */ ++ #define BCMA_CC_CAP_PLLT 0x00038000 /* PLL Type */ ++ #define BCMA_PLLTYPE_NONE 0x00000000 ++@@ -45,6 +48,7 @@ ++ #define BCMA_CC_CAP_PMU 0x10000000 /* PMU available (rev >= 20) */ ++ #define BCMA_CC_CAP_ECI 0x20000000 /* ECI available (rev >= 20) */ ++ #define BCMA_CC_CAP_SPROM 0x40000000 /* SPROM present */ +++#define BCMA_CC_CAP_NFLASH 0x80000000 /* NAND flash present (rev >= 35 or BCM4706?) */ ++ #define BCMA_CC_CORECTL 0x0008 ++ #define BCMA_CC_CORECTL_UARTCLK0 0x00000001 /* Drive UART with internal clock */ ++ #define BCMA_CC_CORECTL_SE 0x00000002 /* sync clk out enable (corerev >= 3) */ ++@@ -56,6 +60,9 @@ + #define BCMA_CC_OTPS_HW_PROTECT 0x00000001 + #define BCMA_CC_OTPS_SW_PROTECT 0x00000002 + #define BCMA_CC_OTPS_CID_PROTECT 0x00000004 +@@ -2903,7 +4439,7 @@ + #define BCMA_CC_OTPC 0x0014 /* OTP control */ + #define BCMA_CC_OTPC_RECWAIT 0xFF000000 + #define BCMA_CC_OTPC_PROGWAIT 0x00FFFF00 +-@@ -72,6 +75,8 @@ ++@@ -72,6 +79,8 @@ + #define BCMA_CC_OTPP_READ 0x40000000 + #define BCMA_CC_OTPP_START 0x80000000 + #define BCMA_CC_OTPP_BUSY 0x80000000 +@@ -2912,7 +4448,7 @@ + #define BCMA_CC_IRQSTAT 0x0020 + #define BCMA_CC_IRQMASK 0x0024 + #define BCMA_CC_IRQ_GPIO 0x00000001 /* gpio intr */ +-@@ -79,6 +84,15 @@ ++@@ -79,6 +88,23 @@ + #define BCMA_CC_IRQ_WDRESET 0x80000000 /* watchdog reset occurred */ + #define BCMA_CC_CHIPCTL 0x0028 /* Rev >= 11 only */ + #define BCMA_CC_CHIPSTAT 0x002C /* Rev >= 11 only */ +@@ -2920,15 +4456,82 @@ + +#define BCMA_CC_CHIPST_4313_OTP_PRESENT 2 + +#define BCMA_CC_CHIPST_4331_SPROM_PRESENT 2 + +#define BCMA_CC_CHIPST_4331_OTP_PRESENT 4 +++#define BCMA_CC_CHIPST_43228_ILP_DIV_EN 0x00000001 +++#define BCMA_CC_CHIPST_43228_OTP_PRESENT 0x00000002 +++#define BCMA_CC_CHIPST_43228_SERDES_REFCLK_PADSEL 0x00000004 +++#define BCMA_CC_CHIPST_43228_SDIO_MODE 0x00000008 +++#define BCMA_CC_CHIPST_43228_SDIO_OTP_PRESENT 0x00000010 +++#define BCMA_CC_CHIPST_43228_SDIO_RESET 0x00000020 + +#define BCMA_CC_CHIPST_4706_PKG_OPTION BIT(0) /* 0: full-featured package 1: low-cost package */ + +#define BCMA_CC_CHIPST_4706_SFLASH_PRESENT BIT(1) /* 0: parallel, 1: serial flash is present */ + +#define BCMA_CC_CHIPST_4706_SFLASH_TYPE BIT(2) /* 0: 8b-p/ST-s flash, 1: 16b-p/Atmal-s flash */ + +#define BCMA_CC_CHIPST_4706_MIPS_BENDIAN BIT(3) /* 0: little, 1: big endian */ + +#define BCMA_CC_CHIPST_4706_PCIE1_DISABLE BIT(5) /* PCIE1 enable strap pin */ +++#define BCMA_CC_CHIPST_5357_NAND_BOOT BIT(4) /* NAND boot, valid for CC rev 38 and/or BCM5357 */ +++#define BCMA_CC_CHIPST_4360_XTAL_40MZ 0x00000001 + #define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */ + #define BCMA_CC_JCMD_START 0x80000000 + #define BCMA_CC_JCMD_BUSY 0x80000000 +-@@ -181,6 +195,22 @@ ++@@ -108,10 +134,58 @@ ++ #define BCMA_CC_JCTL_EXT_EN 2 /* Enable external targets */ ++ #define BCMA_CC_JCTL_EN 1 /* Enable Jtag master */ ++ #define BCMA_CC_FLASHCTL 0x0040 +++/* Start/busy bit in flashcontrol */ +++#define BCMA_CC_FLASHCTL_OPCODE 0x000000ff +++#define BCMA_CC_FLASHCTL_ACTION 0x00000700 +++#define BCMA_CC_FLASHCTL_CS_ACTIVE 0x00001000 /* Chip Select Active, rev >= 20 */ ++ #define BCMA_CC_FLASHCTL_START 0x80000000 ++ #define BCMA_CC_FLASHCTL_BUSY BCMA_CC_FLASHCTL_START +++/* Flashcontrol action + opcodes for ST flashes */ +++#define BCMA_CC_FLASHCTL_ST_WREN 0x0006 /* Write Enable */ +++#define BCMA_CC_FLASHCTL_ST_WRDIS 0x0004 /* Write Disable */ +++#define BCMA_CC_FLASHCTL_ST_RDSR 0x0105 /* Read Status Register */ +++#define BCMA_CC_FLASHCTL_ST_WRSR 0x0101 /* Write Status Register */ +++#define BCMA_CC_FLASHCTL_ST_READ 0x0303 /* Read Data Bytes */ +++#define BCMA_CC_FLASHCTL_ST_PP 0x0302 /* Page Program */ +++#define BCMA_CC_FLASHCTL_ST_SE 0x02d8 /* Sector Erase */ +++#define BCMA_CC_FLASHCTL_ST_BE 0x00c7 /* Bulk Erase */ +++#define BCMA_CC_FLASHCTL_ST_DP 0x00b9 /* Deep Power-down */ +++#define BCMA_CC_FLASHCTL_ST_RES 0x03ab /* Read Electronic Signature */ +++#define BCMA_CC_FLASHCTL_ST_CSA 0x1000 /* Keep chip select asserted */ +++#define BCMA_CC_FLASHCTL_ST_SSE 0x0220 /* Sub-sector Erase */ +++/* Flashcontrol action + opcodes for Atmel flashes */ +++#define BCMA_CC_FLASHCTL_AT_READ 0x07e8 +++#define BCMA_CC_FLASHCTL_AT_PAGE_READ 0x07d2 +++#define BCMA_CC_FLASHCTL_AT_STATUS 0x01d7 +++#define BCMA_CC_FLASHCTL_AT_BUF1_WRITE 0x0384 +++#define BCMA_CC_FLASHCTL_AT_BUF2_WRITE 0x0387 +++#define BCMA_CC_FLASHCTL_AT_BUF1_ERASE_PROGRAM 0x0283 +++#define BCMA_CC_FLASHCTL_AT_BUF2_ERASE_PROGRAM 0x0286 +++#define BCMA_CC_FLASHCTL_AT_BUF1_PROGRAM 0x0288 +++#define BCMA_CC_FLASHCTL_AT_BUF2_PROGRAM 0x0289 +++#define BCMA_CC_FLASHCTL_AT_PAGE_ERASE 0x0281 +++#define BCMA_CC_FLASHCTL_AT_BLOCK_ERASE 0x0250 +++#define BCMA_CC_FLASHCTL_AT_BUF1_WRITE_ERASE_PROGRAM 0x0382 +++#define BCMA_CC_FLASHCTL_AT_BUF2_WRITE_ERASE_PROGRAM 0x0385 +++#define BCMA_CC_FLASHCTL_AT_BUF1_LOAD 0x0253 +++#define BCMA_CC_FLASHCTL_AT_BUF2_LOAD 0x0255 +++#define BCMA_CC_FLASHCTL_AT_BUF1_COMPARE 0x0260 +++#define BCMA_CC_FLASHCTL_AT_BUF2_COMPARE 0x0261 +++#define BCMA_CC_FLASHCTL_AT_BUF1_REPROGRAM 0x0258 +++#define BCMA_CC_FLASHCTL_AT_BUF2_REPROGRAM 0x0259 ++ #define BCMA_CC_FLASHADDR 0x0044 ++ #define BCMA_CC_FLASHDATA 0x0048 +++/* Status register bits for ST flashes */ +++#define BCMA_CC_FLASHDATA_ST_WIP 0x01 /* Write In Progress */ +++#define BCMA_CC_FLASHDATA_ST_WEL 0x02 /* Write Enable Latch */ +++#define BCMA_CC_FLASHDATA_ST_BP_MASK 0x1c /* Block Protect */ +++#define BCMA_CC_FLASHDATA_ST_BP_SHIFT 2 +++#define BCMA_CC_FLASHDATA_ST_SRWD 0x80 /* Status Register Write Disable */ +++/* Status register bits for Atmel flashes */ +++#define BCMA_CC_FLASHDATA_AT_READY 0x80 +++#define BCMA_CC_FLASHDATA_AT_MISMATCH 0x40 +++#define BCMA_CC_FLASHDATA_AT_ID_MASK 0x38 +++#define BCMA_CC_FLASHDATA_AT_ID_SHIFT 3 ++ #define BCMA_CC_BCAST_ADDR 0x0050 ++ #define BCMA_CC_BCAST_DATA 0x0054 ++ #define BCMA_CC_GPIOPULLUP 0x0058 /* Rev >= 20 only */ ++@@ -181,6 +255,45 @@ + #define BCMA_CC_FLASH_CFG 0x0128 + #define BCMA_CC_FLASH_CFG_DS 0x0010 /* Data size, 0=8bit, 1=16bit */ + #define BCMA_CC_FLASH_WAITCNT 0x012C +@@ -2948,18 +4551,120 @@ + +#define BCMA_CC_SROM_CONTROL_SIZE_16K 0x00000004 + +#define BCMA_CC_SROM_CONTROL_SIZE_SHIFT 1 + +#define BCMA_CC_SROM_CONTROL_PRESENT 0x00000001 +++/* Block 0x140 - 0x190 registers are chipset specific */ +++#define BCMA_CC_4706_FLASHSCFG 0x18C /* Flash struct configuration */ +++#define BCMA_CC_4706_FLASHSCFG_MASK 0x000000ff +++#define BCMA_CC_4706_FLASHSCFG_SF1 0x00000001 /* 2nd serial flash present */ +++#define BCMA_CC_4706_FLASHSCFG_PF1 0x00000002 /* 2nd parallel flash present */ +++#define BCMA_CC_4706_FLASHSCFG_SF1_TYPE 0x00000004 /* 2nd serial flash type : 0 : ST, 1 : Atmel */ +++#define BCMA_CC_4706_FLASHSCFG_NF1 0x00000008 /* 2nd NAND flash present */ +++#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_MASK 0x000000f0 +++#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_4MB 0x00000010 /* 4MB */ +++#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_8MB 0x00000020 /* 8MB */ +++#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_16MB 0x00000030 /* 16MB */ +++#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_32MB 0x00000040 /* 32MB */ +++#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_64MB 0x00000050 /* 64MB */ +++#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_128MB 0x00000060 /* 128MB */ +++#define BCMA_CC_4706_FLASHSCFG_1ST_MADDR_SEG_256MB 0x00000070 /* 256MB */ +++/* NAND flash registers for BCM4706 (corerev = 31) */ +++#define BCMA_CC_NFLASH_CTL 0x01A0 +++#define BCMA_CC_NFLASH_CTL_ERR 0x08000000 +++#define BCMA_CC_NFLASH_CONF 0x01A4 +++#define BCMA_CC_NFLASH_COL_ADDR 0x01A8 +++#define BCMA_CC_NFLASH_ROW_ADDR 0x01AC +++#define BCMA_CC_NFLASH_DATA 0x01B0 +++#define BCMA_CC_NFLASH_WAITCNT0 0x01B4 + /* 0x1E0 is defined as shared BCMA_CLKCTLST */ + #define BCMA_CC_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */ + #define BCMA_CC_UART0_DATA 0x0300 +-@@ -240,7 +270,6 @@ ++@@ -203,6 +316,9 @@ ++ #define BCMA_CC_PMU_CTL 0x0600 /* PMU control */ ++ #define BCMA_CC_PMU_CTL_ILP_DIV 0xFFFF0000 /* ILP div mask */ ++ #define BCMA_CC_PMU_CTL_ILP_DIV_SHIFT 16 +++#define BCMA_CC_PMU_CTL_RES 0x00006000 /* reset control mask */ +++#define BCMA_CC_PMU_CTL_RES_SHIFT 13 +++#define BCMA_CC_PMU_CTL_RES_RELOAD 0x2 /* reload POR values */ ++ #define BCMA_CC_PMU_CTL_PLL_UPD 0x00000400 ++ #define BCMA_CC_PMU_CTL_NOILPONW 0x00000200 /* No ILP on wait */ ++ #define BCMA_CC_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */ ++@@ -214,6 +330,8 @@ ++ #define BCMA_CC_PMU_CAP 0x0604 /* PMU capabilities */ ++ #define BCMA_CC_PMU_CAP_REVISION 0x000000FF /* Revision mask */ ++ #define BCMA_CC_PMU_STAT 0x0608 /* PMU status */ +++#define BCMA_CC_PMU_STAT_EXT_LPO_AVAIL 0x00000100 +++#define BCMA_CC_PMU_STAT_WDRESET 0x00000080 ++ #define BCMA_CC_PMU_STAT_INTPEND 0x00000040 /* Interrupt pending */ ++ #define BCMA_CC_PMU_STAT_SBCLKST 0x00000030 /* Backplane clock status? */ ++ #define BCMA_CC_PMU_STAT_HAVEALP 0x00000008 /* ALP available */ ++@@ -239,8 +357,66 @@ ++ #define BCMA_CC_REGCTL_DATA 0x065C + #define BCMA_CC_PLLCTL_ADDR 0x0660 + #define BCMA_CC_PLLCTL_DATA 0x0664 +++#define BCMA_CC_PMU_STRAPOPT 0x0668 /* (corerev >= 28) */ +++#define BCMA_CC_PMU_XTAL_FREQ 0x066C /* (pmurev >= 10) */ +++#define BCMA_CC_PMU_XTAL_FREQ_ILPCTL_MASK 0x00001FFF +++#define BCMA_CC_PMU_XTAL_FREQ_MEASURE_MASK 0x80000000 +++#define BCMA_CC_PMU_XTAL_FREQ_MEASURE_SHIFT 31 + #define BCMA_CC_SPROM 0x0800 /* SPROM beginning */ + -#define BCMA_CC_SPROM_PCIE6 0x0830 /* SPROM beginning on PCIe rev >= 6 */ +++/* NAND flash MLC controller registers (corerev >= 38) */ +++#define BCMA_CC_NAND_REVISION 0x0C00 +++#define BCMA_CC_NAND_CMD_START 0x0C04 +++#define BCMA_CC_NAND_CMD_ADDR_X 0x0C08 +++#define BCMA_CC_NAND_CMD_ADDR 0x0C0C +++#define BCMA_CC_NAND_CMD_END_ADDR 0x0C10 +++#define BCMA_CC_NAND_CS_NAND_SELECT 0x0C14 +++#define BCMA_CC_NAND_CS_NAND_XOR 0x0C18 +++#define BCMA_CC_NAND_SPARE_RD0 0x0C20 +++#define BCMA_CC_NAND_SPARE_RD4 0x0C24 +++#define BCMA_CC_NAND_SPARE_RD8 0x0C28 +++#define BCMA_CC_NAND_SPARE_RD12 0x0C2C +++#define BCMA_CC_NAND_SPARE_WR0 0x0C30 +++#define BCMA_CC_NAND_SPARE_WR4 0x0C34 +++#define BCMA_CC_NAND_SPARE_WR8 0x0C38 +++#define BCMA_CC_NAND_SPARE_WR12 0x0C3C +++#define BCMA_CC_NAND_ACC_CONTROL 0x0C40 +++#define BCMA_CC_NAND_CONFIG 0x0C48 +++#define BCMA_CC_NAND_TIMING_1 0x0C50 +++#define BCMA_CC_NAND_TIMING_2 0x0C54 +++#define BCMA_CC_NAND_SEMAPHORE 0x0C58 +++#define BCMA_CC_NAND_DEVID 0x0C60 +++#define BCMA_CC_NAND_DEVID_X 0x0C64 +++#define BCMA_CC_NAND_BLOCK_LOCK_STATUS 0x0C68 +++#define BCMA_CC_NAND_INTFC_STATUS 0x0C6C +++#define BCMA_CC_NAND_ECC_CORR_ADDR_X 0x0C70 +++#define BCMA_CC_NAND_ECC_CORR_ADDR 0x0C74 +++#define BCMA_CC_NAND_ECC_UNC_ADDR_X 0x0C78 +++#define BCMA_CC_NAND_ECC_UNC_ADDR 0x0C7C +++#define BCMA_CC_NAND_READ_ERROR_COUNT 0x0C80 +++#define BCMA_CC_NAND_CORR_STAT_THRESHOLD 0x0C84 +++#define BCMA_CC_NAND_READ_ADDR_X 0x0C90 +++#define BCMA_CC_NAND_READ_ADDR 0x0C94 +++#define BCMA_CC_NAND_PAGE_PROGRAM_ADDR_X 0x0C98 +++#define BCMA_CC_NAND_PAGE_PROGRAM_ADDR 0x0C9C +++#define BCMA_CC_NAND_COPY_BACK_ADDR_X 0x0CA0 +++#define BCMA_CC_NAND_COPY_BACK_ADDR 0x0CA4 +++#define BCMA_CC_NAND_BLOCK_ERASE_ADDR_X 0x0CA8 +++#define BCMA_CC_NAND_BLOCK_ERASE_ADDR 0x0CAC +++#define BCMA_CC_NAND_INV_READ_ADDR_X 0x0CB0 +++#define BCMA_CC_NAND_INV_READ_ADDR 0x0CB4 +++#define BCMA_CC_NAND_BLK_WR_PROTECT 0x0CC0 +++#define BCMA_CC_NAND_ACC_CONTROL_CS1 0x0CD0 +++#define BCMA_CC_NAND_CONFIG_CS1 0x0CD4 +++#define BCMA_CC_NAND_TIMING_1_CS1 0x0CD8 +++#define BCMA_CC_NAND_TIMING_2_CS1 0x0CDC +++#define BCMA_CC_NAND_SPARE_RD16 0x0D30 +++#define BCMA_CC_NAND_SPARE_RD20 0x0D34 +++#define BCMA_CC_NAND_SPARE_RD24 0x0D38 +++#define BCMA_CC_NAND_SPARE_RD28 0x0D3C +++#define BCMA_CC_NAND_CACHE_ADDR 0x0D40 +++#define BCMA_CC_NAND_CACHE_DATA 0x0D44 +++#define BCMA_CC_NAND_CTRL_CONFIG 0x0D48 +++#define BCMA_CC_NAND_CTRL_STATUS 0x0D4C + + /* Divider allocation in 4716/47162/5356 */ + #define BCMA_CC_PMU5_MAINPLL_CPU 1 +-@@ -256,6 +285,15 @@ ++@@ -256,6 +432,32 @@ + + /* 4706 PMU */ + #define BCMA_CC_PMU4706_MAINPLL_PLL0 0 +@@ -2972,10 +4677,27 @@ + +#define BCMA_CC_PMU6_4706_PROC_NDIV_INT_SHIFT 3 + +#define BCMA_CC_PMU6_4706_PROC_NDIV_MODE_MASK 0x00000007 + +#define BCMA_CC_PMU6_4706_PROC_NDIV_MODE_SHIFT 0 +++ +++/* PMU rev 15 */ +++#define BCMA_CC_PMU15_PLL_PLLCTL0 0 +++#define BCMA_CC_PMU15_PLL_PC0_CLKSEL_MASK 0x00000003 +++#define BCMA_CC_PMU15_PLL_PC0_CLKSEL_SHIFT 0 +++#define BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK 0x003FFFFC +++#define BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT 2 +++#define BCMA_CC_PMU15_PLL_PC0_PRESCALE_MASK 0x00C00000 +++#define BCMA_CC_PMU15_PLL_PC0_PRESCALE_SHIFT 22 +++#define BCMA_CC_PMU15_PLL_PC0_KPCTRL_MASK 0x07000000 +++#define BCMA_CC_PMU15_PLL_PC0_KPCTRL_SHIFT 24 +++#define BCMA_CC_PMU15_PLL_PC0_FCNTCTRL_MASK 0x38000000 +++#define BCMA_CC_PMU15_PLL_PC0_FCNTCTRL_SHIFT 27 +++#define BCMA_CC_PMU15_PLL_PC0_FDCMODE_MASK 0x40000000 +++#define BCMA_CC_PMU15_PLL_PC0_FDCMODE_SHIFT 30 +++#define BCMA_CC_PMU15_PLL_PC0_CTRLBIAS_MASK 0x80000000 +++#define BCMA_CC_PMU15_PLL_PC0_CTRLBIAS_SHIFT 31 + + /* ALP clock on pre-PMU chips */ + #define BCMA_CC_PMU_ALP_CLOCK 20000000 +-@@ -284,6 +322,19 @@ ++@@ -284,6 +486,19 @@ + #define BCMA_CC_PPL_PCHI_OFF 5 + #define BCMA_CC_PPL_PCHI_MASK 0x0000003f + +@@ -2995,7 +4717,7 @@ + /* BCM4331 ChipControl numbers. */ + #define BCMA_CHIPCTL_4331_BT_COEXIST BIT(0) /* 0 disable */ + #define BCMA_CHIPCTL_4331_SECI BIT(1) /* 0 SECI is disabled (JATG functional) */ +-@@ -297,9 +348,18 @@ ++@@ -297,9 +512,56 @@ + #define BCMA_CHIPCTL_4331_OVR_PIPEAUXPWRDOWN BIT(9) /* override core control on pipe_AuxPowerDown */ + #define BCMA_CHIPCTL_4331_PCIE_AUXCLKEN BIT(10) /* pcie_auxclkenable */ + #define BCMA_CHIPCTL_4331_PCIE_PIPE_PLLDOWN BIT(11) /* pcie_pipe_pllpowerdown */ +@@ -3011,14 +4733,109 @@ + +/* 4313 Chip specific ChipControl register bits */ + +#define BCMA_CCTRL_4313_12MA_LED_DRIVE 0x00000007 /* 12 mA drive strengh for later 4313 */ + + +++/* BCM5357 ChipControl register bits */ +++#define BCMA_CHIPCTL_5357_EXTPA BIT(14) +++#define BCMA_CHIPCTL_5357_ANT_MUX_2O3 BIT(15) +++#define BCMA_CHIPCTL_5357_NFLASH BIT(16) +++#define BCMA_CHIPCTL_5357_I2S_PINS_ENABLE BIT(18) +++#define BCMA_CHIPCTL_5357_I2CSPI_PINS_ENABLE BIT(19) +++ +++#define BCMA_RES_4314_LPLDO_PU BIT(0) +++#define BCMA_RES_4314_PMU_SLEEP_DIS BIT(1) +++#define BCMA_RES_4314_PMU_BG_PU BIT(2) +++#define BCMA_RES_4314_CBUCK_LPOM_PU BIT(3) +++#define BCMA_RES_4314_CBUCK_PFM_PU BIT(4) +++#define BCMA_RES_4314_CLDO_PU BIT(5) +++#define BCMA_RES_4314_LPLDO2_LVM BIT(6) +++#define BCMA_RES_4314_WL_PMU_PU BIT(7) +++#define BCMA_RES_4314_LNLDO_PU BIT(8) +++#define BCMA_RES_4314_LDO3P3_PU BIT(9) +++#define BCMA_RES_4314_OTP_PU BIT(10) +++#define BCMA_RES_4314_XTAL_PU BIT(11) +++#define BCMA_RES_4314_WL_PWRSW_PU BIT(12) +++#define BCMA_RES_4314_LQ_AVAIL BIT(13) +++#define BCMA_RES_4314_LOGIC_RET BIT(14) +++#define BCMA_RES_4314_MEM_SLEEP BIT(15) +++#define BCMA_RES_4314_MACPHY_RET BIT(16) +++#define BCMA_RES_4314_WL_CORE_READY BIT(17) +++#define BCMA_RES_4314_ILP_REQ BIT(18) +++#define BCMA_RES_4314_ALP_AVAIL BIT(19) +++#define BCMA_RES_4314_MISC_PWRSW_PU BIT(20) +++#define BCMA_RES_4314_SYNTH_PWRSW_PU BIT(21) +++#define BCMA_RES_4314_RX_PWRSW_PU BIT(22) +++#define BCMA_RES_4314_RADIO_PU BIT(23) +++#define BCMA_RES_4314_VCO_LDO_PU BIT(24) +++#define BCMA_RES_4314_AFE_LDO_PU BIT(25) +++#define BCMA_RES_4314_RX_LDO_PU BIT(26) +++#define BCMA_RES_4314_TX_LDO_PU BIT(27) +++#define BCMA_RES_4314_HT_AVAIL BIT(28) +++#define BCMA_RES_4314_MACPHY_CLK_AVAIL BIT(29) +++ + /* Data for the PMU, if available. + * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU) + */ +-@@ -387,5 +447,6 @@ extern void bcma_chipco_chipctl_maskset( ++@@ -330,6 +592,7 @@ struct bcma_drv_cc { ++ u32 capabilities; ++ u32 capabilities_ext; ++ u8 setup_done:1; +++ u8 early_setup_done:1; ++ /* Fast Powerup Delay constant */ ++ u16 fast_pwrup_delay; ++ struct bcma_chipcommon_pmu pmu; ++@@ -339,6 +602,14 @@ struct bcma_drv_cc { ++ int nr_serial_ports; ++ struct bcma_serial_port serial_ports[4]; ++ #endif /* CONFIG_BCMA_DRIVER_MIPS */ +++ u32 ticks_per_ms; +++ struct platform_device *watchdog; +++ +++ /* Lock for GPIO register access. */ +++ spinlock_t gpio_lock; +++#ifdef CONFIG_BCMA_DRIVER_GPIO +++ struct gpio_chip gpio; +++#endif ++ }; ++ ++ /* Register access */ ++@@ -355,14 +626,16 @@ struct bcma_drv_cc { ++ bcma_cc_write32(cc, offset, (bcma_cc_read32(cc, offset) & (mask)) | (set)) ++ ++ extern void bcma_core_chipcommon_init(struct bcma_drv_cc *cc); +++extern void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc); ++ ++ extern void bcma_chipco_suspend(struct bcma_drv_cc *cc); ++ extern void bcma_chipco_resume(struct bcma_drv_cc *cc); ++ ++ void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable); ++ ++-extern void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, ++- u32 ticks); +++extern u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks); +++ +++extern u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc); ++ ++ void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value); ++ ++@@ -375,9 +648,12 @@ u32 bcma_chipco_gpio_outen(struct bcma_d ++ u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value); ++ u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value); ++ u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value); +++u32 bcma_chipco_gpio_pullup(struct bcma_drv_cc *cc, u32 mask, u32 value); +++u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value); ++ ++ /* PMU support */ ++ extern void bcma_pmu_init(struct bcma_drv_cc *cc); +++extern void bcma_pmu_early_init(struct bcma_drv_cc *cc); ++ ++ extern void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, ++ u32 value); ++@@ -387,5 +663,8 @@ extern void bcma_chipco_chipctl_maskset( + u32 offset, u32 mask, u32 set); + extern void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, + u32 offset, u32 mask, u32 set); + +extern void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid); +++ +++extern u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc); + + #endif /* LINUX_BCMA_DRIVER_CC_H_ */ + --- /dev/null +@@ -3124,6 +4941,44 @@ + +#endif + + + +#endif /* LINUX_BCMA_DRIVER_GMAC_CMN_H_ */ ++--- a/include/linux/bcma/bcma_driver_mips.h +++++ b/include/linux/bcma/bcma_driver_mips.h ++@@ -28,6 +28,7 @@ ++ #define BCMA_MIPS_MIPS74K_GPIOEN 0x0048 ++ #define BCMA_MIPS_MIPS74K_CLKCTLST 0x01E0 ++ +++#define BCMA_MIPS_OOBSELINA74 0x004 ++ #define BCMA_MIPS_OOBSELOUTA30 0x100 ++ ++ struct bcma_device; ++@@ -35,17 +36,24 @@ struct bcma_device; ++ struct bcma_drv_mips { ++ struct bcma_device *core; ++ u8 setup_done:1; ++- unsigned int assigned_irqs; +++ u8 early_setup_done:1; ++ }; ++ ++ #ifdef CONFIG_BCMA_DRIVER_MIPS ++ extern void bcma_core_mips_init(struct bcma_drv_mips *mcore); +++extern void bcma_core_mips_early_init(struct bcma_drv_mips *mcore); +++ +++extern unsigned int bcma_core_irq(struct bcma_device *core); ++ #else ++ static inline void bcma_core_mips_init(struct bcma_drv_mips *mcore) { } +++static inline void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) { } +++ +++static inline unsigned int bcma_core_irq(struct bcma_device *core) +++{ +++ return 0; +++} ++ #endif ++ ++ extern u32 bcma_cpu_clock(struct bcma_drv_mips *mcore); ++ ++-extern unsigned int bcma_core_mips_irq(struct bcma_device *dev); ++- ++ #endif /* LINUX_BCMA_DRIVER_MIPS_H_ */ + --- a/include/linux/bcma/bcma_driver_pci.h + +++ b/include/linux/bcma/bcma_driver_pci.h + @@ -53,11 +53,47 @@ struct pci_dev; +@@ -3174,7 +5029,7 @@ + + /* SBtoPCIx */ + #define BCMA_CORE_PCI_SBTOPCI_MEM 0x00000000 +-@@ -72,20 +108,118 @@ struct pci_dev; ++@@ -72,20 +108,120 @@ struct pci_dev; + #define BCMA_CORE_PCI_SBTOPCI_RC_READL 0x00000010 /* Memory read line */ + #define BCMA_CORE_PCI_SBTOPCI_RC_READM 0x00000020 /* Memory read multiple */ + +@@ -3249,6 +5104,8 @@ + +#define BCMA_CORE_PCI_CFG_FUN_MASK 7 /* Function mask */ + +#define BCMA_CORE_PCI_CFG_OFF_MASK 0xfff /* Register mask */ + + +++#define BCMA_CORE_PCI_CFG_DEVCTRL 0xd8 +++ + +/* PCIE Root Capability Register bits (Host mode only) */ + +#define BCMA_CORE_PCI_RC_CRS_VISIBILITY 0x0001 + + +@@ -3296,7 +5153,29 @@ + #endif /* LINUX_BCMA_DRIVER_PCI_H_ */ + --- a/include/linux/bcma/bcma_regs.h + +++ b/include/linux/bcma/bcma_regs.h +-@@ -56,4 +56,31 @@ ++@@ -11,11 +11,13 @@ ++ #define BCMA_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */ ++ #define BCMA_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */ ++ #define BCMA_CLKCTLST_EXTRESREQ 0x00000700 /* Mask of external resource requests */ +++#define BCMA_CLKCTLST_EXTRESREQ_SHIFT 8 ++ #define BCMA_CLKCTLST_HAVEALP 0x00010000 /* ALP available */ ++ #define BCMA_CLKCTLST_HAVEHT 0x00020000 /* HT available */ ++ #define BCMA_CLKCTLST_BP_ON_ALP 0x00040000 /* RO: running on ALP clock */ ++ #define BCMA_CLKCTLST_BP_ON_HT 0x00080000 /* RO: running on HT clock */ ++ #define BCMA_CLKCTLST_EXTRESST 0x07000000 /* Mask of external resource status */ +++#define BCMA_CLKCTLST_EXTRESST_SHIFT 24 ++ /* Is there any BCM4328 on BCMA bus? */ ++ #define BCMA_CLKCTLST_4328A0_HAVEHT 0x00010000 /* 4328a0 has reversed bits */ ++ #define BCMA_CLKCTLST_4328A0_HAVEALP 0x00020000 /* 4328a0 has reversed bits */ ++@@ -35,6 +37,7 @@ ++ #define BCMA_IOST_BIST_DONE 0x8000 ++ #define BCMA_RESET_CTL 0x0800 ++ #define BCMA_RESET_CTL_RESET 0x0001 +++#define BCMA_RESET_ST 0x0804 ++ ++ /* BCMA PCI config space registers. */ ++ #define BCMA_PCI_PMCSR 0x44 ++@@ -56,4 +59,31 @@ + #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 */ + +@@ -3328,3 +5207,25 @@ + + */ + + + #endif /* LINUX_BCMA_REGS_H_ */ ++--- a/drivers/net/wireless/b43/main.c +++++ b/drivers/net/wireless/b43/main.c ++@@ -4618,7 +4618,7 @@ static int b43_wireless_core_init(struct ++ switch (dev->dev->bus_type) { ++ #ifdef CONFIG_B43_BCMA ++ case B43_BUS_BCMA: ++- bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci, +++ bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci[0], ++ dev->dev->bdev, true); ++ break; ++ #endif ++--- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c +++++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c ++@@ -533,7 +533,7 @@ ai_buscore_setup(struct si_info *sii, st ++ ++ /* fixup necessary chip/core configurations */ ++ if (!sii->pch) { ++- sii->pch = pcicore_init(&sii->pub, sii->icbus->drv_pci.core); +++ sii->pch = pcicore_init(&sii->pub, sii->icbus->drv_pci[0].core); ++ if (sii->pch == NULL) ++ return false; ++ } diff --git a/build_patches/linux/ar71xx/patches-3.3/480-ar913x_wmac_external_reset.patch b/build_patches/linux/ar71xx/patches-3.3/480-ar913x_wmac_external_reset.patch deleted file mode 100644 index 376652a..0000000 --- a/build_patches/linux/ar71xx/patches-3.3/480-ar913x_wmac_external_reset.patch +++ /dev/null @@ -1,31 +0,0 @@ ---- a/arch/mips/ath79/dev-wmac.c -+++ b/arch/mips/ath79/dev-wmac.c -@@ -44,7 +44,7 @@ static struct platform_device ath79_wmac - }, - }; - --static void __init ar913x_wmac_setup(void) -+static int ar913x_wmac_reset(void) - { - /* reset the WMAC */ - ath79_device_reset_set(AR913X_RESET_AMBA2WMAC); -@@ -53,10 +53,19 @@ static void __init ar913x_wmac_setup(voi - ath79_device_reset_clear(AR913X_RESET_AMBA2WMAC); - mdelay(10); - -+ return 0; -+} -+ -+static void __init ar913x_wmac_setup(void) -+{ -+ ar913x_wmac_reset(); -+ - ath79_wmac_resources[0].start = AR913X_WMAC_BASE; - ath79_wmac_resources[0].end = AR913X_WMAC_BASE + AR913X_WMAC_SIZE - 1; - ath79_wmac_resources[1].start = ATH79_CPU_IRQ_IP2; - ath79_wmac_resources[1].end = ATH79_CPU_IRQ_IP2; -+ -+ ath79_wmac_data.external_reset = ar913x_wmac_reset; - } - - diff --git a/build_patches/linux/ar71xx/patches-3.3/501-MIPS-ath79-add-mac-argument-to-ath79_register_wmac.patch b/build_patches/linux/ar71xx/patches-3.3/501-MIPS-ath79-add-mac-argument-to-ath79_register_wmac.patch deleted file mode 100644 index d22b73a..0000000 --- a/build_patches/linux/ar71xx/patches-3.3/501-MIPS-ath79-add-mac-argument-to-ath79_register_wmac.patch +++ /dev/null @@ -1,81 +0,0 @@ ---- a/arch/mips/ath79/dev-wmac.c -+++ b/arch/mips/ath79/dev-wmac.c -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -22,6 +23,7 @@ - #include - #include "dev-wmac.h" - -+static u8 ath79_wmac_mac[ETH_ALEN]; - static struct ath9k_platform_data ath79_wmac_data; - - static struct resource ath79_wmac_resources[] = { -@@ -143,7 +145,7 @@ static void qca955x_wmac_setup(void) - ath79_wmac_data.is_clk_25mhz = true; - } - --void __init ath79_register_wmac(u8 *cal_data) -+void __init ath79_register_wmac(u8 *cal_data, u8 *mac_addr) - { - if (soc_is_ar913x()) - ar913x_wmac_setup(); -@@ -160,5 +162,10 @@ void __init ath79_register_wmac(u8 *cal_ - memcpy(ath79_wmac_data.eeprom_data, cal_data, - sizeof(ath79_wmac_data.eeprom_data)); - -+ if (mac_addr) { -+ memcpy(ath79_wmac_mac, mac_addr, sizeof(ath79_wmac_mac)); -+ ath79_wmac_data.macaddr = ath79_wmac_mac; -+ } -+ - platform_device_register(&ath79_wmac_device); - } ---- a/arch/mips/ath79/dev-wmac.h -+++ b/arch/mips/ath79/dev-wmac.h -@@ -12,6 +12,6 @@ - #ifndef _ATH79_DEV_WMAC_H - #define _ATH79_DEV_WMAC_H - --void ath79_register_wmac(u8 *cal_data); -+void ath79_register_wmac(u8 *cal_data, u8 *mac_addr); - - #endif /* _ATH79_DEV_WMAC_H */ ---- a/arch/mips/ath79/mach-ap81.c -+++ b/arch/mips/ath79/mach-ap81.c -@@ -98,7 +98,7 @@ static void __init ap81_setup(void) - ap81_gpio_keys); - ath79_register_spi(&ap81_spi_data, ap81_spi_info, - ARRAY_SIZE(ap81_spi_info)); -- ath79_register_wmac(cal_data); -+ ath79_register_wmac(cal_data, NULL); - ath79_register_usb(); - } - ---- a/arch/mips/ath79/mach-db120.c -+++ b/arch/mips/ath79/mach-db120.c -@@ -134,7 +134,7 @@ static void __init db120_setup(void) - ath79_register_spi(&db120_spi_data, db120_spi_info, - ARRAY_SIZE(db120_spi_info)); - ath79_register_usb(); -- ath79_register_wmac(art + DB120_WMAC_CALDATA_OFFSET); -+ ath79_register_wmac(art + DB120_WMAC_CALDATA_OFFSET, NULL); - db120_pci_init(art + DB120_PCIE_CALDATA_OFFSET); - } - ---- a/arch/mips/ath79/mach-ap121.c -+++ b/arch/mips/ath79/mach-ap121.c -@@ -91,7 +91,7 @@ static void __init ap121_setup(void) - ath79_register_spi(&ap121_spi_data, ap121_spi_info, - ARRAY_SIZE(ap121_spi_info)); - ath79_register_usb(); -- ath79_register_wmac(cal_data); -+ ath79_register_wmac(cal_data, NULL); - } - - MIPS_MACHINE(ATH79_MACH_AP121, "AP121", "Atheros AP121 reference board", diff --git a/build_patches/linux/ar71xx/patches-3.3/505-MIPS-ath79-add-ath79_gpio_function_select.patch b/build_patches/linux/ar71xx/patches-3.3/505-MIPS-ath79-add-ath79_gpio_function_select.patch deleted file mode 100644 index 08f4a1e..0000000 --- a/build_patches/linux/ar71xx/patches-3.3/505-MIPS-ath79-add-ath79_gpio_function_select.patch +++ /dev/null @@ -1,47 +0,0 @@ ---- a/arch/mips/ath79/common.h -+++ b/arch/mips/ath79/common.h -@@ -26,6 +26,7 @@ void ath79_ddr_wb_flush(unsigned int reg - void ath79_gpio_function_enable(u32 mask); - void ath79_gpio_function_disable(u32 mask); - void ath79_gpio_function_setup(u32 set, u32 clear); -+void ath79_gpio_output_select(unsigned gpio, u8 val); - void ath79_gpio_init(void); - - #endif /* __ATH79_COMMON_H */ ---- a/arch/mips/ath79/gpio.c -+++ b/arch/mips/ath79/gpio.c -@@ -198,6 +198,34 @@ void ath79_gpio_function_setup(u32 set, - spin_unlock_irqrestore(&ath79_gpio_lock, flags); - } - -+void __init ath79_gpio_output_select(unsigned gpio, u8 val) -+{ -+ void __iomem *base = ath79_gpio_base; -+ unsigned long flags; -+ unsigned int reg; -+ u32 t, s; -+ -+ BUG_ON(!soc_is_ar934x()); -+ -+ if (gpio >= AR934X_GPIO_COUNT) -+ return; -+ -+ reg = AR934X_GPIO_REG_OUT_FUNC0 + 4 * (gpio / 4); -+ s = 8 * (gpio % 4); -+ -+ spin_lock_irqsave(&ath79_gpio_lock, flags); -+ -+ t = __raw_readl(base + reg); -+ t &= ~(0xff << s); -+ t |= val << s; -+ __raw_writel(t, base + reg); -+ -+ /* flush write */ -+ (void) __raw_readl(base + reg); -+ -+ spin_unlock_irqrestore(&ath79_gpio_lock, flags); -+} -+ - void __init ath79_gpio_init(void) - { - int err; diff --git a/build_patches/linux/ar71xx/patches-3.3/521-MIPS-ath79-enable-UART-for-early_serial.patch b/build_patches/linux/ar71xx/patches-3.3/521-MIPS-ath79-enable-UART-for-early_serial.patch deleted file mode 100644 index 2ee025b..0000000 --- a/build_patches/linux/ar71xx/patches-3.3/521-MIPS-ath79-enable-UART-for-early_serial.patch +++ /dev/null @@ -1,61 +0,0 @@ ---- a/arch/mips/ath79/early_printk.c -+++ b/arch/mips/ath79/early_printk.c -@@ -56,6 +56,46 @@ static void prom_putchar_dummy(unsigned - /* nothing to do */ - } - -+static void prom_enable_uart(u32 id) -+{ -+ void __iomem *gpio_base; -+ u32 uart_en; -+ u32 t; -+ -+ switch (id) { -+ case REV_ID_MAJOR_AR71XX: -+ uart_en = AR71XX_GPIO_FUNC_UART_EN; -+ break; -+ -+ case REV_ID_MAJOR_AR7240: -+ case REV_ID_MAJOR_AR7241: -+ case REV_ID_MAJOR_AR7242: -+ uart_en = AR724X_GPIO_FUNC_UART_EN; -+ break; -+ -+ case REV_ID_MAJOR_AR913X: -+ uart_en = AR913X_GPIO_FUNC_UART_EN; -+ break; -+ -+ case REV_ID_MAJOR_AR9330: -+ case REV_ID_MAJOR_AR9331: -+ uart_en = AR933X_GPIO_FUNC_UART_EN; -+ break; -+ -+ case REV_ID_MAJOR_AR9341: -+ case REV_ID_MAJOR_AR9342: -+ case REV_ID_MAJOR_AR9344: -+ /* TODO */ -+ default: -+ return; -+ } -+ -+ gpio_base = (void __iomem *)(KSEG1ADDR(AR71XX_GPIO_BASE)); -+ t = __raw_readl(gpio_base + AR71XX_GPIO_REG_FUNC); -+ t |= uart_en; -+ __raw_writel(t, gpio_base + AR71XX_GPIO_REG_FUNC); -+} -+ - static void prom_putchar_init(void) - { - void __iomem *base; -@@ -85,8 +125,10 @@ static void prom_putchar_init(void) - - default: - _prom_putchar = prom_putchar_dummy; -- break; -+ return; - } -+ -+ prom_enable_uart(id); - } - - void prom_putchar(unsigned char ch) diff --git a/build_patches/linux/ar71xx/patches-3.3/606-MIPS-ath79-pb44-fixes.patch b/build_patches/linux/ar71xx/patches-3.3/606-MIPS-ath79-pb44-fixes.patch deleted file mode 100644 index b38b461..0000000 --- a/build_patches/linux/ar71xx/patches-3.3/606-MIPS-ath79-pb44-fixes.patch +++ /dev/null @@ -1,153 +0,0 @@ ---- a/arch/mips/ath79/mach-pb44.c -+++ b/arch/mips/ath79/mach-pb44.c -@@ -8,23 +8,48 @@ - * by the Free Software Foundation. - */ - -+#include - #include - #include - #include - #include - #include -+#include -+#include -+#include - --#include "machtypes.h" -+#include -+#include -+ -+#include "dev-eth.h" - #include "dev-gpio-buttons.h" - #include "dev-leds-gpio.h" - #include "dev-spi.h" - #include "dev-usb.h" -+#include "machtypes.h" - #include "pci.h" - - #define PB44_GPIO_I2C_SCL 0 - #define PB44_GPIO_I2C_SDA 1 - -+#define PB44_PCF8757_VSC7395_CS 0 -+#define PB44_PCF8757_STEREO_CS 1 -+#define PB44_PCF8757_SLIC_CS0 2 -+#define PB44_PCF8757_SLIC_TEST 3 -+#define PB44_PCF8757_SLIC_INT0 4 -+#define PB44_PCF8757_SLIC_INT1 5 -+#define PB44_PCF8757_SW_RESET 6 -+#define PB44_PCF8757_SW_JUMP 8 -+#define PB44_PCF8757_LED_JUMP1 9 -+#define PB44_PCF8757_LED_JUMP2 10 -+#define PB44_PCF8757_TP24 11 -+#define PB44_PCF8757_TP25 12 -+#define PB44_PCF8757_TP26 13 -+#define PB44_PCF8757_TP27 14 -+#define PB44_PCF8757_TP28 15 -+ - #define PB44_GPIO_EXP_BASE 16 -+#define PB44_GPIO_VSC7395_CS (PB44_GPIO_EXP_BASE + PB44_PCF8757_VSC7395_CS) - #define PB44_GPIO_SW_RESET (PB44_GPIO_EXP_BASE + 6) - #define PB44_GPIO_SW_JUMP (PB44_GPIO_EXP_BASE + 8) - #define PB44_GPIO_LED_JUMP1 (PB44_GPIO_EXP_BASE + 9) -@@ -92,21 +117,66 @@ static struct ath79_spi_controller_data - .cs_line = 0, - }; - -+static struct ath79_spi_controller_data pb44_spi1_data = { -+ .cs_type = ATH79_SPI_CS_TYPE_GPIO, -+ .cs_line = PB44_GPIO_VSC7395_CS, -+}; -+ -+static void pb44_vsc7395_reset(void) -+{ -+ ath79_device_reset_set(AR71XX_RESET_GE1_PHY); -+ udelay(10); -+ ath79_device_reset_clear(AR71XX_RESET_GE1_PHY); -+ mdelay(50); -+} -+ -+static struct vsc7385_platform_data pb44_vsc7395_data = { -+ .reset = pb44_vsc7395_reset, -+ .ucode_name = "vsc7395_ucode_pb44.bin", -+ .mac_cfg = { -+ .tx_ipg = 6, -+ .bit2 = 1, -+ .clk_sel = 0, -+ }, -+}; -+ -+static const char *pb44_part_probes[] = { -+ "RedBoot", -+ NULL, -+}; -+ -+static struct flash_platform_data pb44_flash_data = { -+ .part_probes = pb44_part_probes, -+}; -+ - static struct spi_board_info pb44_spi_info[] = { - { - .bus_num = 0, - .chip_select = 0, - .max_speed_hz = 25000000, - .modalias = "m25p64", -+ .platform_data = &pb44_flash_data, - .controller_data = &pb44_spi0_data, - }, -+ { -+ .bus_num = 0, -+ .chip_select = 1, -+ .max_speed_hz = 25000000, -+ .modalias = "spi-vsc7385", -+ .platform_data = &pb44_vsc7395_data, -+ .controller_data = &pb44_spi1_data, -+ } - }; - - static struct ath79_spi_platform_data pb44_spi_data = { - .bus_num = 0, -- .num_chipselect = 1, -+ .num_chipselect = 2, - }; - -+#define PB44_WAN_PHYMASK BIT(0) -+#define PB44_LAN_PHYMASK 0 -+#define PB44_MDIO_PHYMASK (PB44_LAN_PHYMASK | PB44_WAN_PHYMASK) -+ - static void __init pb44_init(void) - { - i2c_register_board_info(0, pb44_i2c_board_info, -@@ -122,6 +192,22 @@ static void __init pb44_init(void) - ARRAY_SIZE(pb44_spi_info)); - ath79_register_usb(); - ath79_register_pci(); -+ -+ ath79_register_mdio(0, ~PB44_MDIO_PHYMASK); -+ -+ ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0); -+ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; -+ ath79_eth0_data.phy_mask = PB44_WAN_PHYMASK; -+ -+ ath79_register_eth(0); -+ -+ ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 1); -+ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; -+ ath79_eth1_data.speed = SPEED_1000; -+ ath79_eth1_data.duplex = DUPLEX_FULL; -+ ath79_eth1_pll_data.pll_1000 = 0x110000; -+ -+ ath79_register_eth(1); - } - - MIPS_MACHINE(ATH79_MACH_PB44, "PB44", "Atheros PB44 reference board", ---- a/arch/mips/ath79/Kconfig -+++ b/arch/mips/ath79/Kconfig -@@ -58,6 +58,7 @@ config ATH79_MACH_DB120 - config ATH79_MACH_PB44 - bool "Atheros PB44 reference board" - select SOC_AR71XX -+ select ATH79_DEV_ETH - select ATH79_DEV_GPIO_BUTTONS - select ATH79_DEV_LEDS_GPIO - select ATH79_DEV_SPI diff --git a/build_patches/linux/ar71xx/patches-3.3/620-MIPS-ath79-OTP-support.patch b/build_patches/linux/ar71xx/patches-3.3/620-MIPS-ath79-OTP-support.patch deleted file mode 100644 index f52961a..0000000 --- a/build_patches/linux/ar71xx/patches-3.3/620-MIPS-ath79-OTP-support.patch +++ /dev/null @@ -1,166 +0,0 @@ ---- a/arch/mips/ath79/dev-wmac.c -+++ b/arch/mips/ath79/dev-wmac.c -@@ -148,6 +148,137 @@ static void qca955x_wmac_setup(void) - ath79_wmac_data.is_clk_25mhz = true; - } - -+static bool __init -+ar93xx_wmac_otp_read_word(void __iomem *base, int addr, u32 *data) -+{ -+ int timeout = 1000; -+ u32 val; -+ -+ __raw_readl(base + AR9300_OTP_BASE + (4 * addr)); -+ while (timeout--) { -+ val = __raw_readl(base + AR9300_OTP_STATUS); -+ if ((val & AR9300_OTP_STATUS_TYPE) == AR9300_OTP_STATUS_VALID) -+ break; -+ -+ udelay(10); -+ } -+ -+ if (!timeout) -+ return false; -+ -+ *data = __raw_readl(base + AR9300_OTP_READ_DATA); -+ return true; -+} -+ -+static bool __init -+ar93xx_wmac_otp_read(void __iomem *base, int addr, u8 *dest, int len) -+{ -+ u32 data; -+ int i; -+ -+ for (i = 0; i < len; i++) { -+ int offset = 8 * ((addr - i) % 4); -+ -+ if (!ar93xx_wmac_otp_read_word(base, (addr - i) / 4, &data)) -+ return false; -+ -+ dest[i] = (data >> offset) & 0xff; -+ } -+ -+ return true; -+} -+ -+static bool __init -+ar93xx_wmac_otp_uncompress(void __iomem *base, int addr, int len, u8 *dest, -+ int dest_start, int dest_len) -+{ -+ int dest_bytes = 0; -+ int offset = 0; -+ int end = addr - len; -+ u8 hdr[2]; -+ -+ while (addr > end) { -+ if (!ar93xx_wmac_otp_read(base, addr, hdr, 2)) -+ return false; -+ -+ addr -= 2; -+ offset += hdr[0]; -+ -+ if (offset <= dest_start + dest_len && -+ offset + len >= dest_start) { -+ int data_offset = 0; -+ int dest_offset = 0; -+ int copy_len; -+ -+ if (offset < dest_start) -+ data_offset = dest_start - offset; -+ else -+ dest_offset = offset - dest_start; -+ -+ copy_len = len - data_offset; -+ if (copy_len > dest_len - dest_offset) -+ copy_len = dest_len - dest_offset; -+ -+ ar93xx_wmac_otp_read(base, addr - data_offset, -+ dest + dest_offset, -+ copy_len); -+ -+ dest_bytes += copy_len; -+ } -+ addr -= hdr[1]; -+ } -+ return !!dest_bytes; -+} -+ -+bool __init ar93xx_wmac_read_mac_address(u8 *dest) -+{ -+ void __iomem *base; -+ bool ret = false; -+ int addr = 0x1ff; -+ unsigned int len; -+ u32 hdr_u32; -+ u8 *hdr = (u8 *) &hdr_u32; -+ u8 mac[6] = { 0x00, 0x02, 0x03, 0x04, 0x05, 0x06 }; -+ int mac_start = 2, mac_end = 8; -+ -+ BUG_ON(!soc_is_ar933x() && !soc_is_ar934x()); -+ base = ioremap_nocache(AR933X_WMAC_BASE, AR933X_WMAC_SIZE); -+ while (addr > sizeof(hdr)) { -+ if (!ar93xx_wmac_otp_read(base, addr, hdr, sizeof(hdr))) -+ break; -+ -+ if (hdr_u32 == 0 || hdr_u32 == ~0) -+ break; -+ -+ len = (hdr[1] << 4) | (hdr[2] >> 4); -+ addr -= 4; -+ -+ switch (hdr[0] >> 5) { -+ case 0: -+ if (len < mac_end) -+ break; -+ -+ ar93xx_wmac_otp_read(base, addr - mac_start, mac, 6); -+ ret = true; -+ break; -+ case 3: -+ ret |= ar93xx_wmac_otp_uncompress(base, addr, len, mac, -+ mac_start, 6); -+ break; -+ default: -+ break; -+ } -+ -+ addr -= len + 2; -+ } -+ -+ iounmap(base); -+ if (ret) -+ memcpy(dest, mac, 6); -+ -+ return ret; -+} -+ - void __init ath79_register_wmac(u8 *cal_data, u8 *mac_addr) - { - if (soc_is_ar913x()) ---- a/arch/mips/ath79/dev-wmac.h -+++ b/arch/mips/ath79/dev-wmac.h -@@ -13,5 +13,6 @@ - #define _ATH79_DEV_WMAC_H - - void ath79_register_wmac(u8 *cal_data, u8 *mac_addr); -+bool ar93xx_wmac_read_mac_address(u8 *dest); - - #endif /* _ATH79_DEV_WMAC_H */ ---- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h -+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h -@@ -129,6 +129,14 @@ - #define QCA955X_NFC_BASE 0x1b000200 - #define QCA955X_NFC_SIZE 0xb8 - -+#define AR9300_OTP_BASE 0x14000 -+#define AR9300_OTP_STATUS 0x15f18 -+#define AR9300_OTP_STATUS_TYPE 0x7 -+#define AR9300_OTP_STATUS_VALID 0x4 -+#define AR9300_OTP_STATUS_ACCESS_BUSY 0x2 -+#define AR9300_OTP_STATUS_SM_BUSY 0x1 -+#define AR9300_OTP_READ_DATA 0x15f1c -+ - /* - * DDR_CTRL block - */ diff --git a/build_patches/linux/ar71xx/patches-3.3/621-MIPS-ath79-add-ath79_wmac_disable_25ghz-helpers.patch b/build_patches/linux/ar71xx/patches-3.3/621-MIPS-ath79-add-ath79_wmac_disable_25ghz-helpers.patch deleted file mode 100644 index 957ccb6..0000000 --- a/build_patches/linux/ar71xx/patches-3.3/621-MIPS-ath79-add-ath79_wmac_disable_25ghz-helpers.patch +++ /dev/null @@ -1,31 +0,0 @@ ---- a/arch/mips/ath79/dev-wmac.c -+++ b/arch/mips/ath79/dev-wmac.c -@@ -279,6 +279,16 @@ bool __init ar93xx_wmac_read_mac_address - return ret; - } - -+void __init ath79_wmac_disable_2ghz(void) -+{ -+ ath79_wmac_data.disable_2ghz = true; -+} -+ -+void __init ath79_wmac_disable_5ghz(void) -+{ -+ ath79_wmac_data.disable_5ghz = true; -+} -+ - void __init ath79_register_wmac(u8 *cal_data, u8 *mac_addr) - { - if (soc_is_ar913x()) ---- a/arch/mips/ath79/dev-wmac.h -+++ b/arch/mips/ath79/dev-wmac.h -@@ -13,6 +13,9 @@ - #define _ATH79_DEV_WMAC_H - - void ath79_register_wmac(u8 *cal_data, u8 *mac_addr); -+void ath79_wmac_disable_2ghz(void); -+void ath79_wmac_disable_5ghz(void); -+ - bool ar93xx_wmac_read_mac_address(u8 *dest); - - #endif /* _ATH79_DEV_WMAC_H */ diff --git a/build_patches/linux/ar71xx/patches-3.3/650-MIPS-ath79-fix-ar933x-reset.patch b/build_patches/linux/ar71xx/patches-3.3/650-MIPS-ath79-fix-ar933x-reset.patch deleted file mode 100644 index d288f08..0000000 --- a/build_patches/linux/ar71xx/patches-3.3/650-MIPS-ath79-fix-ar933x-reset.patch +++ /dev/null @@ -1,31 +0,0 @@ ---- a/arch/mips/ath79/dev-wmac.c -+++ b/arch/mips/ath79/dev-wmac.c -@@ -76,10 +76,27 @@ static void __init ar913x_wmac_setup(voi - - static int ar933x_wmac_reset(void) - { -+ int retries = 20; -+ - ath79_device_reset_set(AR933X_RESET_WMAC); - ath79_device_reset_clear(AR933X_RESET_WMAC); - -- return 0; -+ while (1) { -+ u32 bootstrap; -+ -+ bootstrap = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); -+ if ((bootstrap & AR933X_BOOTSTRAP_EEPBUSY) == 0) -+ return 0; -+ -+ if (retries-- == 0) -+ break; -+ -+ udelay(10000); -+ retries++; -+ } -+ -+ pr_err("ar933x: WMAC reset timed out"); -+ return -ETIMEDOUT; - } - - static int ar933x_r1_get_wmac_revision(void) diff --git a/buildscript b/buildscript index 28856c0..8b68198 100755 --- a/buildscript +++ b/buildscript @@ -2,18 +2,72 @@ builddir=./build -prepare() { - test -d $builddir || mkdir $builddir +OPENWRTREV=35298 +OPENWRTURL=svn://svn.openwrt.org/openwrt/branches/attitude_adjustment +PACKAGEREV=${OPENWRTREV} +PACKAGEURL=svn://svn.openwrt.org/openwrt/packages + +get_source() { + cd src #Get the OpenWrt Core Source for Firmware - svn checkout -r 35298 svn://svn.openwrt.org/openwrt/branches/attitude_adjustment/ $target + if [ -d openwrt ]; then + url=$(svn info openwrt | awk '/^URL/ { print $2 }') + if [ "$url" = "$OPENWRTURL" ]; then + rev=$(svn info openwrt | awk '/^Revision:/ { print $2 }') + if [ "$rev" -ne "$OPENWRTREV" ]; then + svn update -r $OPENWRTREV openwrt + fi + else + /bin/rm -rf openwrt + svn checkout -r $OPENWRTREV $OPENWRTURL openwrt + fi + else + svn checkout -r $OPENWRTREV $OPENWRTURL openwrt + fi + + test -d packages || mkdir packages + cd packages + + if [ -d openwrt ]; then + url=$(svn info openwrt | awk '/^URL/ { print $2 }') + if [ "$url" = "$PACKAGEURL" ]; then + rev=$(svn info openwrt | awk '/^Revision:/ { print $2 }') + if [ "$rev" -ne "$PACKAGEREV" ]; then + svn update -r $PACKAGEREV openwrt + fi + else + /bin/rm -rf openwrt + svn checkout -r $PACKAGEREV $PACKAGEURL openwrt + fi + else + svn checkout -r $PACKAGEREV $PACKAGEURL openwrt + fi + + test -d routing || git clone https://github.com/openwrt-routing/packages.git routing + git --git-dir=routing/.git --work-tree=routing/ checkout 072ba90ce4b126e84d3e1734ba8e9d4beab48f03 + + test -d fastd || git clone git://git.metameute.de/lff/pkg_fastd fastd + git --git-dir=fastd/.git --work-tree=fastd/ checkout v10 + + cd .. # packages + cd .. # src +} + +prepare() { + get_source + + test -d $builddir || mkdir $builddir + + /bin/rm -rf $target + svn export src/openwrt $target + + #apply own feeds.conf + sed -e"s|PATH|$(pwd)/src/packages|g" ./build_patches/feeds.conf > $target/feeds.conf # overwrite feeds (from r38172) to support commit ids in feeds.conf cp ./build_patches/openwrt/feeds $target/scripts/feeds - #apply own feeds.conf - cp ./build_patches/feeds.conf $target/feeds.conf - test -d $target/feeds && /bin/rm -rf $target/feeds $target/scripts/feeds update @@ -21,7 +75,7 @@ prepare() { $target/scripts/feeds install -p packagesol nodewatcher $target/scripts/feeds install -p fastd fastd libuecc $target/scripts/feeds install -p routing alfred kmod-batman-adv kmod-batgat - $target/scripts/feeds install -p packages bridge ethtool gpioctl-sysfs horst libugpio mii-tool wavemon kmod-gpiotoggling + $target/scripts/feeds install -p openwrt bridge ethtool gpioctl-sysfs horst libugpio mii-tool wavemon kmod-gpiotoggling #fix for building toolchain on texinfo>=5 cp -a build_patches/toolchain $target @@ -41,17 +95,17 @@ prepare() { mv $target/package/aa-mac80211/mac80211 $target/package/mac80211 mv $target/package/aa-mac80211/hostapd $target/package/hostapd - svn up -r 37378 $target/target/linux/generic/files/include/linux/ath9k_platform.h - #backport the latests kernel fixes (needed for newer batman) - svn up -r 37768 $target/target/linux/generic/patches-3.3 - + #svn diff -r 35298:37768 svn://svn.openwrt.org/openwrt/branches/attitude_adjustment/target/linux/generic > build_patches/kernel_37768.patch + cat build_patches/kernel_generic_37768.patch | patch -p0 -d $target/target/linux/generic + #backport kernelpatches from openwrt r36664 - cp build_patches/linux/ar71xx/patches-3.3/* $target/target/linux/ar71xx/patches-3.3 + #svn diff -r 35298:36664 svn://svn.openwrt.org/openwrt/branches/attitude_adjustment/target/linux/ar71xx > build_patches/kernel_ar71xx_36664.patch + cat build_patches/kernel_ar71xx_36664.patch | patch -p0 -d $target/target/linux/ar71xx #saves ~200MB for each build - test -d ./dl || mkdir ./dl - ln -s ../../dl $target/dl + test -d ./src/dl || mkdir ./src/dl + ln -s ../../src/dl $target/dl board_prepare } @@ -78,8 +132,8 @@ prebuild() { echo "FIRMWARE_VERSION=\"$version\"" > $target/files/etc/firmware_release echo "RELEASE_DATE=\"build date: "`date`"\"" >> $target/files/etc/firmware_release echo "FIRMWARE_REVISION=\"build date: "`date`"\"" >> $target/files/etc/firmware_release - echo "OPENWRT_CORE_REVISION=\""`svn info $target |grep Revision: |cut -c11-`"\"" >> $target/files/etc/firmware_release - echo "OPENWRT_FEEDS_PACKAGES_REVISION=\""`svn info $target/feeds/packages |grep Revision: |cut -c11-`"\"" >> $target/files/etc/firmware_release + echo "OPENWRT_CORE_REVISION=\""${OPENWRTREV}"\"" >> $target/files/etc/firmware_release + echo "OPENWRT_FEEDS_PACKAGES_REVISION=\""${PACKAGEREV}"\"" >> $target/files/etc/firmware_release } build() { diff --git a/src/packages/ffol/ath9k-watchdog/Makefile b/src/packages/ffol/ath9k-watchdog/Makefile new file mode 100755 index 0000000..985b253 --- /dev/null +++ b/src/packages/ffol/ath9k-watchdog/Makefile @@ -0,0 +1,47 @@ +# +# Copyright (C) 2012 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=ath9k-watchdog +PKG_VERSION:=1 +PKG_RELEASE:=1 + + +include $(INCLUDE_DIR)/package.mk + + +define Package/ath9k-watchdog + SECTION:=utils + CATEGORY:=Utilities + TITLE:=Watchdog for ath9k-outages +endef + +define Package/ath9k-watchdog/description + If pattern "ResetWLAN" is seen in the logs, wifi reset is executed +endef + + +define Package/ath9k-watchdog/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) files/ath9k-watchdog $(1)/usr/sbin/ + $(INSTALL_BIN) files/ath9k-watchdog-pm $(1)/usr/sbin/ + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_DIR) $(1)/etc/init.d/ + $(INSTALL_BIN) files/ath9k-watchdog.init $(1)/etc/init.d/ath9k-watchdog +endef + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) +endef + +define Build/Configure +endef + +define Build/Compile +endef +$(eval $(call BuildPackage,ath9k-watchdog)) diff --git a/src/packages/ffol/ath9k-watchdog/files/ath9k-watchdog b/src/packages/ffol/ath9k-watchdog/files/ath9k-watchdog new file mode 100755 index 0000000..b3c5a4d --- /dev/null +++ b/src/packages/ffol/ath9k-watchdog/files/ath9k-watchdog @@ -0,0 +1,31 @@ +#!/bin/sh +mkdir -p /usr/lib/ath9k-watchdog + +logread -f | while read line +do + case "$line" in + *"Could not stop RX"*) + hostname=$(cat /proc/sys/kernel/hostname) + + if [ "$hostname" == "OpenWrt" ]; then + hostname="" + fi + + if [ "$hostname" == "" ]; then + hostname=$(awk '{ if (mac) next; mac=toupper($1); gsub(":", "", mac); print mac }' /sys/class/net/br-mesh/address /sys/class/net/eth0/address /sys/class/net/ath0/address 2>/dev/null) + fi + + # Perform post-mortem dump + tstmp=$(/bin/date +%s) + echo -n "data[hostname]=${hostname}&data[tstmp]=${tstmp}" > /tmp/$tstmp + + # Move into upload directory + mv /tmp/$tstmp /usr/lib/ath9k-watchdog + + #Bye + /sbin/reboot + ;; + *) + ;; + esac +done diff --git a/src/packages/ffol/ath9k-watchdog/files/ath9k-watchdog-pm b/src/packages/ffol/ath9k-watchdog/files/ath9k-watchdog-pm new file mode 100755 index 0000000..93dff26 --- /dev/null +++ b/src/packages/ffol/ath9k-watchdog/files/ath9k-watchdog-pm @@ -0,0 +1,25 @@ +#!/bin/sh +# Save log +mkdir -p /usr/lib/ath9k-watchdog +WGETC=$(which wget) + + +# CD to avoid annoying prefixes +cd /usr/lib/ath9k-watchdog + +#Poll directory every 60 secs +while [ 1 = 1 ] +do + if [ "$(ls .)" != "" ] + then + UPLOAD_URL="http://[$(uci get configurator.@api[0].ipv6_address)%$(uci get configurator.@api[0].ipv6_interface)]/api/rest/event/" + for f in $(ls .); do + $WGETC -q $UPLOAD_URL"?api_key=$(uci get configurator.@api[0].api_key)&object=router&object_id="$(uci get configurator.@crawl[0].router_id)"&action=watchdog_ath9k_bug&"$(cat $f) -O - && rm $f + done + # If there are more than 15 files, assume that files cannot be uploaded + # Delete oldest files in order to avoid jffs-overflow + ls -t | sed -e '1,15d' | xargs rm 2> /dev/null + fi + + sleep 60 +done diff --git a/src/packages/ffol/ath9k-watchdog/files/ath9k-watchdog.init b/src/packages/ffol/ath9k-watchdog/files/ath9k-watchdog.init new file mode 100755 index 0000000..4d38386 --- /dev/null +++ b/src/packages/ffol/ath9k-watchdog/files/ath9k-watchdog.init @@ -0,0 +1,28 @@ +#!/bin/sh /etc/rc.common + +START=95 +APP=ath9k-watchdog +POSTM=ath9k-watchdog-pm +PID_FILE=/var/run/$APP.pid +POSTM_PID_FILE=/var/run/$POSTM.pid + +start() { + if [ -f $PID_FILE ]; then + echo "Ath9k-watchdog: Already Running" + else + start-stop-daemon -S -x $APP -p $PID_FILE -m -b + fi + + if [ -f $POSTM_PID_FILE ]; then + echo "ath9k-watchdog-pm: Already Running" + else + start-stop-daemon -S -x $POSTM -p $POSTM_PID_FILE -m -b + fi +} + +stop() { + start-stop-daemon -K -n $APP -p $PID_FILE -s TERM + start-stop-daemon -K -n $POSTM -p $POSTM_PID_FILE -s TERM + rm -rf $PID_FILE + rm -rf $POSTM_PID_FILE +} \ No newline at end of file diff --git a/src/packages/ffol/libwlocate/Makefile b/src/packages/ffol/libwlocate/Makefile new file mode 100644 index 0000000..39e191c --- /dev/null +++ b/src/packages/ffol/libwlocate/Makefile @@ -0,0 +1,51 @@ +# +# Copyright (C) 2006-2010 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=libwlocate +PKG_VERSION:=1.1 +PKG_RELEASE:=1 + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://dev.freifunk-ol.de/packages +PKG_MD5SUM:=5f8be7c6e95b64f24dd8cde4557612a4 + +include $(INCLUDE_DIR)/package.mk + +define Package/libwlocate + SECTION:=libs + CATEGORY:=Libraries + TITLE:=Shared library that can be used for location-based services + URL:=http://sourceforge.net/projects/libwlocate/ + DEPENDS:=+libiw +endef + +define Package/libwlocate/description + libwlocate is a shared library that can be used for location-based services. + It checks for WLAN-networks that are available near to a user and retrieves the + current geographic position out of them. + Thus no GPS is needed for positioning. This WLAN-based geolocation happens + without using any of the commercial services that do the same but track the users + position and data. libwlocate instead bases on the free OpenWLANMap project. +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + $(CP) $(PKG_BUILD_DIR)/libwlocate.h $(1)/usr/include/ + + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/libwlocate.so $(1)/usr/lib/ +endef + +define Package/libwlocate/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/libwlocate.so $(1)/usr/lib/ +endef + +$(eval $(call BuildPackage,libwlocate)) diff --git a/src/packages/ffol/lwtrace/Makefile b/src/packages/ffol/lwtrace/Makefile new file mode 100644 index 0000000..90bd197 --- /dev/null +++ b/src/packages/ffol/lwtrace/Makefile @@ -0,0 +1,48 @@ +# +# Copyright (C) 2006-2010 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=lwtrace +PKG_VERSION:=1.1 +PKG_RELEASE:=1 + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://dev.freifunk-ol.de/packages +PKG_MD5SUM:=bbe4e339daf69efe0b6c325f799c3e0b + +include $(INCLUDE_DIR)/package.mk + +define Package/lwtrace + SECTION:=utilities + CATEGORY:=Utilities + TITLE:=Tool that uses the libwlocate library to get a position wireless + URL:=http://sourceforge.net/projects/libwlocate/ + DEPENDS:=+libwlocate +endef + +define Package/lwtrace/description + libwlocate is a shared library that can be used for location-based services. + It checks for WLAN-networks that are available near to a user and retrieves the + current geographic position out of them. + Thus no GPS is needed for positioning. This WLAN-based geolocation happens + without using any of the commercial services that do the same but track the users + position and data. libwlocate instead bases on the free OpenWLANMap project. +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/bin + $(CP) $(PKG_BUILD_DIR)/lwtrace $(1)/usr/bin/ +endef + +define Package/lwtrace/install + $(INSTALL_DIR) $(1)/usr/bin + $(CP) $(PKG_BUILD_DIR)/lwtrace $(1)/usr/bin/ +endef + +$(eval $(call BuildPackage,lwtrace)) \ No newline at end of file diff --git a/src/packages/ffol/nodewatcher/Makefile b/src/packages/ffol/nodewatcher/Makefile new file mode 100644 index 0000000..a16a368 --- /dev/null +++ b/src/packages/ffol/nodewatcher/Makefile @@ -0,0 +1,40 @@ +# +# Copyright (C) 2006-2010 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=nodewatcher +PKG_VERSION:=2013-02-13 +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=git://freifunk-ol.de/ffol/software/nodewatcher.git +PKG_SOURCE:=$(PKG_NAME).tar.gz +PKG_SOURCE_VERSION:=HEAD +PKG_SOURCE_SUBDIR:=$(PKG_NAME) + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) + +include $(INCLUDE_DIR)/package.mk + +define Package/nodewatcher + SECTION:=utilities + CATEGORY:=Utilities + TITLE:=Freifunk Oldenburg Nodewatcher + URL:=http://freifunk-ol.de + DEPENDS:=+libuci +ip +libiw +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/bin + $(CP) $(PKG_BUILD_DIR)/nodewatcher $(1)/usr/bin/ +endef + +define Package/nodewatcher/install + $(INSTALL_DIR) $(1)/usr/bin + $(CP) $(PKG_BUILD_DIR)/nodewatcher $(1)/usr/bin/ +endef + +$(eval $(call BuildPackage,nodewatcher)) \ No newline at end of file