diff options
author | Hauke Mehrtens <hauke@hauke-m.de> | 2013-07-19 12:02:34 +0000 |
---|---|---|
committer | Hauke Mehrtens <hauke@hauke-m.de> | 2013-07-19 12:02:34 +0000 |
commit | c7f8cb3f4f55d187a56c3166793f906a19805358 (patch) | |
tree | 753e841c3e46b9a8013d384934e3469f79f64684 | |
parent | 75df42e578094fba85c2ddd7ad402e4f24545479 (diff) | |
download | mtk-20170518-c7f8cb3f4f55d187a56c3166793f906a19805358.zip mtk-20170518-c7f8cb3f4f55d187a56c3166793f906a19805358.tar.gz mtk-20170518-c7f8cb3f4f55d187a56c3166793f906a19805358.tar.bz2 |
kernel: update bcma and ssb to version from wireless-testing/master tag master-2013-07-18
This should fix some build problems in b43 with kernel 3.3.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
SVN-Revision: 37432
23 files changed, 9597 insertions, 1026 deletions
diff --git a/target/linux/brcm47xx/patches-3.10/241-bcma-broadcom-2011-sdk-updates.patch b/target/linux/brcm47xx/patches-3.10/241-bcma-broadcom-2011-sdk-updates.patch deleted file mode 100644 index 72b0208..0000000 --- a/target/linux/brcm47xx/patches-3.10/241-bcma-broadcom-2011-sdk-updates.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/drivers/bcma/core.c -+++ b/drivers/bcma/core.c -@@ -43,6 +43,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)); diff --git a/target/linux/brcm47xx/patches-3.10/280-activate_ssb_support_in_usb.patch b/target/linux/brcm47xx/patches-3.10/280-activate_ssb_support_in_usb.patch index c4382ed..aabaf29 100644 --- a/target/linux/brcm47xx/patches-3.10/280-activate_ssb_support_in_usb.patch +++ b/target/linux/brcm47xx/patches-3.10/280-activate_ssb_support_in_usb.patch @@ -5,7 +5,7 @@ This prevents the options from being delete with make kernel_oldconfig. --- a/drivers/bcma/Kconfig +++ b/drivers/bcma/Kconfig -@@ -37,6 +37,7 @@ config BCMA_DRIVER_PCI_HOSTMODE +@@ -38,6 +38,7 @@ config BCMA_DRIVER_PCI_HOSTMODE config BCMA_HOST_SOC bool depends on BCMA_DRIVER_MIPS @@ -18,7 +18,7 @@ This prevents the options from being delete with make kernel_oldconfig. @@ -146,6 +146,7 @@ config SSB_SFLASH config SSB_EMBEDDED bool - depends on SSB_DRIVER_MIPS + depends on SSB_DRIVER_MIPS && SSB_PCICORE_HOSTMODE + select USB_HCD_SSB if USB_EHCI_HCD || USB_OHCI_HCD default y diff --git a/target/linux/brcm47xx/patches-3.8/030-mtd-bcm47xxsflash-add-own-struct-for-abstrating-bus-.patch b/target/linux/brcm47xx/patches-3.8/030-mtd-bcm47xxsflash-add-own-struct-for-abstrating-bus-.patch index 2d2f11b..a1d9b37 100644 --- a/target/linux/brcm47xx/patches-3.8/030-mtd-bcm47xxsflash-add-own-struct-for-abstrating-bus-.patch +++ b/target/linux/brcm47xx/patches-3.8/030-mtd-bcm47xxsflash-add-own-struct-for-abstrating-bus-.patch @@ -113,7 +113,7 @@ +#endif /* BCM47XXSFLASH */ --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h -@@ -544,6 +544,7 @@ struct bcma_nflash { +@@ -599,6 +599,7 @@ struct bcma_nflash { bool boot; /* This is the flash the SoC boots from */ struct mtd_info *mtd; diff --git a/target/linux/brcm47xx/patches-3.8/060-ssb-add-serial-flash-driver.patch b/target/linux/brcm47xx/patches-3.8/060-ssb-add-serial-flash-driver.patch index 1148a48..dcb70e8 100644 --- a/target/linux/brcm47xx/patches-3.8/060-ssb-add-serial-flash-driver.patch +++ b/target/linux/brcm47xx/patches-3.8/060-ssb-add-serial-flash-driver.patch @@ -11,7 +11,7 @@ # Assumption: We are on embedded, if we compile the MIPS core. --- a/drivers/ssb/driver_chipcommon_sflash.c +++ b/drivers/ssb/driver_chipcommon_sflash.c -@@ -1,14 +1,35 @@ +@@ -1,14 +1,22 @@ /* * Sonics Silicon Backplane * ChipCommon serial flash interface @@ -31,50 +31,19 @@ +#define NUM_RETRIES 3 + -+static struct resource ssb_sflash_resource = { -+ .name = "ssb_sflash", -+ .start = SSB_FLASH2, -+ .end = 0, -+ .flags = IORESOURCE_MEM | IORESOURCE_READONLY, -+}; -+ -+struct platform_device ssb_sflash_dev = { -+ .name = "bcm47xx-sflash", -+ .resource = &ssb_sflash_resource, -+ .num_resources = 1, -+}; -+ - struct ssb_sflash_tbl_e { - char *name; - u32 id; -@@ -16,7 +37,7 @@ struct ssb_sflash_tbl_e { - u16 numblocks; + static struct resource ssb_sflash_resource = { + .name = "ssb_sflash", + .start = SSB_FLASH2, +@@ -17,7 +25,7 @@ static struct resource ssb_sflash_resour }; --static struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = { -+static const struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = { - { "M25P20", 0x11, 0x10000, 4, }, - { "M25P40", 0x12, 0x10000, 8, }, - -@@ -27,7 +48,7 @@ static struct ssb_sflash_tbl_e ssb_sflas - { 0 }, - }; - --static struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { -+static const struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { - { "SST25WF512", 1, 0x1000, 16, }, - { "SST25VF512", 0x48, 0x1000, 16, }, - { "SST25WF010", 2, 0x1000, 32, }, -@@ -45,7 +66,7 @@ static struct ssb_sflash_tbl_e ssb_sflas - { 0 }, + struct platform_device ssb_sflash_dev = { +- .name = "ssb_sflash", ++ .name = "bcm47xx-sflash", + .resource = &ssb_sflash_resource, + .num_resources = 1, }; - --static struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { -+static const struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { - { "AT45DB011", 0xc, 256, 512, }, - { "AT45DB021", 0x14, 256, 1024, }, - { "AT45DB041", 0x1c, 256, 2048, }, -@@ -70,10 +91,186 @@ static void ssb_sflash_cmd(struct ssb_ch +@@ -83,10 +91,185 @@ static void ssb_sflash_cmd(struct ssb_ch pr_err("SFLASH control command failed (timeout)!\n"); } @@ -256,25 +225,18 @@ /* Initialize serial flash access */ int ssb_sflash_init(struct ssb_chipcommon *cc) { -- struct ssb_sflash_tbl_e *e; +- struct ssb_sflash *sflash = &cc->dev->bus->mipscore.sflash; + struct bcm47xxsflash *sflash = &cc->sflash; -+ const struct ssb_sflash_tbl_e *e; + const struct ssb_sflash_tbl_e *e; u32 id, id2; - switch (cc->capabilities & SSB_CHIPCO_CAP_FLASHT) { -@@ -131,10 +328,26 @@ int ssb_sflash_init(struct ssb_chipcommo - return -ENOTSUPP; - } - +@@ -150,17 +333,21 @@ int ssb_sflash_init(struct ssb_chipcommo + sflash->numblocks = e->numblocks; + sflash->size = sflash->blocksize * sflash->numblocks; + sflash->present = true; +- - pr_info("Found %s serial flash (blocksize: 0x%X, blocks: %d)\n", - e->name, e->blocksize, e->numblocks); -- -- pr_err("Serial flash support is not implemented yet!\n"); -+ sflash->window = SSB_FLASH2; -+ sflash->blocksize = e->blocksize; -+ sflash->numblocks = e->numblocks; -+ sflash->size = sflash->blocksize * sflash->numblocks; -+ sflash->present = true; + sflash->poll = ssb_sflash_poll; + sflash->write = ssb_sflash_write; + sflash->erase = ssb_sflash_erase; @@ -284,13 +246,16 @@ + pr_info("Found %s serial flash (size: %dKiB, blocksize: 0x%X, blocks: %d)\n", + e->name, sflash->size / 1024, sflash->blocksize, + sflash->numblocks); -+ -+ /* Prepare platform device, but don't register it yet. It's too early, -+ * malloc (required by device_private_init) is not available yet. */ -+ ssb_sflash_dev.resource[0].end = ssb_sflash_dev.resource[0].start + + + /* Prepare platform device, but don't register it yet. It's too early, + * malloc (required by device_private_init) is not available yet. */ + ssb_sflash_dev.resource[0].end = ssb_sflash_dev.resource[0].start + +- sflash->size; + sflash->size; -+ ssb_sflash_dev.dev.platform_data = sflash; + ssb_sflash_dev.dev.platform_data = sflash; +- pr_err("Serial flash support is not implemented yet!\n"); +- - return -ENOTSUPP; + return 0; } diff --git a/target/linux/brcm47xx/patches-3.8/070-bcma-add-functions-to-write-to-serial-flash.patch b/target/linux/brcm47xx/patches-3.8/070-bcma-add-functions-to-write-to-serial-flash.patch index bba2b69..fb0e046 100644 --- a/target/linux/brcm47xx/patches-3.8/070-bcma-add-functions-to-write-to-serial-flash.patch +++ b/target/linux/brcm47xx/patches-3.8/070-bcma-add-functions-to-write-to-serial-flash.patch @@ -31,34 +31,7 @@ .resource = &bcma_sflash_resource, .num_resources = 1, }; -@@ -30,7 +37,7 @@ struct bcma_sflash_tbl_e { - u16 numblocks; - }; - --static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { -+static const struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { - { "M25P20", 0x11, 0x10000, 4, }, - { "M25P40", 0x12, 0x10000, 8, }, - -@@ -41,7 +48,7 @@ static struct bcma_sflash_tbl_e bcma_sfl - { 0 }, - }; - --static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { -+static const struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { - { "SST25WF512", 1, 0x1000, 16, }, - { "SST25VF512", 0x48, 0x1000, 16, }, - { "SST25WF010", 2, 0x1000, 32, }, -@@ -59,7 +66,7 @@ static struct bcma_sflash_tbl_e bcma_sfl - { 0 }, - }; - --static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { -+static const struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { - { "AT45DB011", 0xc, 256, 512, }, - { "AT45DB021", 0x14, 256, 1024, }, - { "AT45DB041", 0x1c, 256, 2048, }, -@@ -84,12 +91,186 @@ static void bcma_sflash_cmd(struct bcma_ +@@ -84,11 +91,185 @@ static void bcma_sflash_cmd(struct bcma_ bcma_err(cc->core->bus, "SFLASH control command failed (timeout)!\n"); } @@ -241,12 +214,10 @@ { struct bcma_bus *bus = cc->core->bus; - struct bcma_sflash *sflash = &cc->sflash; -- struct bcma_sflash_tbl_e *e; + struct bcm47xxsflash *sflash = &cc->sflash; -+ const struct bcma_sflash_tbl_e *e; + const struct bcma_sflash_tbl_e *e; u32 id, id2; - switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { @@ -150,6 +331,11 @@ int bcma_sflash_init(struct bcma_drv_cc sflash->numblocks = e->numblocks; sflash->size = sflash->blocksize * sflash->numblocks; @@ -269,7 +240,7 @@ /** ChipCommon core registers. **/ #define BCMA_CC_ID 0x0000 -@@ -523,19 +524,6 @@ struct bcma_pflash { +@@ -578,19 +579,6 @@ struct bcma_pflash { u32 window_size; }; @@ -289,7 +260,7 @@ #ifdef CONFIG_BCMA_NFLASH struct mtd_info; -@@ -570,7 +558,7 @@ struct bcma_drv_cc { +@@ -625,7 +613,7 @@ struct bcma_drv_cc { #ifdef CONFIG_BCMA_DRIVER_MIPS struct bcma_pflash pflash; #ifdef CONFIG_BCMA_SFLASH diff --git a/target/linux/brcm47xx/patches-3.8/241-bcma-broadcom-2011-sdk-updates.patch b/target/linux/brcm47xx/patches-3.8/241-bcma-broadcom-2011-sdk-updates.patch deleted file mode 100644 index 72b0208..0000000 --- a/target/linux/brcm47xx/patches-3.8/241-bcma-broadcom-2011-sdk-updates.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/drivers/bcma/core.c -+++ b/drivers/bcma/core.c -@@ -43,6 +43,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)); diff --git a/target/linux/brcm47xx/patches-3.8/280-activate_ssb_support_in_usb.patch b/target/linux/brcm47xx/patches-3.8/280-activate_ssb_support_in_usb.patch index c4382ed..aabaf29 100644 --- a/target/linux/brcm47xx/patches-3.8/280-activate_ssb_support_in_usb.patch +++ b/target/linux/brcm47xx/patches-3.8/280-activate_ssb_support_in_usb.patch @@ -5,7 +5,7 @@ This prevents the options from being delete with make kernel_oldconfig. --- a/drivers/bcma/Kconfig +++ b/drivers/bcma/Kconfig -@@ -37,6 +37,7 @@ config BCMA_DRIVER_PCI_HOSTMODE +@@ -38,6 +38,7 @@ config BCMA_DRIVER_PCI_HOSTMODE config BCMA_HOST_SOC bool depends on BCMA_DRIVER_MIPS @@ -18,7 +18,7 @@ This prevents the options from being delete with make kernel_oldconfig. @@ -146,6 +146,7 @@ config SSB_SFLASH config SSB_EMBEDDED bool - depends on SSB_DRIVER_MIPS + depends on SSB_DRIVER_MIPS && SSB_PCICORE_HOSTMODE + select USB_HCD_SSB if USB_EHCI_HCD || USB_OHCI_HCD default y diff --git a/target/linux/brcm47xx/patches-3.9/060-ssb-add-serial-flash-driver.patch b/target/linux/brcm47xx/patches-3.9/060-ssb-add-serial-flash-driver.patch index 1148a48..dcb70e8 100644 --- a/target/linux/brcm47xx/patches-3.9/060-ssb-add-serial-flash-driver.patch +++ b/target/linux/brcm47xx/patches-3.9/060-ssb-add-serial-flash-driver.patch @@ -11,7 +11,7 @@ # Assumption: We are on embedded, if we compile the MIPS core. --- a/drivers/ssb/driver_chipcommon_sflash.c +++ b/drivers/ssb/driver_chipcommon_sflash.c -@@ -1,14 +1,35 @@ +@@ -1,14 +1,22 @@ /* * Sonics Silicon Backplane * ChipCommon serial flash interface @@ -31,50 +31,19 @@ +#define NUM_RETRIES 3 + -+static struct resource ssb_sflash_resource = { -+ .name = "ssb_sflash", -+ .start = SSB_FLASH2, -+ .end = 0, -+ .flags = IORESOURCE_MEM | IORESOURCE_READONLY, -+}; -+ -+struct platform_device ssb_sflash_dev = { -+ .name = "bcm47xx-sflash", -+ .resource = &ssb_sflash_resource, -+ .num_resources = 1, -+}; -+ - struct ssb_sflash_tbl_e { - char *name; - u32 id; -@@ -16,7 +37,7 @@ struct ssb_sflash_tbl_e { - u16 numblocks; + static struct resource ssb_sflash_resource = { + .name = "ssb_sflash", + .start = SSB_FLASH2, +@@ -17,7 +25,7 @@ static struct resource ssb_sflash_resour }; --static struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = { -+static const struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = { - { "M25P20", 0x11, 0x10000, 4, }, - { "M25P40", 0x12, 0x10000, 8, }, - -@@ -27,7 +48,7 @@ static struct ssb_sflash_tbl_e ssb_sflas - { 0 }, - }; - --static struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { -+static const struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { - { "SST25WF512", 1, 0x1000, 16, }, - { "SST25VF512", 0x48, 0x1000, 16, }, - { "SST25WF010", 2, 0x1000, 32, }, -@@ -45,7 +66,7 @@ static struct ssb_sflash_tbl_e ssb_sflas - { 0 }, + struct platform_device ssb_sflash_dev = { +- .name = "ssb_sflash", ++ .name = "bcm47xx-sflash", + .resource = &ssb_sflash_resource, + .num_resources = 1, }; - --static struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { -+static const struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { - { "AT45DB011", 0xc, 256, 512, }, - { "AT45DB021", 0x14, 256, 1024, }, - { "AT45DB041", 0x1c, 256, 2048, }, -@@ -70,10 +91,186 @@ static void ssb_sflash_cmd(struct ssb_ch +@@ -83,10 +91,185 @@ static void ssb_sflash_cmd(struct ssb_ch pr_err("SFLASH control command failed (timeout)!\n"); } @@ -256,25 +225,18 @@ /* Initialize serial flash access */ int ssb_sflash_init(struct ssb_chipcommon *cc) { -- struct ssb_sflash_tbl_e *e; +- struct ssb_sflash *sflash = &cc->dev->bus->mipscore.sflash; + struct bcm47xxsflash *sflash = &cc->sflash; -+ const struct ssb_sflash_tbl_e *e; + const struct ssb_sflash_tbl_e *e; u32 id, id2; - switch (cc->capabilities & SSB_CHIPCO_CAP_FLASHT) { -@@ -131,10 +328,26 @@ int ssb_sflash_init(struct ssb_chipcommo - return -ENOTSUPP; - } - +@@ -150,17 +333,21 @@ int ssb_sflash_init(struct ssb_chipcommo + sflash->numblocks = e->numblocks; + sflash->size = sflash->blocksize * sflash->numblocks; + sflash->present = true; +- - pr_info("Found %s serial flash (blocksize: 0x%X, blocks: %d)\n", - e->name, e->blocksize, e->numblocks); -- -- pr_err("Serial flash support is not implemented yet!\n"); -+ sflash->window = SSB_FLASH2; -+ sflash->blocksize = e->blocksize; -+ sflash->numblocks = e->numblocks; -+ sflash->size = sflash->blocksize * sflash->numblocks; -+ sflash->present = true; + sflash->poll = ssb_sflash_poll; + sflash->write = ssb_sflash_write; + sflash->erase = ssb_sflash_erase; @@ -284,13 +246,16 @@ + pr_info("Found %s serial flash (size: %dKiB, blocksize: 0x%X, blocks: %d)\n", + e->name, sflash->size / 1024, sflash->blocksize, + sflash->numblocks); -+ -+ /* Prepare platform device, but don't register it yet. It's too early, -+ * malloc (required by device_private_init) is not available yet. */ -+ ssb_sflash_dev.resource[0].end = ssb_sflash_dev.resource[0].start + + + /* Prepare platform device, but don't register it yet. It's too early, + * malloc (required by device_private_init) is not available yet. */ + ssb_sflash_dev.resource[0].end = ssb_sflash_dev.resource[0].start + +- sflash->size; + sflash->size; -+ ssb_sflash_dev.dev.platform_data = sflash; + ssb_sflash_dev.dev.platform_data = sflash; +- pr_err("Serial flash support is not implemented yet!\n"); +- - return -ENOTSUPP; + return 0; } diff --git a/target/linux/brcm47xx/patches-3.9/070-bcma-add-functions-to-write-to-serial-flash.patch b/target/linux/brcm47xx/patches-3.9/070-bcma-add-functions-to-write-to-serial-flash.patch index 3a06b52..9999848 100644 --- a/target/linux/brcm47xx/patches-3.9/070-bcma-add-functions-to-write-to-serial-flash.patch +++ b/target/linux/brcm47xx/patches-3.9/070-bcma-add-functions-to-write-to-serial-flash.patch @@ -31,34 +31,7 @@ .resource = &bcma_sflash_resource, .num_resources = 1, }; -@@ -30,7 +37,7 @@ struct bcma_sflash_tbl_e { - u16 numblocks; - }; - --static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { -+static const struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { - { "M25P20", 0x11, 0x10000, 4, }, - { "M25P40", 0x12, 0x10000, 8, }, - -@@ -41,7 +48,7 @@ static struct bcma_sflash_tbl_e bcma_sfl - { 0 }, - }; - --static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { -+static const struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { - { "SST25WF512", 1, 0x1000, 16, }, - { "SST25VF512", 0x48, 0x1000, 16, }, - { "SST25WF010", 2, 0x1000, 32, }, -@@ -59,7 +66,7 @@ static struct bcma_sflash_tbl_e bcma_sfl - { 0 }, - }; - --static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { -+static const struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { - { "AT45DB011", 0xc, 256, 512, }, - { "AT45DB021", 0x14, 256, 1024, }, - { "AT45DB041", 0x1c, 256, 2048, }, -@@ -84,12 +91,186 @@ static void bcma_sflash_cmd(struct bcma_ +@@ -84,11 +91,185 @@ static void bcma_sflash_cmd(struct bcma_ bcma_err(cc->core->bus, "SFLASH control command failed (timeout)!\n"); } @@ -241,12 +214,10 @@ { struct bcma_bus *bus = cc->core->bus; - struct bcma_sflash *sflash = &cc->sflash; -- struct bcma_sflash_tbl_e *e; + struct bcm47xxsflash *sflash = &cc->sflash; -+ const struct bcma_sflash_tbl_e *e; + const struct bcma_sflash_tbl_e *e; u32 id, id2; - switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { @@ -150,6 +331,11 @@ int bcma_sflash_init(struct bcma_drv_cc sflash->numblocks = e->numblocks; sflash->size = sflash->blocksize * sflash->numblocks; @@ -269,7 +240,7 @@ /** ChipCommon core registers. **/ #define BCMA_CC_ID 0x0000 -@@ -523,19 +524,6 @@ struct bcma_pflash { +@@ -578,19 +579,6 @@ struct bcma_pflash { u32 window_size; }; @@ -289,7 +260,7 @@ #ifdef CONFIG_BCMA_NFLASH struct mtd_info; -@@ -569,7 +557,7 @@ struct bcma_drv_cc { +@@ -624,7 +612,7 @@ struct bcma_drv_cc { #ifdef CONFIG_BCMA_DRIVER_MIPS struct bcma_pflash pflash; #ifdef CONFIG_BCMA_SFLASH diff --git a/target/linux/brcm47xx/patches-3.9/241-bcma-broadcom-2011-sdk-updates.patch b/target/linux/brcm47xx/patches-3.9/241-bcma-broadcom-2011-sdk-updates.patch deleted file mode 100644 index 72b0208..0000000 --- a/target/linux/brcm47xx/patches-3.9/241-bcma-broadcom-2011-sdk-updates.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/drivers/bcma/core.c -+++ b/drivers/bcma/core.c -@@ -43,6 +43,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)); diff --git a/target/linux/brcm47xx/patches-3.9/280-activate_ssb_support_in_usb.patch b/target/linux/brcm47xx/patches-3.9/280-activate_ssb_support_in_usb.patch index c4382ed..aabaf29 100644 --- a/target/linux/brcm47xx/patches-3.9/280-activate_ssb_support_in_usb.patch +++ b/target/linux/brcm47xx/patches-3.9/280-activate_ssb_support_in_usb.patch @@ -5,7 +5,7 @@ This prevents the options from being delete with make kernel_oldconfig. --- a/drivers/bcma/Kconfig +++ b/drivers/bcma/Kconfig -@@ -37,6 +37,7 @@ config BCMA_DRIVER_PCI_HOSTMODE +@@ -38,6 +38,7 @@ config BCMA_DRIVER_PCI_HOSTMODE config BCMA_HOST_SOC bool depends on BCMA_DRIVER_MIPS @@ -18,7 +18,7 @@ This prevents the options from being delete with make kernel_oldconfig. @@ -146,6 +146,7 @@ config SSB_SFLASH config SSB_EMBEDDED bool - depends on SSB_DRIVER_MIPS + depends on SSB_DRIVER_MIPS && SSB_PCICORE_HOSTMODE + select USB_HCD_SSB if USB_EHCI_HCD || USB_OHCI_HCD default y diff --git a/target/linux/generic/patches-3.10/020-ssb_update.patch b/target/linux/generic/patches-3.10/020-ssb_update.patch new file mode 100644 index 0000000..0a75e5e --- /dev/null +++ b/target/linux/generic/patches-3.10/020-ssb_update.patch @@ -0,0 +1,201 @@ +diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig +index 5ff3a4f..36171fd 100644 +--- a/drivers/ssb/Kconfig ++++ b/drivers/ssb/Kconfig +@@ -144,7 +144,7 @@ config SSB_SFLASH + # Assumption: We are on embedded, if we compile the MIPS core. + config SSB_EMBEDDED + bool +- depends on SSB_DRIVER_MIPS ++ depends on SSB_DRIVER_MIPS && SSB_PCICORE_HOSTMODE + default y + + config SSB_DRIVER_EXTIF +diff --git a/drivers/ssb/driver_chipcommon_sflash.c b/drivers/ssb/driver_chipcommon_sflash.c +index 720665c..e84cf04 100644 +--- a/drivers/ssb/driver_chipcommon_sflash.c ++++ b/drivers/ssb/driver_chipcommon_sflash.c +@@ -9,6 +9,19 @@ + + #include "ssb_private.h" + ++static struct resource ssb_sflash_resource = { ++ .name = "ssb_sflash", ++ .start = SSB_FLASH2, ++ .end = 0, ++ .flags = IORESOURCE_MEM | IORESOURCE_READONLY, ++}; ++ ++struct platform_device ssb_sflash_dev = { ++ .name = "ssb_sflash", ++ .resource = &ssb_sflash_resource, ++ .num_resources = 1, ++}; ++ + struct ssb_sflash_tbl_e { + char *name; + u32 id; +@@ -16,7 +29,7 @@ struct ssb_sflash_tbl_e { + u16 numblocks; + }; + +-static struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = { ++static const struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = { + { "M25P20", 0x11, 0x10000, 4, }, + { "M25P40", 0x12, 0x10000, 8, }, + +@@ -27,7 +40,7 @@ static struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = { + { 0 }, + }; + +-static struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { ++static const struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { + { "SST25WF512", 1, 0x1000, 16, }, + { "SST25VF512", 0x48, 0x1000, 16, }, + { "SST25WF010", 2, 0x1000, 32, }, +@@ -45,7 +58,7 @@ static struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { + { 0 }, + }; + +-static struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { ++static const struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { + { "AT45DB011", 0xc, 256, 512, }, + { "AT45DB021", 0x14, 256, 1024, }, + { "AT45DB041", 0x1c, 256, 2048, }, +@@ -73,7 +86,8 @@ static void ssb_sflash_cmd(struct ssb_chipcommon *cc, u32 opcode) + /* Initialize serial flash access */ + int ssb_sflash_init(struct ssb_chipcommon *cc) + { +- struct ssb_sflash_tbl_e *e; ++ struct ssb_sflash *sflash = &cc->dev->bus->mipscore.sflash; ++ const struct ssb_sflash_tbl_e *e; + u32 id, id2; + + switch (cc->capabilities & SSB_CHIPCO_CAP_FLASHT) { +@@ -131,9 +145,21 @@ int ssb_sflash_init(struct ssb_chipcommon *cc) + return -ENOTSUPP; + } + ++ sflash->window = SSB_FLASH2; ++ sflash->blocksize = e->blocksize; ++ sflash->numblocks = e->numblocks; ++ sflash->size = sflash->blocksize * sflash->numblocks; ++ sflash->present = true; ++ + pr_info("Found %s serial flash (blocksize: 0x%X, blocks: %d)\n", + e->name, e->blocksize, e->numblocks); + ++ /* Prepare platform device, but don't register it yet. It's too early, ++ * malloc (required by device_private_init) is not available yet. */ ++ ssb_sflash_dev.resource[0].end = ssb_sflash_dev.resource[0].start + ++ sflash->size; ++ ssb_sflash_dev.dev.platform_data = sflash; ++ + pr_err("Serial flash support is not implemented yet!\n"); + + return -ENOTSUPP; +diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c +index 812775a..e55ddf7 100644 +--- a/drivers/ssb/main.c ++++ b/drivers/ssb/main.c +@@ -553,6 +553,14 @@ static int ssb_devices_register(struct ssb_bus *bus) + } + #endif + ++#ifdef CONFIG_SSB_SFLASH ++ if (bus->mipscore.sflash.present) { ++ err = platform_device_register(&ssb_sflash_dev); ++ if (err) ++ pr_err("Error registering serial flash\n"); ++ } ++#endif ++ + return 0; + error: + /* Unwind the already registered devices. */ +diff --git a/drivers/ssb/pcihost_wrapper.c b/drivers/ssb/pcihost_wrapper.c +index 32ed1fa..69161bb 100644 +--- a/drivers/ssb/pcihost_wrapper.c ++++ b/drivers/ssb/pcihost_wrapper.c +@@ -38,7 +38,7 @@ static int ssb_pcihost_resume(struct pci_dev *dev) + struct ssb_bus *ssb = pci_get_drvdata(dev); + int err; + +- pci_set_power_state(dev, 0); ++ pci_set_power_state(dev, PCI_D0); + err = pci_enable_device(dev); + if (err) + return err; +diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c +index a3b2364..e753fbe 100644 +--- a/drivers/ssb/sprom.c ++++ b/drivers/ssb/sprom.c +@@ -54,7 +54,7 @@ static int hex2sprom(u16 *sprom, const char *dump, size_t len, + while (cnt < sprom_size_words) { + memcpy(tmp, dump, 4); + dump += 4; +- err = strict_strtoul(tmp, 16, &parsed); ++ err = kstrtoul(tmp, 16, &parsed); + if (err) + return err; + sprom[cnt++] = swab16((u16)parsed); +diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h +index 4671f17..eb507a5 100644 +--- a/drivers/ssb/ssb_private.h ++++ b/drivers/ssb/ssb_private.h +@@ -243,6 +243,10 @@ static inline int ssb_sflash_init(struct ssb_chipcommon *cc) + extern struct platform_device ssb_pflash_dev; + #endif + ++#ifdef CONFIG_SSB_SFLASH ++extern struct platform_device ssb_sflash_dev; ++#endif ++ + #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); +diff --git a/include/linux/ssb/ssb_driver_mips.h b/include/linux/ssb/ssb_driver_mips.h +index afe79d4..6535e47 100644 +--- a/include/linux/ssb/ssb_driver_mips.h ++++ b/include/linux/ssb/ssb_driver_mips.h +@@ -20,6 +20,18 @@ struct ssb_pflash { + u32 window_size; + }; + ++#ifdef CONFIG_SSB_SFLASH ++struct ssb_sflash { ++ bool present; ++ u32 window; ++ u32 blocksize; ++ u16 numblocks; ++ u32 size; ++ ++ void *priv; ++}; ++#endif ++ + struct ssb_mipscore { + struct ssb_device *dev; + +@@ -27,6 +39,9 @@ struct ssb_mipscore { + struct ssb_serial_port serial_ports[4]; + + struct ssb_pflash pflash; ++#ifdef CONFIG_SSB_SFLASH ++ struct ssb_sflash sflash; ++#endif + }; + + extern void ssb_mipscore_init(struct ssb_mipscore *mcore); +diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h +index 3a72569..f9f931c 100644 +--- a/include/linux/ssb/ssb_regs.h ++++ b/include/linux/ssb/ssb_regs.h +@@ -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 diff --git a/target/linux/generic/patches-3.10/025-bcma_backport.patch b/target/linux/generic/patches-3.10/025-bcma_backport.patch new file mode 100644 index 0000000..a6e3b01 --- /dev/null +++ b/target/linux/generic/patches-3.10/025-bcma_backport.patch @@ -0,0 +1,601 @@ +diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig +index 8b4221c..380a200 100644 +--- a/drivers/bcma/Kconfig ++++ b/drivers/bcma/Kconfig +@@ -26,6 +26,7 @@ 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" +diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h +index 79595a0..0215f9a 100644 +--- a/drivers/bcma/bcma_private.h ++++ b/drivers/bcma/bcma_private.h +@@ -22,6 +22,8 @@ + struct bcma_bus; + + /* main.c */ ++bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value, ++ int timeout); + int bcma_bus_register(struct bcma_bus *bus); + void bcma_bus_unregister(struct bcma_bus *bus); + int __init bcma_bus_early_register(struct bcma_bus *bus, +diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c +index 17b26ce..37a5ffe 100644 +--- a/drivers/bcma/core.c ++++ b/drivers/bcma/core.c +@@ -9,6 +9,25 @@ + #include <linux/export.h> + #include <linux/bcma/bcma.h> + ++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,13 +44,15 @@ void bcma_core_disable(struct bcma_device *core, u32 flags) + 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); + +@@ -43,6 +64,7 @@ int bcma_core_enable(struct bcma_device *core, u32 flags) + 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)); +diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c +index 036c674..b068f98 100644 +--- a/drivers/bcma/driver_chipcommon.c ++++ b/drivers/bcma/driver_chipcommon.c +@@ -140,8 +140,15 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) + 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) +diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c +index edca73a..5081a8c 100644 +--- a/drivers/bcma/driver_chipcommon_pmu.c ++++ b/drivers/bcma/driver_chipcommon_pmu.c +@@ -56,6 +56,109 @@ void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, + } + EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset); + ++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 BCMA_CHIP_ID_BCM43142: ++ if (xtalfreq == 0) ++ xtalfreq = 20000; ++ bcma_pmu2_pll_init0(cc, xtalfreq); ++ break; ++ } ++} ++ + static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) + { + struct bcma_bus *bus = cc->core->bus; +@@ -66,6 +169,25 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) + min_msk = 0x200D; + max_msk = 0xFFFF; + 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: + bcma_debug(bus, "PMU resource config unknown or not needed for device 0x%04X\n", + bus->chipinfo.id); +@@ -165,6 +287,7 @@ void bcma_pmu_init(struct bcma_drv_cc *cc) + bcma_cc_set32(cc, BCMA_CC_PMU_CTL, + BCMA_CC_PMU_CTL_NOILPONW); + ++ bcma_pmu_pll_init(cc); + bcma_pmu_resources_init(cc); + bcma_pmu_workarounds(cc); + } +diff --git a/drivers/bcma/driver_chipcommon_sflash.c b/drivers/bcma/driver_chipcommon_sflash.c +index e6ed4fe..4d07cce 100644 +--- a/drivers/bcma/driver_chipcommon_sflash.c ++++ b/drivers/bcma/driver_chipcommon_sflash.c +@@ -30,7 +30,7 @@ struct bcma_sflash_tbl_e { + u16 numblocks; + }; + +-static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { ++static const struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { + { "M25P20", 0x11, 0x10000, 4, }, + { "M25P40", 0x12, 0x10000, 8, }, + +@@ -41,7 +41,7 @@ static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { + { 0 }, + }; + +-static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { ++static const struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { + { "SST25WF512", 1, 0x1000, 16, }, + { "SST25VF512", 0x48, 0x1000, 16, }, + { "SST25WF010", 2, 0x1000, 32, }, +@@ -59,7 +59,7 @@ static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { + { 0 }, + }; + +-static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { ++static const struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { + { "AT45DB011", 0xc, 256, 512, }, + { "AT45DB021", 0x14, 256, 1024, }, + { "AT45DB041", 0x1c, 256, 2048, }, +@@ -89,7 +89,7 @@ int bcma_sflash_init(struct bcma_drv_cc *cc) + { + struct bcma_bus *bus = cc->core->bus; + struct bcma_sflash *sflash = &cc->sflash; +- struct bcma_sflash_tbl_e *e; ++ const struct bcma_sflash_tbl_e *e; + u32 id, id2; + + switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { +diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c +index fbf2759..a355e63 100644 +--- a/drivers/bcma/host_pci.c ++++ b/drivers/bcma/host_pci.c +@@ -275,6 +275,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, + { 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, }, + }; +diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c +index f72f52b..0067422 100644 +--- a/drivers/bcma/main.c ++++ b/drivers/bcma/main.c +@@ -93,6 +93,25 @@ struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid, + 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) + { + struct bcma_device *core = container_of(dev, struct bcma_device, dev); +diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c +index 8934298..72bf454 100644 +--- a/drivers/bcma/sprom.c ++++ b/drivers/bcma/sprom.c +@@ -72,12 +72,12 @@ fail: + * R/W ops. + **************************************************/ + +-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)); + } + + /************************************************** +@@ -124,29 +124,29 @@ static inline u8 bcma_crc8(u8 crc, u8 data) + 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; +@@ -154,21 +154,25 @@ static int bcma_sprom_check_crc(const u16 *sprom) + 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; + } + +@@ -208,9 +212,6 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) + 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; +- + for (i = 0; i < 3; i++) { + v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i]; + *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v); +@@ -502,7 +503,7 @@ static bool bcma_sprom_onchip_available(struct bcma_bus *bus) + 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 */ +@@ -550,7 +551,9 @@ int bcma_sprom_get(struct bcma_bus *bus) + { + u16 offset = BCMA_CC_SPROM; + u16 *sprom; +- 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; +@@ -579,32 +582,37 @@ int bcma_sprom_get(struct bcma_bus *bus) + } + } + +- sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), +- GFP_KERNEL); +- if (!sprom) +- return -ENOMEM; +- + 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, false); + + 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; ++ ++ kfree(sprom); ++ } + + 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); + +- err = bcma_sprom_valid(sprom); + if (err) { +- bcma_warn(bus, "invalid sprom read from the PCIe card, try to use fallback sprom\n"); ++ 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); +- goto out; ++ } else { ++ bcma_sprom_extract_r8(bus, sprom); ++ kfree(sprom); + } + +- bcma_sprom_extract_r8(bus, sprom); +- +-out: +- kfree(sprom); + return err; + } +diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h +index 2e34db8..622fc50 100644 +--- a/include/linux/bcma/bcma.h ++++ b/include/linux/bcma/bcma.h +@@ -144,6 +144,7 @@ struct bcma_host_ops { + + /* 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 +diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h +index b8b09ea..c49e1a1 100644 +--- a/include/linux/bcma/bcma_driver_chipcommon.h ++++ b/include/linux/bcma/bcma_driver_chipcommon.h +@@ -330,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 */ +@@ -355,6 +357,11 @@ + #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 */ + /* NAND flash MLC controller registers (corerev >= 38) */ + #define BCMA_CC_NAND_REVISION 0x0C00 +@@ -435,6 +442,23 @@ + #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 + /* HT clock for systems with PMU-enabled chipcommon */ +@@ -507,6 +531,37 @@ + #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) + */ diff --git a/target/linux/generic/patches-3.3/020-ssb_update.patch b/target/linux/generic/patches-3.3/020-ssb_update.patch index 4ca2614..51b23b0 100644 --- a/target/linux/generic/patches-3.3/020-ssb_update.patch +++ b/target/linux/generic/patches-3.3/020-ssb_update.patch @@ -30,7 +30,7 @@ ARRAY_SIZE(wgt634u_devices)); --- a/drivers/ssb/Kconfig +++ b/drivers/ssb/Kconfig -@@ -136,6 +136,11 @@ config SSB_DRIVER_MIPS +@@ -136,10 +136,15 @@ config SSB_DRIVER_MIPS If unsure, say N @@ -42,6 +42,11 @@ # Assumption: We are on embedded, if we compile the MIPS core. config SSB_EMBEDDED bool +- depends on SSB_DRIVER_MIPS ++ depends on SSB_DRIVER_MIPS && SSB_PCICORE_HOSTMODE + default y + + config SSB_DRIVER_EXTIF @@ -160,4 +165,12 @@ config SSB_DRIVER_GIGE If unsure, say N @@ -106,7 +111,7 @@ #include "ssb_private.h" -@@ -280,10 +282,76 @@ static void calc_fast_powerup_delay(stru +@@ -280,13 +282,79 @@ static void calc_fast_powerup_delay(stru cc->fast_pwrup_delay = tmp; } @@ -182,7 +187,11 @@ + 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_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); @@ -362,6 +371,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. */ @@ -387,16 +436,22 @@ ssb_pmu0_pllinit_r0(cc, crystalfreq); break; case 0x4322: -@@ -339,6 +346,8 @@ static void ssb_pmu_pll_init(struct ssb_ +@@ -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", -@@ -427,6 +436,7 @@ static void ssb_pmu_resources_init(struc +- 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: @@ -404,7 +459,30 @@ /* We keep the default settings: * min_msk = 0xCBB * max_msk = 0x7FFFF -@@ -607,3 +617,90 @@ void ssb_pmu_set_ldo_paref(struct ssb_ch +@@ -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); @@ -429,9 +507,8 @@ + case 0x5354: + ssb_pmu_get_alp_clock_clk0(cc); + default: -+ ssb_printk(KERN_ERR PFX -+ "ERROR: PMU alp clock unknown for device %04X\n", -+ bus->chip_id); ++ ssb_err("ERROR: PMU alp clock unknown for device %04X\n", ++ bus->chip_id); + return 0; + } +} @@ -445,9 +522,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; + } +} @@ -460,9 +536,8 @@ + 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; + } +} @@ -483,8 +558,23 @@ + pmu_ctl = SSB_CHIPCO_PMU_CTL_PLL_UPD; + break; + case 43222: -+ /* TODO: BCM43222 requires updating PLLs too */ -+ return; ++ 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", @@ -497,7 +587,7 @@ +EXPORT_SYMBOL_GPL(ssb_pmu_spuravoid_pllupdate); --- /dev/null +++ b/drivers/ssb/driver_chipcommon_sflash.c -@@ -0,0 +1,18 @@ +@@ -0,0 +1,166 @@ +/* + * Sonics Silicon Backplane + * ChipCommon serial flash interface @@ -509,9 +599,157 @@ + +#include "ssb_private.h" + ++static struct resource ssb_sflash_resource = { ++ .name = "ssb_sflash", ++ .start = SSB_FLASH2, ++ .end = 0, ++ .flags = IORESOURCE_MEM | IORESOURCE_READONLY, ++}; ++ ++struct platform_device ssb_sflash_dev = { ++ .name = "ssb_sflash", ++ .resource = &ssb_sflash_resource, ++ .num_resources = 1, ++}; ++ ++struct ssb_sflash_tbl_e { ++ char *name; ++ u32 id; ++ u32 blocksize; ++ u16 numblocks; ++}; ++ ++static const struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = { ++ { "M25P20", 0x11, 0x10000, 4, }, ++ { "M25P40", 0x12, 0x10000, 8, }, ++ ++ { "M25P16", 0x14, 0x10000, 32, }, ++ { "M25P32", 0x15, 0x10000, 64, }, ++ { "M25P64", 0x16, 0x10000, 128, }, ++ { "M25FL128", 0x17, 0x10000, 256, }, ++ { 0 }, ++}; ++ ++static const struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { ++ { "SST25WF512", 1, 0x1000, 16, }, ++ { "SST25VF512", 0x48, 0x1000, 16, }, ++ { "SST25WF010", 2, 0x1000, 32, }, ++ { "SST25VF010", 0x49, 0x1000, 32, }, ++ { "SST25WF020", 3, 0x1000, 64, }, ++ { "SST25VF020", 0x43, 0x1000, 64, }, ++ { "SST25WF040", 4, 0x1000, 128, }, ++ { "SST25VF040", 0x44, 0x1000, 128, }, ++ { "SST25VF040B", 0x8d, 0x1000, 128, }, ++ { "SST25WF080", 5, 0x1000, 256, }, ++ { "SST25VF080B", 0x8e, 0x1000, 256, }, ++ { "SST25VF016", 0x41, 0x1000, 512, }, ++ { "SST25VF032", 0x4a, 0x1000, 1024, }, ++ { "SST25VF064", 0x4b, 0x1000, 2048, }, ++ { 0 }, ++}; ++ ++static const struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { ++ { "AT45DB011", 0xc, 256, 512, }, ++ { "AT45DB021", 0x14, 256, 1024, }, ++ { "AT45DB041", 0x1c, 256, 2048, }, ++ { "AT45DB081", 0x24, 256, 4096, }, ++ { "AT45DB161", 0x2c, 512, 4096, }, ++ { "AT45DB321", 0x34, 512, 8192, }, ++ { "AT45DB642", 0x3c, 1024, 8192, }, ++ { 0 }, ++}; ++ ++static void ssb_sflash_cmd(struct ssb_chipcommon *cc, u32 opcode) ++{ ++ int i; ++ chipco_write32(cc, SSB_CHIPCO_FLASHCTL, ++ SSB_CHIPCO_FLASHCTL_START | opcode); ++ for (i = 0; i < 1000; i++) { ++ if (!(chipco_read32(cc, SSB_CHIPCO_FLASHCTL) & ++ SSB_CHIPCO_FLASHCTL_BUSY)) ++ return; ++ cpu_relax(); ++ } ++ pr_err("SFLASH control command failed (timeout)!\n"); ++} ++ +/* Initialize serial flash access */ +int ssb_sflash_init(struct ssb_chipcommon *cc) +{ ++ struct ssb_sflash *sflash = &cc->dev->bus->mipscore.sflash; ++ const struct ssb_sflash_tbl_e *e; ++ u32 id, id2; ++ ++ switch (cc->capabilities & SSB_CHIPCO_CAP_FLASHT) { ++ case SSB_CHIPCO_FLASHT_STSER: ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_DP); ++ ++ chipco_write32(cc, SSB_CHIPCO_FLASHADDR, 0); ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_RES); ++ id = chipco_read32(cc, SSB_CHIPCO_FLASHDATA); ++ ++ chipco_write32(cc, SSB_CHIPCO_FLASHADDR, 1); ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_RES); ++ id2 = chipco_read32(cc, SSB_CHIPCO_FLASHDATA); ++ ++ switch (id) { ++ case 0xbf: ++ for (e = ssb_sflash_sst_tbl; e->name; e++) { ++ if (e->id == id2) ++ break; ++ } ++ break; ++ case 0x13: ++ return -ENOTSUPP; ++ default: ++ for (e = ssb_sflash_st_tbl; e->name; e++) { ++ if (e->id == id) ++ break; ++ } ++ break; ++ } ++ if (!e->name) { ++ pr_err("Unsupported ST serial flash (id: 0x%X, id2: 0x%X)\n", ++ id, id2); ++ return -ENOTSUPP; ++ } ++ ++ break; ++ case SSB_CHIPCO_FLASHT_ATSER: ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_AT_STATUS); ++ id = chipco_read32(cc, SSB_CHIPCO_FLASHDATA) & 0x3c; ++ ++ for (e = ssb_sflash_at_tbl; e->name; e++) { ++ if (e->id == id) ++ break; ++ } ++ if (!e->name) { ++ pr_err("Unsupported Atmel serial flash (id: 0x%X)\n", ++ id); ++ return -ENOTSUPP; ++ } ++ ++ break; ++ default: ++ pr_err("Unsupported flash type\n"); ++ return -ENOTSUPP; ++ } ++ ++ sflash->window = SSB_FLASH2; ++ sflash->blocksize = e->blocksize; ++ sflash->numblocks = e->numblocks; ++ sflash->size = sflash->blocksize * sflash->numblocks; ++ sflash->present = true; ++ ++ pr_info("Found %s serial flash (blocksize: 0x%X, blocks: %d)\n", ++ e->name, e->blocksize, e->numblocks); ++ ++ /* Prepare platform device, but don't register it yet. It's too early, ++ * malloc (required by device_private_init) is not available yet. */ ++ ssb_sflash_dev.resource[0].end = ssb_sflash_dev.resource[0].start + ++ sflash->size; ++ ssb_sflash_dev.dev.platform_data = sflash; ++ + pr_err("Serial flash support is not implemented yet!\n"); + + return -ENOTSUPP; @@ -615,7 +853,7 @@ } --- /dev/null +++ b/drivers/ssb/driver_gpio.c -@@ -0,0 +1,176 @@ +@@ -0,0 +1,210 @@ +/* + * Sonics Silicon Backplane + * GPIO driver @@ -692,6 +930,16 @@ + 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; @@ -704,6 +952,7 @@ + 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 @@ -752,6 +1001,16 @@ + 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; @@ -762,6 +1021,7 @@ + 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 @@ -792,9 +1052,88 @@ + + 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 -@@ -178,9 +178,9 @@ static void ssb_mips_serial_init(struct +@@ -10,6 +10,7 @@ + + #include <linux/ssb/ssb.h> + ++#include <linux/mtd/physmap.h> + #include <linux/serial.h> + #include <linux/serial_core.h> + #include <linux/serial_reg.h> +@@ -17,6 +18,25 @@ + + #include "ssb_private.h" + ++static const char * const part_probes[] = { "bcm47xxpart", NULL }; ++ ++static struct physmap_flash_data ssb_pflash_data = { ++ .part_probe_types = part_probes, ++}; ++ ++static struct resource ssb_pflash_resource = { ++ .name = "ssb_pflash", ++ .flags = IORESOURCE_MEM, ++}; ++ ++struct platform_device ssb_pflash_dev = { ++ .name = "physmap-flash", ++ .dev = { ++ .platform_data = &ssb_pflash_data, ++ }, ++ .resource = &ssb_pflash_resource, ++ .num_resources = 1, ++}; + + static inline u32 mips_read32(struct ssb_mipscore *mcore, + u16 offset) +@@ -147,21 +167,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 +199,9 @@ static void ssb_mips_serial_init(struct { struct ssb_bus *bus = mcore->dev->bus; @@ -806,9 +1145,11 @@ mcore->nr_serial_ports = ssb_chipco_serial_init(&bus->chipco, mcore->serial_ports); else mcore->nr_serial_ports = 0; -@@ -190,16 +190,33 @@ static void ssb_mips_flash_detect(struct +@@ -189,17 +210,42 @@ static void ssb_mips_serial_init(struct + static void ssb_mips_flash_detect(struct ssb_mipscore *mcore) { struct ssb_bus *bus = mcore->dev->bus; ++ struct ssb_pflash *pflash = &mcore->pflash; - mcore->flash_buswidth = 2; - if (bus->chipco.dev) { @@ -816,11 +1157,11 @@ - mcore->flash_window_size = 0x02000000; + /* When there is no chipcommon on the bus there is 4MB flash */ + if (!ssb_chipco_available(&bus->chipco)) { -+ mcore->pflash.present = true; -+ mcore->pflash.buswidth = 2; -+ mcore->pflash.window = SSB_FLASH1; -+ mcore->pflash.window_size = SSB_FLASH1_SZ; -+ return; ++ pflash->present = true; ++ pflash->buswidth = 2; ++ pflash->window = SSB_FLASH1; ++ pflash->window_size = SSB_FLASH1_SZ; ++ goto ssb_pflash; + } + + /* There is ChipCommon, so use it to read info about flash */ @@ -832,23 +1173,30 @@ + break; + case SSB_CHIPCO_FLASHT_PARA: + pr_debug("Found parallel flash\n"); -+ mcore->pflash.present = true; -+ mcore->pflash.window = SSB_FLASH2; -+ mcore->pflash.window_size = SSB_FLASH2_SZ; ++ pflash->present = true; ++ pflash->window = SSB_FLASH2; ++ pflash->window_size = SSB_FLASH2_SZ; if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG) & SSB_CHIPCO_CFG_DS16) == 0) - mcore->flash_buswidth = 1; - } else { - mcore->flash_window = 0x1fc00000; - mcore->flash_window_size = 0x00400000; -+ mcore->pflash.buswidth = 1; ++ pflash->buswidth = 1; + else -+ mcore->pflash.buswidth = 2; ++ pflash->buswidth = 2; + break; ++ } ++ ++ssb_pflash: ++ if (pflash->present) { ++ ssb_pflash_data.width = pflash->buswidth; ++ ssb_pflash_resource.start = pflash->window; ++ ssb_pflash_resource.end = pflash->window + pflash->window_size; } } -@@ -208,9 +225,12 @@ u32 ssb_cpu_clock(struct ssb_mipscore *m +@@ -208,9 +254,12 @@ u32 ssb_cpu_clock(struct ssb_mipscore *m struct ssb_bus *bus = mcore->dev->bus; u32 pll_type, n, m, rate = 0; @@ -863,7 +1211,16 @@ ssb_chipco_get_clockcpu(&bus->chipco, &pll_type, &n, &m); } else return 0; -@@ -246,9 +266,9 @@ void ssb_mipscore_init(struct ssb_mipsco +@@ -238,7 +287,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 +295,9 @@ void ssb_mipscore_init(struct ssb_mipsco hz = 100000000; ns = 1000000000 / hz; @@ -875,6 +1232,71 @@ 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 +335,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 @@ @@ -891,7 +1313,7 @@ #include <linux/ssb/ssb.h> #include <linux/ssb/ssb_embedded.h> #include <linux/ssb/ssb_driver_pci.h> -@@ -32,6 +34,39 @@ int ssb_watchdog_timer_set(struct ssb_bu +@@ -32,6 +34,38 @@ int ssb_watchdog_timer_set(struct ssb_bu } EXPORT_SYMBOL(ssb_watchdog_timer_set); @@ -918,9 +1340,8 @@ + bus->busnumber, &wdt, + sizeof(wdt)); + if (IS_ERR(pdev)) { -+ ssb_dprintk(KERN_INFO PFX -+ "can not register watchdog device, err: %li\n", -+ PTR_ERR(pdev)); ++ ssb_dbg("can not register watchdog device, err: %li\n", ++ PTR_ERR(pdev)); + return PTR_ERR(pdev); + } + @@ -941,49 +1362,18 @@ #include <linux/ssb/ssb.h> #include <linux/ssb/ssb_regs.h> #include <linux/ssb/ssb_driver_gige.h> -@@ -140,19 +141,6 @@ static void ssb_device_put(struct ssb_de - put_device(dev->dev); - } - --static inline struct ssb_driver *ssb_driver_get(struct ssb_driver *drv) --{ -- if (drv) -- get_driver(&drv->drv); -- return drv; --} -- --static inline void ssb_driver_put(struct ssb_driver *drv) --{ -- if (drv) -- put_driver(&drv->drv); --} -- - static int ssb_device_resume(struct device *dev) - { - struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); -@@ -250,11 +238,9 @@ int ssb_devices_freeze(struct ssb_bus *b - ssb_device_put(sdev); - continue; - } -- sdrv = ssb_driver_get(drv_to_ssb_drv(sdev->dev->driver)); -- if (!sdrv || SSB_WARN_ON(!sdrv->remove)) { -- ssb_device_put(sdev); -+ sdrv = drv_to_ssb_drv(sdev->dev->driver); -+ if (SSB_WARN_ON(!sdrv->remove)) - continue; -- } - sdrv->remove(sdev); - ctx->device_frozen[i] = 1; - } -@@ -293,7 +279,6 @@ int ssb_devices_thaw(struct ssb_freeze_c - dev_name(sdev->dev)); +@@ -289,8 +290,8 @@ 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); - } - -@@ -449,6 +434,11 @@ static void ssb_devices_unregister(struc + ssb_driver_put(sdrv); +@@ -449,10 +450,23 @@ static void ssb_devices_unregister(struc if (sdev->dev) device_unregister(sdev->dev); } @@ -995,7 +1385,63 @@ } void ssb_bus_unregister(struct ssb_bus *bus) -@@ -577,6 +567,8 @@ static int __devinit ssb_attach_queued_b + { ++ 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 +512,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 +551,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; +@@ -550,6 +561,22 @@ static int ssb_devices_register(struct s + dev_idx++; + } + ++#ifdef CONFIG_SSB_DRIVER_MIPS ++ if (bus->mipscore.pflash.present) { ++ err = platform_device_register(&ssb_pflash_dev); ++ if (err) ++ pr_err("Error registering parallel flash\n"); ++ } ++#endif ++ ++#ifdef CONFIG_SSB_SFLASH ++ if (bus->mipscore.sflash.present) { ++ err = platform_device_register(&ssb_sflash_dev); ++ if (err) ++ pr_err("Error registering serial flash\n"); ++ } ++#endif ++ + return 0; + error: + /* Unwind the already registered devices. */ +@@ -577,6 +604,8 @@ static int __devinit ssb_attach_queued_b if (err) goto error; ssb_pcicore_init(&bus->pcicore); @@ -1004,7 +1450,7 @@ ssb_bus_may_powerdown(bus); err = ssb_devices_register(bus); -@@ -812,7 +804,14 @@ static int __devinit ssb_bus_register(st +@@ -812,7 +841,13 @@ static int __devinit ssb_bus_register(st if (err) goto err_pcmcia_exit; ssb_chipcommon_init(&bus->chipco); @@ -1012,14 +1458,62 @@ ssb_mipscore_init(&bus->mipscore); + err = ssb_gpio_init(bus); + if (err == -ENOTSUPP) -+ ssb_dprintk(KERN_DEBUG PFX "GPIO driver not activated\n"); ++ ssb_dbg("GPIO driver not activated\n"); + else if (err) -+ ssb_dprintk(KERN_ERR PFX -+ "Error registering GPIO driver: %i\n", err); ++ ssb_dbg("Error registering GPIO driver: %i\n", err); err = ssb_fetch_invariants(bus, get_invariants); if (err) { ssb_bus_may_powerdown(bus); -@@ -1094,6 +1093,9 @@ u32 ssb_clockspeed(struct ssb_bus *bus) +@@ -863,11 +898,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 +923,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 +946,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 +966,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 +1129,9 @@ u32 ssb_clockspeed(struct ssb_bus *bus) u32 plltype; u32 clkctl_n, clkctl_m; @@ -1029,7 +1523,7 @@ if (ssb_extif_available(&bus->extif)) ssb_extif_get_clockcontrol(&bus->extif, &plltype, &clkctl_n, &clkctl_m); -@@ -1131,8 +1133,7 @@ static u32 ssb_tmslow_reject_bitmask(str +@@ -1131,8 +1169,7 @@ static u32 ssb_tmslow_reject_bitmask(str case SSB_IDLOW_SSBREV_27: /* same here */ return SSB_TMSLOW_REJECT; /* this is a guess */ default: @@ -1039,9 +1533,68 @@ } return (SSB_TMSLOW_REJECT | SSB_TMSLOW_REJECT_23); } +@@ -1324,7 +1361,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 +1384,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 +1492,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) @@ -1060,7 +1613,71 @@ static inline u8 ssb_crc8(u8 crc, u8 data) { -@@ -327,11 +339,25 @@ static s8 r123_extract_antgain(u8 sprom_ +@@ -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 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; } @@ -1081,25 +1698,49 @@ + static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) { - int i; - u16 v; +- int i; +- u16 v; - s8 gain; u16 loc[3]; if (out->revision == 3) /* rev 3 moved MAC */ -@@ -361,8 +387,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, -@@ -386,24 +413,19 @@ 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); @@ -1135,11 +1776,31 @@ } /* Revs 4 5 and 8 have partially shared layout */ -@@ -464,14 +486,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); @@ -1155,7 +1816,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 +529,14 @@ static void sprom_extract_r45(struct ssb +@@ -504,16 +524,14 @@ static void sprom_extract_r45(struct ssb } /* Extract the antenna gain values. */ @@ -1176,12 +1837,12 @@ sprom_extract_r458(out, in); -@@ -523,14 +546,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 @@ -1190,18 +1851,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 +627,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. */ @@ -1254,7 +1918,7 @@ /* Extract FEM info */ SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G, -@@ -630,6 +691,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); @@ -1318,7 +1982,79 @@ sprom_extract_r458(out, in); /* TODO - get remaining rev 8 stuff needed */ -@@ -759,7 +877,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; @@ -1326,9 +2062,108 @@ } int ssb_pci_get_invariants(struct ssb_bus *bus, +--- a/drivers/ssb/pcihost_wrapper.c ++++ b/drivers/ssb/pcihost_wrapper.c +@@ -38,7 +38,7 @@ static int ssb_pcihost_resume(struct pci + struct ssb_bus *ssb = pci_get_drvdata(dev); + int err; + +- pci_set_power_state(dev, 0); ++ pci_set_power_state(dev, PCI_D0); + err = pci_enable_device(dev); + if (err) + return err; --- 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"); @@ -1347,6 +2182,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) @@ -1358,16 +2228,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 @@ -1389,9 +2336,36 @@ break; case SSB_SDIO_CIS_BFLAGS: GOTO_ERROR_ON((tuple->size != 3) && +--- a/drivers/ssb/sprom.c ++++ b/drivers/ssb/sprom.c +@@ -54,7 +54,7 @@ static int hex2sprom(u16 *sprom, const c + while (cnt < sprom_size_words) { + memcpy(tmp, dump, 4); + dump += 4; +- err = strict_strtoul(tmp, 16, &parsed); ++ err = kstrtoul(tmp, 16, &parsed); + if (err) + return err; + sprom[cnt++] = swab16((u16)parsed); +@@ -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 -@@ -3,6 +3,7 @@ +@@ -3,21 +3,33 @@ #include <linux/ssb/ssb.h> #include <linux/types.h> @@ -1399,7 +2373,37 @@ #define PFX "ssb: " -@@ -207,4 +208,66 @@ static inline void b43_pci_ssb_bridge_ex + + #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,79 @@ static inline void b43_pci_ssb_bridge_ex } #endif /* CONFIG_SSB_B43_PCI_BRIDGE */ @@ -1423,6 +2427,14 @@ +} +#endif /* CONFIG_SSB_SFLASH */ + ++#ifdef CONFIG_SSB_DRIVER_MIPS ++extern struct platform_device ssb_pflash_dev; ++#endif ++ ++#ifdef CONFIG_SSB_SFLASH ++extern struct platform_device ssb_sflash_dev; ++#endif ++ +#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); @@ -1458,11 +2470,16 @@ + +#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_ */ @@ -1479,7 +2496,7 @@ #include <linux/ssb/ssb_regs.h> -@@ -16,6 +18,12 @@ struct pcmcia_device; +@@ -16,19 +18,28 @@ struct pcmcia_device; struct ssb_bus; struct ssb_driver; @@ -1491,8 +2508,14 @@ + struct ssb_sprom { u8 revision; - u8 il0mac[6]; /* MAC address for 802.11b/g */ -@@ -26,9 +34,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. */ @@ -1649,7 +2672,72 @@ /* Vendor-ID values */ #define SSB_VENDOR_BROADCOM 0x4243 -@@ -354,7 +434,11 @@ struct ssb_bus { +@@ -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; @@ -1813,9 +2901,49 @@ #include <linux/pci.h> #include <linux/spinlock.h> +@@ -96,21 +97,16 @@ static inline bool ssb_gige_must_flush_p + return 0; + } + +-#ifdef CONFIG_BCM47XX +-#include <asm/mach-bcm47xx/nvram.h> + /* 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 -@@ -13,6 +13,12 @@ struct ssb_serial_port { +@@ -13,6 +13,24 @@ struct ssb_serial_port { unsigned int reg_shift; }; @@ -1825,10 +2953,22 @@ + u32 window; + u32 window_size; +}; ++ ++#ifdef CONFIG_SSB_SFLASH ++struct ssb_sflash { ++ bool present; ++ u32 window; ++ u32 blocksize; ++ u16 numblocks; ++ u32 size; ++ ++ void *priv; ++}; ++#endif struct ssb_mipscore { struct ssb_device *dev; -@@ -20,9 +26,7 @@ struct ssb_mipscore { +@@ -20,9 +38,10 @@ struct ssb_mipscore { int nr_serial_ports; struct ssb_serial_port serial_ports[4]; @@ -1836,12 +2976,35 @@ - u32 flash_window; - u32 flash_window_size; + struct ssb_pflash pflash; ++#ifdef CONFIG_SSB_SFLASH ++ struct ssb_sflash sflash; ++#endif }; extern void ssb_mipscore_init(struct ssb_mipscore *mcore); +@@ -41,6 +60,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 @@ -1849,7 +3012,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 */ @@ -1857,7 +3020,7 @@ #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) */ -@@ -287,11 +289,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 */ @@ -1874,7 +3037,7 @@ #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 +391,11 @@ +@@ -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 @@ -1886,7 +3049,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 @@ -1900,7 +3063,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 */ @@ -1908,7 +3071,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 @@ -1984,7 +3147,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 diff --git a/target/linux/generic/patches-3.3/025-bcma_backport.patch b/target/linux/generic/patches-3.3/025-bcma_backport.patch index d3f9fb0..05d461d 100644 --- a/target/linux/generic/patches-3.3/025-bcma_backport.patch +++ b/target/linux/generic/patches-3.3/025-bcma_backport.patch @@ -1,6 +1,21 @@ +--- 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/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 +24,7 @@ help PCI core hostmode operation (external PCI bus). -@@ -46,6 +46,33 @@ config BCMA_DRIVER_MIPS +@@ -46,6 +47,33 @@ config BCMA_DRIVER_MIPS If unsure, say N @@ -60,7 +75,7 @@ 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 @@ -77,11 +92,13 @@ /* 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, -@@ -22,6 +31,8 @@ int __init bcma_bus_early_register(struc +@@ -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 @@ -90,7 +107,11 @@ /* scan.c */ int bcma_bus_scan(struct bcma_bus *bus); -@@ -39,8 +50,32 @@ void bcma_chipco_serial_init(struct bcma +@@ -36,11 +49,36 @@ int bcma_sprom_get(struct bcma_bus *bus) + /* driver_chipcommon.c */ + #ifdef CONFIG_BCMA_DRIVER_MIPS + void bcma_chipco_serial_init(struct bcma_drv_cc *cc); ++extern struct platform_device bcma_pflash_dev; #endif /* CONFIG_BCMA_DRIVER_MIPS */ /* driver_chipcommon_pmu.c */ @@ -125,7 +146,7 @@ #ifdef CONFIG_BCMA_HOST_PCI /* host_pci.c */ -@@ -48,8 +83,24 @@ extern int __init bcma_host_pci_init(voi +@@ -48,8 +86,29 @@ extern int __init bcma_host_pci_init(voi extern void __exit bcma_host_pci_exit(void); #endif /* CONFIG_BCMA_HOST_PCI */ @@ -143,25 +164,75 @@ +#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 <linux/export.h> + #include <linux/bcma/bcma.h> + ++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); -@@ -64,7 +65,7 @@ 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); @@ -170,7 +241,7 @@ for (i = 0; i < 1500; i++) { if (bcma_read32(core, BCMA_CLKCTLST) & BCMA_CLKCTLST_HAVEHT) { -@@ -74,10 +75,10 @@ void bcma_core_set_clockmode(struct bcma +@@ -74,10 +97,10 @@ void bcma_core_set_clockmode(struct bcma udelay(10); } if (i) @@ -183,7 +254,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) @@ -191,11 +262,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: @@ -224,7 +301,7 @@ #include <linux/bcma/bcma.h> static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, -@@ -22,20 +25,120 @@ static inline u32 bcma_cc_write32_masked +@@ -22,29 +25,136 @@ static inline u32 bcma_cc_write32_masked return value; } @@ -347,9 +424,19 @@ + 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); -@@ -44,7 +147,7 @@ void bcma_core_chipcommon_init(struct bc +- 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) @@ -358,7 +445,7 @@ if (cc->core->id.rev >= 16) { if (cc->core->bus->sprom.leddc_on_time && -@@ -56,15 +159,33 @@ void bcma_core_chipcommon_init(struct bc +@@ -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))); } @@ -395,7 +482,7 @@ } void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value) -@@ -84,28 +205,99 @@ u32 bcma_chipco_gpio_in(struct bcma_drv_ +@@ -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) { @@ -500,7 +587,7 @@ } #ifdef CONFIG_BCMA_DRIVER_MIPS -@@ -118,8 +310,7 @@ void bcma_chipco_serial_init(struct bcma +@@ -118,8 +317,7 @@ void bcma_chipco_serial_init(struct bcma struct bcma_serial_port *ports = cc->serial_ports; if (ccrev >= 11 && ccrev != 15) { @@ -510,7 +597,7 @@ if (ccrev >= 21) { /* Turn off UART clock before switching clocksource. */ bcma_cc_write32(cc, BCMA_CC_CORECTL, -@@ -137,8 +328,7 @@ void bcma_chipco_serial_init(struct bcma +@@ -137,12 +335,11 @@ void bcma_chipco_serial_init(struct bcma | BCMA_CC_CORECTL_UARTCLKEN); } } else { @@ -520,6 +607,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); --- /dev/null +++ b/drivers/bcma/driver_chipcommon_nflash.c @@ -0,0 +1,44 @@ @@ -530,11 +622,11 @@ + * Licensed under the GNU/GPL. See COPYING for details. + */ + ++#include "bcma_private.h" ++ +#include <linux/platform_device.h> +#include <linux/bcma/bcma.h> + -+#include "bcma_private.h" -+ +struct platform_device bcma_nflash_dev = { + .name = "bcma_nflash", + .num_resources = 0, @@ -546,7 +638,7 @@ + struct bcma_bus *bus = cc->core->bus; + + if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4706 && -+ cc->core->id.rev != 0x38) { ++ cc->core->id.rev != 38) { + bcma_err(bus, "NAND flash on unsupported board!\n"); + return -ENOTSUPP; + } @@ -594,29 +686,121 @@ void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value) { -@@ -54,38 +56,19 @@ void bcma_chipco_regctl_maskset(struct b +@@ -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) { @@ -627,7 +811,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); @@ -636,16 +838,16 @@ } /* Set the resource masks. */ -@@ -93,22 +76,12 @@ 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: @@ -664,7 +866,7 @@ } /* Disable to allow reading SPROM. Don't know the adventages of enabling it. */ -@@ -122,51 +95,69 @@ 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; @@ -751,14 +953,14 @@ if (cc->pmu.rev == 1) bcma_cc_mask32(cc, BCMA_CC_PMU_CTL, ~BCMA_CC_PMU_CTL_NOILPONW); -@@ -174,37 +165,47 @@ void bcma_pmu_init(struct bcma_drv_cc *c +@@ -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); @@ -817,7 +1019,7 @@ } return BCMA_CC_PMU_ALP_CLOCK; } -@@ -212,7 +213,7 @@ u32 bcma_pmu_alp_clock(struct bcma_drv_c +@@ -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. */ @@ -826,7 +1028,7 @@ { u32 tmp, div, ndiv, p1, p2, fc; struct bcma_bus *bus = cc->core->bus; -@@ -221,7 +222,8 @@ static u32 bcma_pmu_clock(struct bcma_dr +@@ -221,7 +345,8 @@ static u32 bcma_pmu_clock(struct bcma_dr BUG_ON(!m || m > 4); @@ -836,7 +1038,7 @@ /* Detect failure in clock setting */ tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); if (tmp & 0x40000) -@@ -240,60 +242,95 @@ 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 */ @@ -880,7 +1082,7 @@ + /* query bus clock frequency for PMU-enabled chipcommon */ -u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc) -+static u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc) ++u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc) { struct bcma_bus *bus = cc->core->bus; @@ -928,6 +1130,7 @@ } return BCMA_CC_PMU_HT_CLOCK; } ++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) @@ -958,7 +1161,7 @@ pll = BCMA_CC_PMU5357_MAINPLL_PLL0; break; default: -@@ -301,10 +338,189 @@ u32 bcma_pmu_get_clockcpu(struct bcma_dr +@@ -301,10 +462,189 @@ u32 bcma_pmu_get_clockcpu(struct bcma_dr break; } @@ -1162,11 +1365,11 @@ + * Licensed under the GNU/GPL. See COPYING for details. + */ + ++#include "bcma_private.h" ++ +#include <linux/platform_device.h> +#include <linux/bcma/bcma.h> + -+#include "bcma_private.h" -+ +static struct resource bcma_sflash_resource = { + .name = "bcma_sflash", + .start = BCMA_SOC_FLASH2, @@ -1187,7 +1390,7 @@ + u16 numblocks; +}; + -+static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { ++static const struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { + { "M25P20", 0x11, 0x10000, 4, }, + { "M25P40", 0x12, 0x10000, 8, }, + @@ -1198,7 +1401,7 @@ + { 0 }, +}; + -+static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { ++static const struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { + { "SST25WF512", 1, 0x1000, 16, }, + { "SST25VF512", 0x48, 0x1000, 16, }, + { "SST25WF010", 2, 0x1000, 32, }, @@ -1216,7 +1419,7 @@ + { 0 }, +}; + -+static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { ++static const struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { + { "AT45DB011", 0xc, 256, 512, }, + { "AT45DB021", 0x14, 256, 1024, }, + { "AT45DB041", 0x1c, 256, 2048, }, @@ -1246,7 +1449,7 @@ +{ + struct bcma_bus *bus = cc->core->bus; + struct bcma_sflash *sflash = &cc->sflash; -+ struct bcma_sflash_tbl_e *e; ++ const struct bcma_sflash_tbl_e *e; + u32 id, id2; + + switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { @@ -1339,7 +1542,7 @@ +} --- /dev/null +++ b/drivers/bcma/driver_gpio.c -@@ -0,0 +1,98 @@ +@@ -0,0 +1,114 @@ +/* + * Broadcom specific AMBA + * GPIO driver @@ -1415,6 +1618,16 @@ + 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; @@ -1427,6 +1640,7 @@ + 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 @@ -1438,9 +1652,44 @@ + + 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 @@ +@@ -14,23 +14,45 @@ + + #include <linux/bcma/bcma.h> + ++#include <linux/mtd/physmap.h> ++#include <linux/platform_device.h> + #include <linux/serial.h> + #include <linux/serial_core.h> + #include <linux/serial_reg.h> + #include <linux/time.h> + ++static const char * const part_probes[] = { "bcm47xxpart", NULL }; ++ ++static struct physmap_flash_data bcma_pflash_data = { ++ .part_probe_types = part_probes, ++}; ++ ++static struct resource bcma_pflash_resource = { ++ .name = "bcma_pflash", ++ .flags = IORESOURCE_MEM, ++}; ++ ++struct platform_device bcma_pflash_dev = { ++ .name = "physmap-flash", ++ .dev = { ++ .platform_data = &bcma_pflash_data, ++ }, ++ .resource = &bcma_pflash_resource, ++ .num_resources = 1, ++}; ++ /* The 47162a0 hangs when reading MIPS DMP registers registers */ static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev) { @@ -1460,7 +1709,7 @@ dev->bus->chipinfo.pkg == 11 && dev->id.id == BCMA_CORE_USB20_HOST; } -@@ -74,11 +74,16 @@ static u32 bcma_core_mips_irqflag(struct +@@ -74,28 +96,41 @@ static u32 bcma_core_mips_irqflag(struct return dev->core_index; flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30); @@ -1476,9 +1725,11 @@ + * If disabled, 5 is returned. + * If not supported, 6 is returned. */ - unsigned int bcma_core_mips_irq(struct bcma_device *dev) +-unsigned int bcma_core_mips_irq(struct bcma_device *dev) ++static unsigned int bcma_core_mips_irq(struct bcma_device *dev) { -@@ -87,13 +92,15 @@ unsigned int bcma_core_mips_irq(struct b + struct bcma_device *mdev = dev->bus->drv_mips.core; + u32 irqflag; unsigned int irq; irqflag = bcma_core_mips_irqflag(dev); @@ -1493,10 +1744,19 @@ - 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_mips_irq); ++EXPORT_SYMBOL(bcma_core_irq); -@@ -114,8 +121,8 @@ static void bcma_core_mips_set_irq(struc + static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq) + { +@@ -114,8 +149,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)); @@ -1507,7 +1767,7 @@ /* assign the new one */ if (irq == 0) { -@@ -123,17 +130,17 @@ static void bcma_core_mips_set_irq(struc +@@ -123,17 +158,17 @@ static void bcma_core_mips_set_irq(struc bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) | (1 << irqflag)); } else { @@ -1530,7 +1790,7 @@ bcma_core_mips_set_irq(core, 0); break; } -@@ -143,15 +150,31 @@ static void bcma_core_mips_set_irq(struc +@@ -143,15 +178,31 @@ static void bcma_core_mips_set_irq(struc 1 << irqflag); } @@ -1565,7 +1825,7 @@ for (i = 0; i <= 6; i++) printk(" %s%s", irq_name[i], i == irq ? "*" : " "); printk("\n"); -@@ -161,7 +184,7 @@ static void bcma_core_mips_dump_irq(stru +@@ -161,7 +212,7 @@ static void bcma_core_mips_dump_irq(stru { struct bcma_device *core; @@ -1574,7 +1834,7 @@ bcma_core_mips_print_irq(core, bcma_core_mips_irq(core)); } } -@@ -171,9 +194,9 @@ u32 bcma_cpu_clock(struct bcma_drv_mips +@@ -171,9 +222,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) @@ -1586,11 +1846,12 @@ return 0; } EXPORT_SYMBOL(bcma_cpu_clock); -@@ -181,76 +204,109 @@ EXPORT_SYMBOL(bcma_cpu_clock); +@@ -181,25 +232,81 @@ EXPORT_SYMBOL(bcma_cpu_clock); static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore) { struct bcma_bus *bus = mcore->core->bus; + struct bcma_drv_cc *cc = &bus->drv_cc; ++ struct bcma_pflash *pflash = &cc->pflash; - switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) { + switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { @@ -1605,18 +1866,23 @@ - bus->drv_cc.pflash.window = 0x1c000000; - bus->drv_cc.pflash.window_size = 0x02000000; + bcma_debug(bus, "Found parallel flash\n"); -+ cc->pflash.present = true; -+ cc->pflash.window = BCMA_SOC_FLASH2; -+ cc->pflash.window_size = BCMA_SOC_FLASH2_SZ; ++ pflash->present = true; ++ pflash->window = BCMA_SOC_FLASH2; ++ pflash->window_size = BCMA_SOC_FLASH2_SZ; - if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) & + if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) & BCMA_CC_FLASH_CFG_DS) == 0) - bus->drv_cc.pflash.buswidth = 1; -+ cc->pflash.buswidth = 1; ++ pflash->buswidth = 1; else - bus->drv_cc.pflash.buswidth = 2; -+ cc->pflash.buswidth = 2; ++ pflash->buswidth = 2; ++ ++ bcma_pflash_data.width = pflash->buswidth; ++ bcma_pflash_resource.start = pflash->window; ++ bcma_pflash_resource.end = pflash->window + pflash->window_size; ++ break; default: - pr_err("flash not supported.\n"); @@ -1629,9 +1895,9 @@ + bcma_debug(bus, "Found NAND flash\n"); + bcma_nflash_init(cc); + } - } - } - ++ } ++} ++ +void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) +{ + struct bcma_bus *bus = mcore->core->bus; @@ -1645,21 +1911,43 @@ + mcore->early_setup_done = true; +} + - void bcma_core_mips_init(struct bcma_drv_mips *mcore) - { - struct bcma_bus *bus; ++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,48 +316,59 @@ void bcma_core_mips_init(struct bcma_drv struct bcma_device *core; bus = mcore->core->bus; - pr_info("Initializing MIPS core...\n"); + if (mcore->setup_done) + return; -+ -+ bcma_debug(bus, "Initializing MIPS core...\n"); - if (!mcore->setup_done) - mcore->assigned_irqs = 1; -+ bcma_core_mips_early_init(mcore); ++ bcma_debug(bus, "Initializing MIPS core...\n"); - /* Assign IRQs to all cores on the bus */ - list_for_each_entry_reverse(core, &bus->cores, list) { @@ -1689,6 +1977,10 @@ - bcma_core_mips_set_irq(core, - mcore->assigned_irqs++); - break; ++ bcma_core_mips_early_init(mcore); ++ ++ bcma_fix_i2s_irqflag(bus); ++ + switch (bus->chipinfo.id) { + case BCMA_CHIP_ID_BCM4716: + case BCMA_CHIP_ID_BCM4748: @@ -1725,7 +2017,7 @@ + break; + default: + list_for_each_entry(core, &bus->cores, list) { -+ core->irq = bcma_core_mips_irq(core) + 2; ++ core->irq = bcma_core_irq(core); } + bcma_err(bus, + "Unknown device (0x%x) found, can not configure IRQs\n", @@ -2105,7 +2397,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,600 @@ +@@ -2,13 +2,616 @@ * Broadcom specific AMBA * PCI Core in hostmode * @@ -2186,13 +2478,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; @@ -2203,19 +2493,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 { @@ -2228,11 +2518,9 @@ + goto out; + + if (mips_busprobe32(val, mmio)) { -+ val = 0xffffffff; ++ val = 0xFFFFFFFF; + goto unmap; + } -+ -+ val = readl(mmio); + } + val >>= (8 * (off & 3)); + @@ -2254,13 +2542,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; + @@ -2268,16 +2558,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); @@ -2289,19 +2585,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; @@ -2309,13 +2603,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); + @@ -2386,7 +2681,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 */ @@ -2511,6 +2806,8 @@ + 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; @@ -2536,7 +2833,7 @@ + /* Reset RC */ + usleep_range(3000, 5000); + pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE); -+ usleep_range(1000, 2000); ++ msleep(50); + pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST | + BCMA_CORE_PCI_CTL_RST_OE); + @@ -2598,6 +2895,17 @@ + + 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)); @@ -2686,7 +2994,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; @@ -2705,7 +3013,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 @@ -2799,7 +3107,7 @@ static int bcma_host_pci_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); -@@ -257,17 +261,20 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bc +@@ -257,17 +261,21 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bc bcma_host_pci_resume); #define BCMA_PM_OPS (&bcma_pm_ops) @@ -2819,10 +3127,11 @@ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, + { 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 +284,7 @@ static struct pci_driver bcma_pci_bridge +@@ -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, @@ -2880,7 +3189,7 @@ { struct bcma_device *core; -@@ -65,6 +79,19 @@ static struct bcma_device *bcma_find_cor +@@ -65,6 +79,38 @@ static struct bcma_device *bcma_find_cor } return NULL; } @@ -2897,10 +3206,29 @@ + } + 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 +111,18 @@ static int bcma_register_cores(struct bc +@@ -84,16 +130,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) { @@ -2913,6 +3241,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); @@ -2920,7 +3253,7 @@ switch (bus->hosttype) { case BCMA_HOSTTYPE_PCI: -@@ -111,41 +140,90 @@ static int bcma_register_cores(struct bc +@@ -111,41 +164,98 @@ static int bcma_register_cores(struct bc err = device_register(&core->dev); if (err) { @@ -2935,6 +3268,14 @@ dev_id++; } ++#ifdef CONFIG_BCMA_DRIVER_MIPS ++ if (bus->drv_cc.pflash.present) { ++ err = platform_device_register(&bcma_pflash_dev); ++ if (err) ++ bcma_err(bus, "Error registering parallel flash\n"); ++ } ++#endif ++ +#ifdef CONFIG_BCMA_SFLASH + if (bus->drv_cc.sflash.present) { + err = platform_device_register(&bcma_sflash_dev); @@ -3018,7 +3359,7 @@ if (core) { bus->drv_cc.core = core; bcma_core_chipcommon_init(&bus->drv_cc); -@@ -159,30 +237,47 @@ int bcma_bus_register(struct bcma_bus *b +@@ -159,30 +269,54 @@ int bcma_bus_register(struct bcma_bus *b } /* Init PCIE core */ @@ -3063,6 +3404,13 @@ 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); @@ -3076,7 +3424,7 @@ } int __init bcma_bus_early_register(struct bcma_bus *bus, -@@ -196,14 +291,14 @@ int __init bcma_bus_early_register(struc +@@ -196,14 +330,14 @@ int __init bcma_bus_early_register(struc bcma_init_bus(bus); match.manuf = BCMA_MANUF_BCM; @@ -3093,7 +3441,7 @@ return -1; } -@@ -215,25 +310,25 @@ int __init bcma_bus_early_register(struc +@@ -215,25 +349,25 @@ int __init bcma_bus_early_register(struc /* Scan for mips core */ err = bcma_bus_scan_early(bus, &match, core_mips); if (err) { @@ -3126,7 +3474,7 @@ return 0; } -@@ -259,8 +354,7 @@ int bcma_bus_resume(struct bcma_bus *bus +@@ -259,8 +393,7 @@ int bcma_bus_resume(struct bcma_bus *bus struct bcma_device *core; /* Init CC core */ @@ -3192,8 +3540,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) @@ -3241,7 +3593,74 @@ 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; } @@ -3259,7 +3678,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) { @@ -3280,7 +3699,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; } @@ -3304,7 +3723,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) @@ -3313,7 +3732,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; @@ -3321,7 +3740,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); @@ -3337,7 +3756,7 @@ bus->init_done = true; } -@@ -392,9 +460,12 @@ 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) { @@ -3352,7 +3771,7 @@ INIT_LIST_HEAD(&core->list); core->bus = bus; -@@ -409,25 +480,28 @@ int bcma_bus_scan(struct bcma_bus *bus) +@@ -409,25 +482,28 @@ int bcma_bus_scan(struct bcma_bus *bus) } else if (err == -ESPIPE) { break; } @@ -3389,7 +3808,7 @@ } int __init bcma_bus_scan_early(struct bcma_bus *bus, -@@ -467,21 +541,21 @@ int __init bcma_bus_scan_early(struct bc +@@ -467,21 +543,21 @@ int __init bcma_bus_scan_early(struct bc else if (err == -ESPIPE) break; else if (err < 0) @@ -3440,7 +3859,7 @@ * Licensed under the GNU/GPL. See COPYING for details. */ -@@ -14,7 +16,57 @@ +@@ -14,18 +16,68 @@ #include <linux/dma-mapping.h> #include <linux/slab.h> @@ -3499,7 +3918,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. **************************************************/ @@ -3529,6 +4029,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 @@ -3536,14 +4039,14 @@ + 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,107 +216,390 @@ 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); ++ SPEX(board_type, SSB_SPROM1_SPID, ~0, 0); + + SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0, + SSB_SPROM4_TXPID2G0_SHIFT); @@ -3620,71 +4123,7 @@ + SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0); + SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~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(fem.ghz2.tssipos, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_TSSIPOS, + SSB_SROM8_FEM_TSSIPOS_SHIFT); + SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_EXTPA_GAIN, @@ -3866,7 +4305,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; + } @@ -3892,7 +4395,7 @@ + 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 */ @@ -3941,7 +4444,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; @@ -3950,7 +4456,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 @@ -3972,11 +4482,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) @@ -3987,24 +4492,45 @@ - * 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); -- if (err) +- bcma_sprom_extract_r8(bus, sprom); + if (err) { -+ bcma_warn(bus, "invalid sprom read from the PCIe card, try to use fallback sprom\n"); ++ 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); - goto out; ++ } else { ++ bcma_sprom_extract_r8(bus, sprom); ++ kfree(sprom); + } - bcma_sprom_extract_r8(bus, sprom); - +-out: +- kfree(sprom); + return err; + } --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h @@ -7,9 +7,10 @@ @@ -4045,17 +4571,21 @@ #define BCMA_CORE_INVALID 0x700 #define BCMA_CORE_CHIPCOMMON 0x800 #define BCMA_CORE_ILINE20 0x801 -@@ -121,10 +134,46 @@ 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_ARM_CR4 0x83e ++#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 @@ -4089,10 +4619,64 @@ +#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 +185,10 @@ struct bcma_device { +@@ -136,8 +243,10 @@ struct bcma_device { bool dev_registered; u8 core_index; @@ -4103,7 +4687,7 @@ u32 wrap; void __iomem *io_addr; -@@ -175,6 +226,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); @@ -4116,7 +4700,7 @@ struct bcma_bus { /* The MMIO area. */ void __iomem *mmio; -@@ -191,14 +248,18 @@ struct bcma_bus { +@@ -191,14 +306,18 @@ struct bcma_bus { struct bcma_chipinfo chipinfo; @@ -4136,7 +4720,7 @@ /* 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 +343,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); } @@ -4144,7 +4728,7 @@ 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 +351,7 @@ extern void bcma_core_set_clockmode(stru +@@ -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); @@ -4169,7 +4753,7 @@ #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_NFLASH 0x00000200 /* NAND flash */ ++#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 @@ -4339,9 +4923,24 @@ #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 */ -@@ -240,7 +356,60 @@ +@@ -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) */ @@ -4401,7 +5000,7 @@ /* Divider allocation in 4716/47162/5356 */ #define BCMA_CC_PMU5_MAINPLL_CPU 1 -@@ -256,6 +425,15 @@ +@@ -256,6 +432,32 @@ /* 4706 PMU */ #define BCMA_CC_PMU4706_MAINPLL_PLL0 0 @@ -4414,10 +5013,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 +462,19 @@ +@@ -284,6 +486,19 @@ #define BCMA_CC_PPL_PCHI_OFF 5 #define BCMA_CC_PPL_PCHI_MASK 0x0000003f @@ -4437,7 +5053,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 +488,25 @@ +@@ -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 */ @@ -4460,10 +5076,41 @@ +#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) */ -@@ -310,11 +517,35 @@ struct bcma_chipcommon_pmu { +@@ -310,11 +572,36 @@ struct bcma_chipcommon_pmu { #ifdef CONFIG_BCMA_DRIVER_MIPS struct bcma_pflash { @@ -4482,6 +5129,7 @@ + u32 size; + + struct mtd_info *mtd; ++ void *priv; +}; +#endif + @@ -4499,7 +5147,7 @@ struct bcma_serial_port { void *regs; unsigned long clockspeed; -@@ -330,15 +561,30 @@ struct bcma_drv_cc { +@@ -330,15 +617,30 @@ struct bcma_drv_cc { u32 capabilities; u32 capabilities_ext; u8 setup_done:1; @@ -4530,7 +5178,7 @@ }; /* Register access */ -@@ -355,14 +601,16 @@ struct bcma_drv_cc { +@@ -355,14 +657,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); @@ -4549,7 +5197,7 @@ void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value); -@@ -375,9 +623,12 @@ u32 bcma_chipco_gpio_outen(struct bcma_d +@@ -375,9 +679,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); @@ -4562,11 +5210,13 @@ extern void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value); -@@ -387,5 +638,6 @@ extern void bcma_chipco_chipctl_maskset( +@@ -387,5 +694,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 @@ -4674,7 +5324,15 @@ +#endif /* LINUX_BCMA_DRIVER_GMAC_CMN_H_ */ --- a/include/linux/bcma/bcma_driver_mips.h +++ b/include/linux/bcma/bcma_driver_mips.h -@@ -35,13 +35,15 @@ struct bcma_device; +@@ -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; @@ -4685,12 +5343,23 @@ #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; @@ -4741,7 +5410,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 */ @@ -4816,6 +5485,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 + diff --git a/target/linux/generic/patches-3.6/020-ssb_update.patch b/target/linux/generic/patches-3.6/020-ssb_update.patch index 6f9c834..2d13458 100644 --- a/target/linux/generic/patches-3.6/020-ssb_update.patch +++ b/target/linux/generic/patches-3.6/020-ssb_update.patch @@ -30,7 +30,7 @@ ARRAY_SIZE(wgt634u_devices)); --- a/drivers/ssb/Kconfig +++ b/drivers/ssb/Kconfig -@@ -136,6 +136,11 @@ config SSB_DRIVER_MIPS +@@ -136,10 +136,15 @@ config SSB_DRIVER_MIPS If unsure, say N @@ -42,6 +42,11 @@ # Assumption: We are on embedded, if we compile the MIPS core. config SSB_EMBEDDED bool +- depends on SSB_DRIVER_MIPS ++ depends on SSB_DRIVER_MIPS && SSB_PCICORE_HOSTMODE + default y + + config SSB_DRIVER_EXTIF @@ -160,4 +165,12 @@ config SSB_DRIVER_GIGE If unsure, say N @@ -98,7 +103,7 @@ #include "ssb_private.h" -@@ -280,10 +282,76 @@ static void calc_fast_powerup_delay(stru +@@ -280,13 +282,79 @@ static void calc_fast_powerup_delay(stru cc->fast_pwrup_delay = tmp; } @@ -174,7 +179,11 @@ + 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_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); @@ -333,16 +342,62 @@ /* Turn off UART clock before switching clocksource. */ --- a/drivers/ssb/driver_chipcommon_pmu.c +++ b/drivers/ssb/driver_chipcommon_pmu.c -@@ -346,6 +346,8 @@ static void ssb_pmu_pll_init(struct ssb_ +@@ -110,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) { +@@ -138,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); +@@ -249,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) { +@@ -275,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); +@@ -346,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", -@@ -434,6 +436,7 @@ static void ssb_pmu_resources_init(struc +- 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); + } + } + +@@ -434,6 +435,7 @@ static void ssb_pmu_resources_init(struc min_msk = 0xCBB; break; case 0x4322: @@ -350,7 +405,30 @@ /* We keep the default settings: * min_msk = 0xCBB * max_msk = 0x7FFFF -@@ -615,6 +618,33 @@ void ssb_pmu_set_ldo_paref(struct ssb_ch +@@ -469,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) { +@@ -523,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, +@@ -615,6 +616,32 @@ void ssb_pmu_set_ldo_paref(struct ssb_ch EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage); EXPORT_SYMBOL(ssb_pmu_set_ldo_paref); @@ -374,9 +452,8 @@ + case 0x5354: + ssb_pmu_get_alp_clock_clk0(cc); + default: -+ ssb_printk(KERN_ERR PFX -+ "ERROR: PMU alp clock unknown for device %04X\n", -+ bus->chip_id); ++ ssb_err("ERROR: PMU alp clock unknown for device %04X\n", ++ bus->chip_id); + return 0; + } +} @@ -384,7 +461,27 @@ u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc) { struct ssb_bus *bus = cc->dev->bus; -@@ -645,3 +675,32 @@ u32 ssb_pmu_get_controlclock(struct ssb_ +@@ -624,9 +651,8 @@ u32 ssb_pmu_get_cpu_clock(struct ssb_chi + /* 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; + } + } +@@ -639,9 +665,52 @@ u32 ssb_pmu_get_controlclock(struct ssb_ + 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; } } @@ -405,8 +502,23 @@ + pmu_ctl = SSB_CHIPCO_PMU_CTL_PLL_UPD; + break; + case 43222: -+ /* TODO: BCM43222 requires updating PLLs too */ -+ return; ++ 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", @@ -419,7 +531,7 @@ +EXPORT_SYMBOL_GPL(ssb_pmu_spuravoid_pllupdate); --- /dev/null +++ b/drivers/ssb/driver_chipcommon_sflash.c -@@ -0,0 +1,18 @@ +@@ -0,0 +1,166 @@ +/* + * Sonics Silicon Backplane + * ChipCommon serial flash interface @@ -431,9 +543,157 @@ + +#include "ssb_private.h" + ++static struct resource ssb_sflash_resource = { ++ .name = "ssb_sflash", ++ .start = SSB_FLASH2, ++ .end = 0, ++ .flags = IORESOURCE_MEM | IORESOURCE_READONLY, ++}; ++ ++struct platform_device ssb_sflash_dev = { ++ .name = "ssb_sflash", ++ .resource = &ssb_sflash_resource, ++ .num_resources = 1, ++}; ++ ++struct ssb_sflash_tbl_e { ++ char *name; ++ u32 id; ++ u32 blocksize; ++ u16 numblocks; ++}; ++ ++static const struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = { ++ { "M25P20", 0x11, 0x10000, 4, }, ++ { "M25P40", 0x12, 0x10000, 8, }, ++ ++ { "M25P16", 0x14, 0x10000, 32, }, ++ { "M25P32", 0x15, 0x10000, 64, }, ++ { "M25P64", 0x16, 0x10000, 128, }, ++ { "M25FL128", 0x17, 0x10000, 256, }, ++ { 0 }, ++}; ++ ++static const struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { ++ { "SST25WF512", 1, 0x1000, 16, }, ++ { "SST25VF512", 0x48, 0x1000, 16, }, ++ { "SST25WF010", 2, 0x1000, 32, }, ++ { "SST25VF010", 0x49, 0x1000, 32, }, ++ { "SST25WF020", 3, 0x1000, 64, }, ++ { "SST25VF020", 0x43, 0x1000, 64, }, ++ { "SST25WF040", 4, 0x1000, 128, }, ++ { "SST25VF040", 0x44, 0x1000, 128, }, ++ { "SST25VF040B", 0x8d, 0x1000, 128, }, ++ { "SST25WF080", 5, 0x1000, 256, }, ++ { "SST25VF080B", 0x8e, 0x1000, 256, }, ++ { "SST25VF016", 0x41, 0x1000, 512, }, ++ { "SST25VF032", 0x4a, 0x1000, 1024, }, ++ { "SST25VF064", 0x4b, 0x1000, 2048, }, ++ { 0 }, ++}; ++ ++static const struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { ++ { "AT45DB011", 0xc, 256, 512, }, ++ { "AT45DB021", 0x14, 256, 1024, }, ++ { "AT45DB041", 0x1c, 256, 2048, }, ++ { "AT45DB081", 0x24, 256, 4096, }, ++ { "AT45DB161", 0x2c, 512, 4096, }, ++ { "AT45DB321", 0x34, 512, 8192, }, ++ { "AT45DB642", 0x3c, 1024, 8192, }, ++ { 0 }, ++}; ++ ++static void ssb_sflash_cmd(struct ssb_chipcommon *cc, u32 opcode) ++{ ++ int i; ++ chipco_write32(cc, SSB_CHIPCO_FLASHCTL, ++ SSB_CHIPCO_FLASHCTL_START | opcode); ++ for (i = 0; i < 1000; i++) { ++ if (!(chipco_read32(cc, SSB_CHIPCO_FLASHCTL) & ++ SSB_CHIPCO_FLASHCTL_BUSY)) ++ return; ++ cpu_relax(); ++ } ++ pr_err("SFLASH control command failed (timeout)!\n"); ++} ++ +/* Initialize serial flash access */ +int ssb_sflash_init(struct ssb_chipcommon *cc) +{ ++ struct ssb_sflash *sflash = &cc->dev->bus->mipscore.sflash; ++ const struct ssb_sflash_tbl_e *e; ++ u32 id, id2; ++ ++ switch (cc->capabilities & SSB_CHIPCO_CAP_FLASHT) { ++ case SSB_CHIPCO_FLASHT_STSER: ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_DP); ++ ++ chipco_write32(cc, SSB_CHIPCO_FLASHADDR, 0); ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_RES); ++ id = chipco_read32(cc, SSB_CHIPCO_FLASHDATA); ++ ++ chipco_write32(cc, SSB_CHIPCO_FLASHADDR, 1); ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_RES); ++ id2 = chipco_read32(cc, SSB_CHIPCO_FLASHDATA); ++ ++ switch (id) { ++ case 0xbf: ++ for (e = ssb_sflash_sst_tbl; e->name; e++) { ++ if (e->id == id2) ++ break; ++ } ++ break; ++ case 0x13: ++ return -ENOTSUPP; ++ default: ++ for (e = ssb_sflash_st_tbl; e->name; e++) { ++ if (e->id == id) ++ break; ++ } ++ break; ++ } ++ if (!e->name) { ++ pr_err("Unsupported ST serial flash (id: 0x%X, id2: 0x%X)\n", ++ id, id2); ++ return -ENOTSUPP; ++ } ++ ++ break; ++ case SSB_CHIPCO_FLASHT_ATSER: ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_AT_STATUS); ++ id = chipco_read32(cc, SSB_CHIPCO_FLASHDATA) & 0x3c; ++ ++ for (e = ssb_sflash_at_tbl; e->name; e++) { ++ if (e->id == id) ++ break; ++ } ++ if (!e->name) { ++ pr_err("Unsupported Atmel serial flash (id: 0x%X)\n", ++ id); ++ return -ENOTSUPP; ++ } ++ ++ break; ++ default: ++ pr_err("Unsupported flash type\n"); ++ return -ENOTSUPP; ++ } ++ ++ sflash->window = SSB_FLASH2; ++ sflash->blocksize = e->blocksize; ++ sflash->numblocks = e->numblocks; ++ sflash->size = sflash->blocksize * sflash->numblocks; ++ sflash->present = true; ++ ++ pr_info("Found %s serial flash (blocksize: 0x%X, blocks: %d)\n", ++ e->name, e->blocksize, e->numblocks); ++ ++ /* Prepare platform device, but don't register it yet. It's too early, ++ * malloc (required by device_private_init) is not available yet. */ ++ ssb_sflash_dev.resource[0].end = ssb_sflash_dev.resource[0].start + ++ sflash->size; ++ ssb_sflash_dev.dev.platform_data = sflash; ++ + pr_err("Serial flash support is not implemented yet!\n"); + + return -ENOTSUPP; @@ -537,7 +797,7 @@ } --- /dev/null +++ b/drivers/ssb/driver_gpio.c -@@ -0,0 +1,176 @@ +@@ -0,0 +1,210 @@ +/* + * Sonics Silicon Backplane + * GPIO driver @@ -614,6 +874,16 @@ + 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; @@ -626,6 +896,7 @@ + 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 @@ -674,6 +945,16 @@ + 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; @@ -684,6 +965,7 @@ + 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 @@ -714,9 +996,88 @@ + + 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 -@@ -178,9 +178,9 @@ static void ssb_mips_serial_init(struct +@@ -10,6 +10,7 @@ + + #include <linux/ssb/ssb.h> + ++#include <linux/mtd/physmap.h> + #include <linux/serial.h> + #include <linux/serial_core.h> + #include <linux/serial_reg.h> +@@ -17,6 +18,25 @@ + + #include "ssb_private.h" + ++static const char * const part_probes[] = { "bcm47xxpart", NULL }; ++ ++static struct physmap_flash_data ssb_pflash_data = { ++ .part_probe_types = part_probes, ++}; ++ ++static struct resource ssb_pflash_resource = { ++ .name = "ssb_pflash", ++ .flags = IORESOURCE_MEM, ++}; ++ ++struct platform_device ssb_pflash_dev = { ++ .name = "physmap-flash", ++ .dev = { ++ .platform_data = &ssb_pflash_data, ++ }, ++ .resource = &ssb_pflash_resource, ++ .num_resources = 1, ++}; + + static inline u32 mips_read32(struct ssb_mipscore *mcore, + u16 offset) +@@ -147,21 +167,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 +199,9 @@ static void ssb_mips_serial_init(struct { struct ssb_bus *bus = mcore->dev->bus; @@ -728,9 +1089,11 @@ mcore->nr_serial_ports = ssb_chipco_serial_init(&bus->chipco, mcore->serial_ports); else mcore->nr_serial_ports = 0; -@@ -190,16 +190,33 @@ static void ssb_mips_flash_detect(struct +@@ -189,17 +210,42 @@ static void ssb_mips_serial_init(struct + static void ssb_mips_flash_detect(struct ssb_mipscore *mcore) { struct ssb_bus *bus = mcore->dev->bus; ++ struct ssb_pflash *pflash = &mcore->pflash; - mcore->flash_buswidth = 2; - if (bus->chipco.dev) { @@ -738,11 +1101,11 @@ - mcore->flash_window_size = 0x02000000; + /* When there is no chipcommon on the bus there is 4MB flash */ + if (!ssb_chipco_available(&bus->chipco)) { -+ mcore->pflash.present = true; -+ mcore->pflash.buswidth = 2; -+ mcore->pflash.window = SSB_FLASH1; -+ mcore->pflash.window_size = SSB_FLASH1_SZ; -+ return; ++ pflash->present = true; ++ pflash->buswidth = 2; ++ pflash->window = SSB_FLASH1; ++ pflash->window_size = SSB_FLASH1_SZ; ++ goto ssb_pflash; + } + + /* There is ChipCommon, so use it to read info about flash */ @@ -754,23 +1117,30 @@ + break; + case SSB_CHIPCO_FLASHT_PARA: + pr_debug("Found parallel flash\n"); -+ mcore->pflash.present = true; -+ mcore->pflash.window = SSB_FLASH2; -+ mcore->pflash.window_size = SSB_FLASH2_SZ; ++ pflash->present = true; ++ pflash->window = SSB_FLASH2; ++ pflash->window_size = SSB_FLASH2_SZ; if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG) & SSB_CHIPCO_CFG_DS16) == 0) - mcore->flash_buswidth = 1; - } else { - mcore->flash_window = 0x1fc00000; - mcore->flash_window_size = 0x00400000; -+ mcore->pflash.buswidth = 1; ++ pflash->buswidth = 1; + else -+ mcore->pflash.buswidth = 2; ++ pflash->buswidth = 2; + break; ++ } ++ ++ssb_pflash: ++ if (pflash->present) { ++ ssb_pflash_data.width = pflash->buswidth; ++ ssb_pflash_resource.start = pflash->window; ++ ssb_pflash_resource.end = pflash->window + pflash->window_size; } } -@@ -211,9 +228,9 @@ u32 ssb_cpu_clock(struct ssb_mipscore *m +@@ -211,9 +257,9 @@ u32 ssb_cpu_clock(struct ssb_mipscore *m if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU) return ssb_pmu_get_cpu_clock(&bus->chipco); @@ -782,7 +1152,16 @@ ssb_chipco_get_clockcpu(&bus->chipco, &pll_type, &n, &m); } else return 0; -@@ -249,9 +266,9 @@ void ssb_mipscore_init(struct ssb_mipsco +@@ -241,7 +287,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); +@@ -249,9 +295,9 @@ void ssb_mipscore_init(struct ssb_mipsco hz = 100000000; ns = 1000000000 / hz; @@ -794,6 +1173,71 @@ 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 */ +@@ -289,7 +335,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 @@ @@ -810,7 +1254,7 @@ #include <linux/ssb/ssb.h> #include <linux/ssb/ssb_embedded.h> #include <linux/ssb/ssb_driver_pci.h> -@@ -32,6 +34,39 @@ int ssb_watchdog_timer_set(struct ssb_bu +@@ -32,6 +34,38 @@ int ssb_watchdog_timer_set(struct ssb_bu } EXPORT_SYMBOL(ssb_watchdog_timer_set); @@ -837,9 +1281,8 @@ + bus->busnumber, &wdt, + sizeof(wdt)); + if (IS_ERR(pdev)) { -+ ssb_dprintk(KERN_INFO PFX -+ "can not register watchdog device, err: %li\n", -+ PTR_ERR(pdev)); ++ ssb_dbg("can not register watchdog device, err: %li\n", ++ PTR_ERR(pdev)); + return PTR_ERR(pdev); + } + @@ -860,7 +1303,18 @@ #include <linux/ssb/ssb.h> #include <linux/ssb/ssb_regs.h> #include <linux/ssb/ssb_driver_gige.h> -@@ -433,6 +434,11 @@ static void ssb_devices_unregister(struc +@@ -274,8 +275,8 @@ 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_device_put(sdev); +@@ -433,10 +434,23 @@ static void ssb_devices_unregister(struc if (sdev->dev) device_unregister(sdev->dev); } @@ -872,7 +1326,63 @@ } void ssb_bus_unregister(struct ssb_bus *bus) -@@ -561,6 +567,8 @@ static int __devinit ssb_attach_queued_b + { ++ 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); +@@ -482,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; + } +@@ -522,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; +@@ -534,6 +545,22 @@ static int ssb_devices_register(struct s + dev_idx++; + } + ++#ifdef CONFIG_SSB_DRIVER_MIPS ++ if (bus->mipscore.pflash.present) { ++ err = platform_device_register(&ssb_pflash_dev); ++ if (err) ++ pr_err("Error registering parallel flash\n"); ++ } ++#endif ++ ++#ifdef CONFIG_SSB_SFLASH ++ if (bus->mipscore.sflash.present) { ++ err = platform_device_register(&ssb_sflash_dev); ++ if (err) ++ pr_err("Error registering serial flash\n"); ++ } ++#endif ++ + return 0; + error: + /* Unwind the already registered devices. */ +@@ -561,6 +588,8 @@ static int __devinit ssb_attach_queued_b if (err) goto error; ssb_pcicore_init(&bus->pcicore); @@ -881,7 +1391,7 @@ ssb_bus_may_powerdown(bus); err = ssb_devices_register(bus); -@@ -796,7 +804,14 @@ static int __devinit ssb_bus_register(st +@@ -796,7 +825,13 @@ static int __devinit ssb_bus_register(st if (err) goto err_pcmcia_exit; ssb_chipcommon_init(&bus->chipco); @@ -889,14 +1399,62 @@ ssb_mipscore_init(&bus->mipscore); + err = ssb_gpio_init(bus); + if (err == -ENOTSUPP) -+ ssb_dprintk(KERN_DEBUG PFX "GPIO driver not activated\n"); ++ ssb_dbg("GPIO driver not activated\n"); + else if (err) -+ ssb_dprintk(KERN_ERR PFX -+ "Error registering GPIO driver: %i\n", err); ++ ssb_dbg("Error registering GPIO driver: %i\n", err); err = ssb_fetch_invariants(bus, get_invariants); if (err) { ssb_bus_may_powerdown(bus); -@@ -1118,8 +1133,7 @@ static u32 ssb_tmslow_reject_bitmask(str +@@ -847,11 +882,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; +@@ -872,8 +907,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; +@@ -895,8 +930,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; +@@ -915,8 +950,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; +@@ -1118,8 +1153,7 @@ static u32 ssb_tmslow_reject_bitmask(str case SSB_IDLOW_SSBREV_27: /* same here */ return SSB_TMSLOW_REJECT; /* this is a guess */ default: @@ -906,9 +1464,589 @@ } return (SSB_TMSLOW_REJECT | SSB_TMSLOW_REJECT_23); } +@@ -1311,7 +1345,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); +@@ -1334,7 +1368,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); +@@ -1442,15 +1476,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 +@@ -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); +@@ -231,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 word; +@@ -278,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; +@@ -286,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); +@@ -309,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; + } + +@@ -339,10 +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; + u16 loc[3]; + + if (out->revision == 3) /* rev 3 moved MAC */ +@@ -352,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, +@@ -372,6 +384,7 @@ 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(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); +@@ -398,8 +411,7 @@ 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); ++ + SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8); + SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0); + +@@ -410,6 +422,8 @@ static void sprom_extract_r123(struct ss + 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 */ +@@ -454,23 +468,20 @@ 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(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8); + SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0); +@@ -530,7 +541,7 @@ static void sprom_extract_r45(struct ssb + static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) + { + int i; +- 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 +@@ -539,11 +550,10 @@ static void sprom_extract_r8(struct ssb_ + 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); +- } ++ 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); +@@ -743,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); + +@@ -752,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) { +@@ -769,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); + } +@@ -791,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! */ +@@ -810,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) +@@ -835,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); +--- a/drivers/ssb/pcihost_wrapper.c ++++ b/drivers/ssb/pcihost_wrapper.c +@@ -38,7 +38,7 @@ static int ssb_pcihost_resume(struct pci + struct ssb_bus *ssb = pci_get_drvdata(dev); + int err; + +- pci_set_power_state(dev, 0); ++ pci_set_power_state(dev, PCI_D0); + err = pci_enable_device(dev); + if (err) + return err; +--- a/drivers/ssb/pcmcia.c ++++ b/drivers/ssb/pcmcia.c +@@ -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; +@@ -700,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; +@@ -722,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; + } +@@ -733,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; + } +@@ -843,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 +@@ -125,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; +@@ -152,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; +@@ -320,15 +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) { +@@ -370,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; + } + } +@@ -379,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; +@@ -388,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; +@@ -398,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; +@@ -420,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/sprom.c ++++ b/drivers/ssb/sprom.c +@@ -54,7 +54,7 @@ static int hex2sprom(u16 *sprom, const c + while (cnt < sprom_size_words) { + memcpy(tmp, dump, 4); + dump += 4; +- err = strict_strtoul(tmp, 16, &parsed); ++ err = kstrtoul(tmp, 16, &parsed); + if (err) + return err; + sprom[cnt++] = swab16((u16)parsed); +@@ -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 -@@ -3,6 +3,7 @@ +@@ -3,21 +3,33 @@ #include <linux/ssb/ssb.h> #include <linux/types.h> @@ -916,7 +2054,37 @@ #define PFX "ssb: " -@@ -210,5 +211,63 @@ static inline void b43_pci_ssb_bridge_ex + + #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 +@@ -210,5 +222,76 @@ static inline void b43_pci_ssb_bridge_ex /* 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); @@ -937,6 +2105,14 @@ +} +#endif /* CONFIG_SSB_SFLASH */ + ++#ifdef CONFIG_SSB_DRIVER_MIPS ++extern struct platform_device ssb_pflash_dev; ++#endif ++ ++#ifdef CONFIG_SSB_SFLASH ++extern struct platform_device ssb_sflash_dev; ++#endif ++ +#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); @@ -972,11 +2148,16 @@ + +#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_ */ @@ -993,7 +2174,85 @@ #include <linux/ssb/ssb_regs.h> -@@ -432,7 +434,11 @@ struct ssb_bus { +@@ -24,9 +26,9 @@ struct ssb_sprom_core_pwr_info { + + struct ssb_sprom { + u8 revision; +- 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 */ +@@ -338,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 */ +@@ -432,7 +482,11 @@ struct ssb_bus { #ifdef CONFIG_SSB_EMBEDDED /* Lock for GPIO register access. */ spinlock_t gpio_lock; @@ -1147,9 +2406,51 @@ + #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 +@@ -97,21 +97,16 @@ static inline bool ssb_gige_must_flush_p + return 0; + } + +-#ifdef CONFIG_BCM47XX +-#include <asm/mach-bcm47xx/nvram.h> + /* 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); +@@ -175,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 -@@ -13,6 +13,12 @@ struct ssb_serial_port { +@@ -13,6 +13,24 @@ struct ssb_serial_port { unsigned int reg_shift; }; @@ -1159,10 +2460,22 @@ + u32 window; + u32 window_size; +}; ++ ++#ifdef CONFIG_SSB_SFLASH ++struct ssb_sflash { ++ bool present; ++ u32 window; ++ u32 blocksize; ++ u16 numblocks; ++ u32 size; ++ ++ void *priv; ++}; ++#endif struct ssb_mipscore { struct ssb_device *dev; -@@ -20,9 +26,7 @@ struct ssb_mipscore { +@@ -20,9 +38,10 @@ struct ssb_mipscore { int nr_serial_ports; struct ssb_serial_port serial_ports[4]; @@ -1170,12 +2483,35 @@ - u32 flash_window; - u32 flash_window_size; + struct ssb_pflash pflash; ++#ifdef CONFIG_SSB_SFLASH ++ struct ssb_sflash sflash; ++#endif }; extern void ssb_mipscore_init(struct ssb_mipscore *mcore); +@@ -41,6 +60,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 -@@ -289,11 +289,11 @@ +@@ -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 +@@ -289,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 */ @@ -1192,7 +2528,7 @@ #define SSB_SPROM4_AGAIN01 0x005E /* Antenna Gain (in dBm Q5.2) */ #define SSB_SPROM4_AGAIN0 0x00FF /* Antenna 0 */ #define SSB_SPROM4_AGAIN0_SHIFT 0 -@@ -485,7 +485,7 @@ +@@ -485,7 +486,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 @@ -1235,46 +2571,3 @@ break; #endif } ---- a/drivers/ssb/pci.c -+++ b/drivers/ssb/pci.c -@@ -339,6 +339,21 @@ 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; -@@ -398,8 +413,7 @@ 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); -+ - SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8); - SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0); - -@@ -410,6 +424,8 @@ static void sprom_extract_r123(struct ss - 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 */ diff --git a/target/linux/generic/patches-3.6/025-bcma_backport.patch b/target/linux/generic/patches-3.6/025-bcma_backport.patch index 15f54a7..9ad3ce3 100644 --- a/target/linux/generic/patches-3.6/025-bcma_backport.patch +++ b/target/linux/generic/patches-3.6/025-bcma_backport.patch @@ -1,6 +1,25 @@ +--- 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/drivers/bcma/Kconfig +++ b/drivers/bcma/Kconfig -@@ -48,12 +48,12 @@ config BCMA_DRIVER_MIPS +@@ -26,6 +26,7 @@ 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" +@@ -48,12 +49,12 @@ config BCMA_DRIVER_MIPS config BCMA_SFLASH bool @@ -15,7 +34,7 @@ default y config BCMA_DRIVER_GMAC_CMN -@@ -65,6 +65,14 @@ config BCMA_DRIVER_GMAC_CMN +@@ -65,6 +66,14 @@ config BCMA_DRIVER_GMAC_CMN If unsure, say N @@ -42,7 +61,16 @@ obj-$(CONFIG_BCMA) += bcma.o --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h -@@ -31,6 +31,8 @@ int __init bcma_bus_early_register(struc +@@ -22,6 +22,8 @@ + struct bcma_bus; + + /* main.c */ ++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, +@@ -31,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 @@ -51,7 +79,11 @@ /* scan.c */ int bcma_bus_scan(struct bcma_bus *bus); -@@ -48,12 +50,13 @@ void bcma_chipco_serial_init(struct bcma +@@ -45,15 +49,17 @@ int bcma_sprom_get(struct bcma_bus *bus) + /* driver_chipcommon.c */ + #ifdef CONFIG_BCMA_DRIVER_MIPS + void bcma_chipco_serial_init(struct bcma_drv_cc *cc); ++extern struct platform_device bcma_pflash_dev; #endif /* CONFIG_BCMA_DRIVER_MIPS */ /* driver_chipcommon_pmu.c */ @@ -67,7 +99,7 @@ #else static inline int bcma_sflash_init(struct bcma_drv_cc *cc) { -@@ -65,6 +68,7 @@ static inline int bcma_sflash_init(struc +@@ -65,6 +71,7 @@ static inline int bcma_sflash_init(struc #ifdef CONFIG_BCMA_NFLASH /* driver_chipcommon_nflash.c */ int bcma_nflash_init(struct bcma_drv_cc *cc); @@ -75,7 +107,7 @@ #else static inline int bcma_nflash_init(struct bcma_drv_cc *cc) { -@@ -82,9 +86,21 @@ extern void __exit bcma_host_pci_exit(vo +@@ -82,9 +89,26 @@ extern void __exit bcma_host_pci_exit(vo /* driver_pci.c */ u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address); @@ -89,17 +121,75 @@ +#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 -@@ -65,7 +65,7 @@ void bcma_core_set_clockmode(struct bcma +@@ -9,6 +9,25 @@ + #include <linux/export.h> + #include <linux/bcma/bcma.h> + ++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,13 +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); + +@@ -43,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)); +@@ -65,7 +87,7 @@ void bcma_core_set_clockmode(struct bcma switch (clkmode) { case BCMA_CLKMODE_FAST: bcma_set32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT); @@ -108,6 +198,21 @@ for (i = 0; i < 1500; i++) { if (bcma_read32(core, BCMA_CLKCTLST) & BCMA_CLKCTLST_HAVEHT) { +@@ -104,7 +126,13 @@ void bcma_core_pll_ctl(struct bcma_devic + if (i) + bcma_err(core->bus, "PLL enable timeout\n"); + } else { +- 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); --- a/drivers/bcma/driver_chipcommon.c +++ b/drivers/bcma/driver_chipcommon.c @@ -4,12 +4,15 @@ @@ -126,7 +231,7 @@ #include <linux/bcma/bcma.h> static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, -@@ -22,20 +25,120 @@ static inline u32 bcma_cc_write32_masked +@@ -22,23 +25,130 @@ static inline u32 bcma_cc_write32_masked return value; } @@ -249,9 +354,21 @@ + 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); -@@ -56,15 +159,33 @@ void bcma_core_chipcommon_init(struct bc +- 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) +@@ -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))); } @@ -288,7 +405,7 @@ } void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value) -@@ -84,28 +205,99 @@ u32 bcma_chipco_gpio_in(struct bcma_drv_ +@@ -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) { @@ -393,7 +510,7 @@ } #ifdef CONFIG_BCMA_DRIVER_MIPS -@@ -118,8 +310,7 @@ void bcma_chipco_serial_init(struct bcma +@@ -118,8 +317,7 @@ void bcma_chipco_serial_init(struct bcma struct bcma_serial_port *ports = cc->serial_ports; if (ccrev >= 11 && ccrev != 15) { @@ -403,24 +520,34 @@ if (ccrev >= 21) { /* Turn off UART clock before switching clocksource. */ bcma_cc_write32(cc, BCMA_CC_CORECTL, +@@ -141,7 +339,7 @@ void bcma_chipco_serial_init(struct bcma + 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_nflash.c +++ b/drivers/bcma/driver_chipcommon_nflash.c @@ -5,15 +5,40 @@ * Licensed under the GNU/GPL. See COPYING for details. */ ++#include "bcma_private.h" ++ +#include <linux/platform_device.h> #include <linux/bcma/bcma.h> -#include <linux/bcma/bcma_driver_chipcommon.h> -#include <linux/delay.h> - #include "bcma_private.h" - +-#include "bcma_private.h" +struct platform_device bcma_nflash_dev = { + .name = "bcma_nflash", + .num_resources = 0, +}; -+ + /* Initialize NAND flash access */ int bcma_nflash_init(struct bcma_drv_cc *cc) { @@ -428,7 +555,7 @@ + struct bcma_bus *bus = cc->core->bus; + + if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4706 && -+ cc->core->id.rev != 0x38) { ++ cc->core->id.rev != 38) { + bcma_err(bus, "NAND flash on unsupported board!\n"); + return -ENOTSUPP; + } @@ -466,7 +593,143 @@ void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value) { -@@ -76,7 +77,10 @@ static void bcma_pmu_resources_init(stru +@@ -55,6 +56,109 @@ void bcma_chipco_regctl_maskset(struct b + } + EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset); + ++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 BCMA_CHIP_ID_BCM43142: ++ if (xtalfreq == 0) ++ xtalfreq = 20000; ++ bcma_pmu2_pll_init0(cc, xtalfreq); ++ break; ++ } ++} ++ + static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) + { + struct bcma_bus *bus = cc->core->bus; +@@ -65,6 +169,25 @@ static void bcma_pmu_resources_init(stru + min_msk = 0x200D; + max_msk = 0xFFFF; + 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: + bcma_debug(bus, "PMU resource config unknown or not needed for device 0x%04X\n", + bus->chipinfo.id); +@@ -76,7 +199,10 @@ static void bcma_pmu_resources_init(stru if (max_msk) bcma_cc_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk); @@ -478,7 +741,7 @@ mdelay(2); } -@@ -101,7 +105,7 @@ void bcma_chipco_bcm4331_ext_pa_lines_ct +@@ -101,7 +227,7 @@ void bcma_chipco_bcm4331_ext_pa_lines_ct bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val); } @@ -487,7 +750,7 @@ { struct bcma_bus *bus = cc->core->bus; -@@ -141,7 +145,7 @@ void bcma_pmu_workarounds(struct bcma_dr +@@ -141,7 +267,7 @@ void bcma_pmu_workarounds(struct bcma_dr } } @@ -496,7 +759,7 @@ { u32 pmucap; -@@ -150,7 +154,10 @@ void bcma_pmu_init(struct bcma_drv_cc *c +@@ -150,7 +276,10 @@ void bcma_pmu_init(struct bcma_drv_cc *c bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n", cc->pmu.rev, pmucap); @@ -507,7 +770,12 @@ if (cc->pmu.rev == 1) bcma_cc_mask32(cc, BCMA_CC_PMU_CTL, ~BCMA_CC_PMU_CTL_NOILPONW); -@@ -162,24 +169,40 @@ void bcma_pmu_init(struct bcma_drv_cc *c +@@ -158,28 +287,45 @@ void bcma_pmu_init(struct bcma_drv_cc *c + bcma_cc_set32(cc, BCMA_CC_PMU_CTL, + BCMA_CC_PMU_CTL_NOILPONW); + ++ bcma_pmu_pll_init(cc); + bcma_pmu_resources_init(cc); bcma_pmu_workarounds(cc); } @@ -553,7 +821,7 @@ default: bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n", bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK); -@@ -190,7 +213,7 @@ u32 bcma_pmu_alp_clock(struct bcma_drv_c +@@ -190,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. */ @@ -562,7 +830,7 @@ { u32 tmp, div, ndiv, p1, p2, fc; struct bcma_bus *bus = cc->core->bus; -@@ -219,14 +242,14 @@ static u32 bcma_pmu_clock(struct bcma_dr +@@ -219,14 +365,14 @@ static u32 bcma_pmu_clock(struct bcma_dr ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT; /* Do calculation in Mhz */ @@ -579,16 +847,16 @@ { u32 tmp, ndiv, p1div, p2div; u32 clock; -@@ -257,7 +280,7 @@ static u32 bcma_pmu_clock_bcm4706(struct +@@ -257,7 +403,7 @@ static u32 bcma_pmu_clock_bcm4706(struct } /* query bus clock frequency for PMU-enabled chipcommon */ -u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc) -+static u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc) ++u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc) { struct bcma_bus *bus = cc->core->bus; -@@ -265,40 +288,42 @@ u32 bcma_pmu_get_clockcontrol(struct bcm +@@ -265,40 +411,43 @@ u32 bcma_pmu_get_clockcontrol(struct bcm case BCMA_CHIP_ID_BCM4716: case BCMA_CHIP_ID_BCM4748: case BCMA_CHIP_ID_BCM47162: @@ -622,6 +890,7 @@ } return BCMA_CC_PMU_HT_CLOCK; } ++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) @@ -642,7 +911,7 @@ BCMA_CC_PMU4706_MAINPLL_PLL0, BCMA_CC_PMU5_MAINPLL_CPU); case BCMA_CHIP_ID_BCM5356: -@@ -313,10 +338,11 @@ u32 bcma_pmu_get_clockcpu(struct bcma_dr +@@ -313,10 +462,11 @@ u32 bcma_pmu_get_clockcpu(struct bcma_dr break; } @@ -656,7 +925,7 @@ } static void bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc *cc, u32 offset, -@@ -362,7 +388,7 @@ void bcma_pmu_spuravoid_pllupdate(struct +@@ -362,7 +512,7 @@ void bcma_pmu_spuravoid_pllupdate(struct tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT; bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp); @@ -665,7 +934,7 @@ break; case BCMA_CHIP_ID_BCM4331: -@@ -383,7 +409,7 @@ void bcma_pmu_spuravoid_pllupdate(struct +@@ -383,7 +533,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 0x03000a08); } @@ -674,7 +943,7 @@ break; case BCMA_CHIP_ID_BCM43224: -@@ -416,7 +442,7 @@ void bcma_pmu_spuravoid_pllupdate(struct +@@ -416,7 +566,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 0x88888815); } @@ -683,7 +952,7 @@ break; case BCMA_CHIP_ID_BCM4716: -@@ -450,7 +476,7 @@ void bcma_pmu_spuravoid_pllupdate(struct +@@ -450,7 +600,7 @@ void bcma_pmu_spuravoid_pllupdate(struct 0x88888815); } @@ -692,7 +961,7 @@ break; case BCMA_CHIP_ID_BCM43227: -@@ -486,7 +512,7 @@ void bcma_pmu_spuravoid_pllupdate(struct +@@ -486,7 +636,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 0x88888815); } @@ -707,13 +976,14 @@ * Licensed under the GNU/GPL. See COPYING for details. */ ++#include "bcma_private.h" ++ +#include <linux/platform_device.h> #include <linux/bcma/bcma.h> -#include <linux/bcma/bcma_driver_chipcommon.h> -#include <linux/delay.h> - #include "bcma_private.h" - +-#include "bcma_private.h" +static struct resource bcma_sflash_resource = { + .name = "bcma_sflash", + .start = BCMA_SOC_FLASH2, @@ -734,7 +1004,7 @@ + u16 numblocks; +}; + -+static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { ++static const struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { + { "M25P20", 0x11, 0x10000, 4, }, + { "M25P40", 0x12, 0x10000, 8, }, + @@ -745,7 +1015,7 @@ + { 0 }, +}; + -+static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { ++static const struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { + { "SST25WF512", 1, 0x1000, 16, }, + { "SST25VF512", 0x48, 0x1000, 16, }, + { "SST25WF010", 2, 0x1000, 32, }, @@ -763,7 +1033,7 @@ + { 0 }, +}; + -+static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { ++static const struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { + { "AT45DB011", 0xc, 256, 512, }, + { "AT45DB021", 0x14, 256, 1024, }, + { "AT45DB041", 0x1c, 256, 2048, }, @@ -787,14 +1057,14 @@ + } + bcma_err(cc->core->bus, "SFLASH control command failed (timeout)!\n"); +} -+ + /* Initialize serial flash access */ int bcma_sflash_init(struct bcma_drv_cc *cc) { - bcma_err(cc->core->bus, "Serial flash support is broken\n"); + struct bcma_bus *bus = cc->core->bus; + struct bcma_sflash *sflash = &cc->sflash; -+ struct bcma_sflash_tbl_e *e; ++ const struct bcma_sflash_tbl_e *e; + u32 id, id2; + + switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { @@ -870,7 +1140,7 @@ } --- /dev/null +++ b/drivers/bcma/driver_gpio.c -@@ -0,0 +1,98 @@ +@@ -0,0 +1,114 @@ +/* + * Broadcom specific AMBA + * GPIO driver @@ -946,6 +1216,16 @@ + 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; @@ -958,6 +1238,7 @@ + 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 @@ -969,9 +1250,48 @@ + + 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 -@@ -74,11 +74,16 @@ static u32 bcma_core_mips_irqflag(struct +@@ -14,11 +14,33 @@ + + #include <linux/bcma/bcma.h> + ++#include <linux/mtd/physmap.h> ++#include <linux/platform_device.h> + #include <linux/serial.h> + #include <linux/serial_core.h> + #include <linux/serial_reg.h> + #include <linux/time.h> + ++static const char * const part_probes[] = { "bcm47xxpart", NULL }; ++ ++static struct physmap_flash_data bcma_pflash_data = { ++ .part_probe_types = part_probes, ++}; ++ ++static struct resource bcma_pflash_resource = { ++ .name = "bcma_pflash", ++ .flags = IORESOURCE_MEM, ++}; ++ ++struct platform_device bcma_pflash_dev = { ++ .name = "physmap-flash", ++ .dev = { ++ .platform_data = &bcma_pflash_data, ++ }, ++ .resource = &bcma_pflash_resource, ++ .num_resources = 1, ++}; ++ + /* The 47162a0 hangs when reading MIPS DMP registers registers */ + static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev) + { +@@ -74,28 +96,41 @@ static u32 bcma_core_mips_irqflag(struct return dev->core_index; flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30); @@ -987,9 +1307,11 @@ + * If disabled, 5 is returned. + * If not supported, 6 is returned. */ - unsigned int bcma_core_mips_irq(struct bcma_device *dev) +-unsigned int bcma_core_mips_irq(struct bcma_device *dev) ++static unsigned int bcma_core_mips_irq(struct bcma_device *dev) { -@@ -87,13 +92,15 @@ unsigned int bcma_core_mips_irq(struct b + struct bcma_device *mdev = dev->bus->drv_mips.core; + u32 irqflag; unsigned int irq; irqflag = bcma_core_mips_irqflag(dev); @@ -1004,10 +1326,19 @@ - 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_mips_irq); ++EXPORT_SYMBOL(bcma_core_irq); -@@ -114,8 +121,8 @@ static void bcma_core_mips_set_irq(struc + static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq) + { +@@ -114,8 +149,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)); @@ -1018,7 +1349,7 @@ /* assign the new one */ if (irq == 0) { -@@ -123,9 +130,9 @@ static void bcma_core_mips_set_irq(struc +@@ -123,9 +158,9 @@ static void bcma_core_mips_set_irq(struc bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) | (1 << irqflag)); } else { @@ -1031,7 +1362,7 @@ struct bcma_device *core; /* backplane irq line is in use, find out who uses -@@ -133,7 +140,7 @@ static void bcma_core_mips_set_irq(struc +@@ -133,7 +168,7 @@ static void bcma_core_mips_set_irq(struc */ list_for_each_entry(core, &bus->cores, list) { if ((1 << bcma_core_mips_irqflag(core)) == @@ -1040,7 +1371,7 @@ bcma_core_mips_set_irq(core, 0); break; } -@@ -143,15 +150,31 @@ static void bcma_core_mips_set_irq(struc +@@ -143,15 +178,31 @@ static void bcma_core_mips_set_irq(struc 1 << irqflag); } @@ -1075,7 +1406,7 @@ for (i = 0; i <= 6; i++) printk(" %s%s", irq_name[i], i == irq ? "*" : " "); printk("\n"); -@@ -171,7 +194,7 @@ u32 bcma_cpu_clock(struct bcma_drv_mips +@@ -171,7 +222,7 @@ u32 bcma_cpu_clock(struct bcma_drv_mips struct bcma_bus *bus = mcore->core->bus; if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU) @@ -1084,11 +1415,12 @@ bcma_err(bus, "No PMU available, need this to get the cpu clock\n"); return 0; -@@ -181,85 +204,109 @@ EXPORT_SYMBOL(bcma_cpu_clock); +@@ -181,85 +232,143 @@ EXPORT_SYMBOL(bcma_cpu_clock); static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore) { struct bcma_bus *bus = mcore->core->bus; + struct bcma_drv_cc *cc = &bus->drv_cc; ++ struct bcma_pflash *pflash = &cc->pflash; - switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) { + switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { @@ -1102,18 +1434,23 @@ bcma_debug(bus, "Found parallel flash\n"); - bus->drv_cc.pflash.window = 0x1c000000; - bus->drv_cc.pflash.window_size = 0x02000000; -+ cc->pflash.present = true; -+ cc->pflash.window = BCMA_SOC_FLASH2; -+ cc->pflash.window_size = BCMA_SOC_FLASH2_SZ; ++ pflash->present = true; ++ pflash->window = BCMA_SOC_FLASH2; ++ pflash->window_size = BCMA_SOC_FLASH2_SZ; - if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) & + if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) & BCMA_CC_FLASH_CFG_DS) == 0) - bus->drv_cc.pflash.buswidth = 1; -+ cc->pflash.buswidth = 1; ++ pflash->buswidth = 1; else - bus->drv_cc.pflash.buswidth = 2; -+ cc->pflash.buswidth = 2; ++ pflash->buswidth = 2; ++ ++ bcma_pflash_data.width = pflash->buswidth; ++ bcma_pflash_resource.start = pflash->window; ++ bcma_pflash_resource.end = pflash->window + pflash->window_size; ++ break; default: bcma_err(bus, "Flash type not supported\n"); @@ -1144,6 +1481,32 @@ + 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"); ++ } ++} ++ void bcma_core_mips_init(struct bcma_drv_mips *mcore) { struct bcma_bus *bus; @@ -1188,6 +1551,8 @@ - break; + bcma_core_mips_early_init(mcore); + ++ bcma_fix_i2s_irqflag(bus); ++ + switch (bus->chipinfo.id) { + case BCMA_CHIP_ID_BCM4716: + case BCMA_CHIP_ID_BCM4748: @@ -1224,7 +1589,7 @@ + break; + default: + list_for_each_entry(core, &bus->cores, list) { -+ core->irq = bcma_core_mips_irq(core) + 2; ++ core->irq = bcma_core_irq(core); } + bcma_err(bus, + "Unknown device (0x%x) found, can not configure IRQs\n", @@ -1284,7 +1649,130 @@ bcma_core_enable(pc->core, 0); return !mips_busprobe32(tmp, pc->core->io_addr); -@@ -396,6 +391,11 @@ void __devinit bcma_core_pci_hostmode_in +@@ -99,19 +94,19 @@ static int bcma_extpci_read_config(struc + 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 { +@@ -124,11 +119,9 @@ static int bcma_extpci_read_config(struc + goto out; + + if (mips_busprobe32(val, mmio)) { +- val = 0xffffffff; ++ val = 0xFFFFFFFF; + goto unmap; + } +- +- val = readl(mmio); + } + val >>= (8 * (off & 3)); + +@@ -156,7 +149,7 @@ static int bcma_extpci_write_config(stru + const void *buf, int len) + { + int err = -EINVAL; +- u32 addr = 0, val = 0; ++ u32 addr, val; + void __iomem *mmio = 0; + u16 chipid = pc->core->bus->chipinfo.id; + +@@ -164,16 +157,22 @@ static int bcma_extpci_write_config(stru + 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); +@@ -185,19 +184,17 @@ static int bcma_extpci_write_config(stru + 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; +@@ -205,13 +202,14 @@ static int bcma_extpci_write_config(stru + 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); + +@@ -282,7 +280,7 @@ static u8 __devinit bcma_find_pci_capabi + /* 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 */ +@@ -396,12 +394,19 @@ void __devinit bcma_core_pci_hostmode_in bcma_info(bus, "PCIEcore in host mode found\n"); @@ -1296,7 +1784,15 @@ pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL); if (!pc_host) { bcma_err(bus, "can not allocate memory"); -@@ -425,9 +425,9 @@ void __devinit bcma_core_pci_hostmode_in + 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; +@@ -425,9 +430,9 @@ void __devinit bcma_core_pci_hostmode_in pc_host->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED; /* Reset RC */ @@ -1304,11 +1800,11 @@ + usleep_range(3000, 5000); pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE); - udelay(1000); -+ usleep_range(1000, 2000); ++ msleep(50); pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST | BCMA_CORE_PCI_CTL_RST_OE); -@@ -452,6 +452,8 @@ void __devinit bcma_core_pci_hostmode_in +@@ -452,6 +457,8 @@ void __devinit bcma_core_pci_hostmode_in pc_host->mem_resource.start = BCMA_SOC_PCI_MEM; pc_host->mem_resource.end = BCMA_SOC_PCI_MEM + BCMA_SOC_PCI_MEM_SZ - 1; @@ -1317,7 +1813,7 @@ pci_membase_1G = BCMA_SOC_PCIE_DMA_H32; pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, tmp | BCMA_SOC_PCI_MEM); -@@ -459,6 +461,8 @@ void __devinit bcma_core_pci_hostmode_in +@@ -459,6 +466,8 @@ void __devinit bcma_core_pci_hostmode_in pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM; pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM + BCMA_SOC_PCI_MEM_SZ - 1; @@ -1326,7 +1822,7 @@ pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32; pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG; pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, -@@ -481,7 +485,7 @@ void __devinit bcma_core_pci_hostmode_in +@@ -481,10 +490,21 @@ void __devinit bcma_core_pci_hostmode_in * before issuing configuration requests to PCI Express * devices. */ @@ -1335,7 +1831,21 @@ bcma_core_pci_enable_crs(pc); -@@ -501,7 +505,7 @@ void __devinit bcma_core_pci_hostmode_in ++ 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)); +@@ -501,7 +521,7 @@ void __devinit bcma_core_pci_hostmode_in 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. */ @@ -1344,7 +1854,7 @@ register_pci_controller(&pc_host->pci_controller); return; } -@@ -534,7 +538,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ +@@ -534,7 +554,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ static void bcma_core_pci_fixup_addresses(struct pci_dev *dev) { struct resource *res; @@ -1353,7 +1863,7 @@ if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { /* This is not a device on the PCI-core bridge. */ -@@ -547,8 +551,12 @@ static void bcma_core_pci_fixup_addresse +@@ -547,8 +567,12 @@ static void bcma_core_pci_fixup_addresse for (pos = 0; pos < 6; pos++) { res = &dev->resource[pos]; @@ -1368,6 +1878,23 @@ } } DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_addresses); +@@ -569,7 +593,7 @@ int bcma_core_pci_plat_dev_init(struct p + 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; +@@ -588,6 +612,6 @@ int bcma_core_pci_pcibios_map_irq(const + + 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 +++ b/drivers/bcma/host_pci.c @@ -77,8 +77,8 @@ static void bcma_host_pci_write32(struct @@ -1425,14 +1952,16 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, -@@ -272,6 +273,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_ +@@ -272,7 +273,9 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, + { 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, }, + }; --- a/drivers/bcma/host_soc.c +++ b/drivers/bcma/host_soc.c @@ -143,7 +143,7 @@ static void bcma_host_soc_awrite32(struc @@ -1454,7 +1983,7 @@ #include <linux/bcma/bcma.h> #include <linux/slab.h> -@@ -80,6 +81,18 @@ struct bcma_device *bcma_find_core(struc +@@ -80,6 +81,37 @@ struct bcma_device *bcma_find_core(struc } EXPORT_SYMBOL_GPL(bcma_find_core); @@ -1470,13 +1999,52 @@ + 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) { struct bcma_device *core = container_of(dev, struct bcma_device, dev); -@@ -136,6 +149,33 @@ static int bcma_register_cores(struct bc +@@ -107,6 +139,11 @@ static int bcma_register_cores(struct bc + 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", bus->num, dev_id); +@@ -136,6 +173,41 @@ static int bcma_register_cores(struct bc dev_id++; } ++#ifdef CONFIG_BCMA_DRIVER_MIPS ++ if (bus->drv_cc.pflash.present) { ++ err = platform_device_register(&bcma_pflash_dev); ++ if (err) ++ bcma_err(bus, "Error registering parallel flash\n"); ++ } ++#endif ++ +#ifdef CONFIG_BCMA_SFLASH + if (bus->drv_cc.sflash.present) { + err = platform_device_register(&bcma_sflash_dev); @@ -1507,7 +2075,7 @@ return 0; } -@@ -148,6 +188,8 @@ static void bcma_unregister_cores(struct +@@ -148,6 +220,8 @@ static void bcma_unregister_cores(struct if (core->dev_registered) device_unregister(&core->dev); } @@ -1516,7 +2084,7 @@ } int __devinit bcma_bus_register(struct bcma_bus *bus) -@@ -166,6 +208,20 @@ int __devinit bcma_bus_register(struct b +@@ -166,6 +240,20 @@ int __devinit bcma_bus_register(struct b return -1; } @@ -1537,28 +2105,28 @@ /* Init CC core */ core = bcma_find_core(bus, bcma_cc_core_id(bus)); if (core) { -@@ -181,10 +237,17 @@ int __devinit bcma_bus_register(struct b +@@ -181,10 +269,17 @@ int __devinit bcma_bus_register(struct b } /* Init PCIE core */ - core = bcma_find_core(bus, BCMA_CORE_PCIE); + core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 0); -+ if (core) { + 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]); + } + + /* Init PCIE core */ + core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 1); - if (core) { -- bus->drv_pci.core = core; -- bcma_core_pci_init(&bus->drv_pci); ++ if (core) { + bus->drv_pci[1].core = core; + bcma_core_pci_init(&bus->drv_pci[1]); } /* Init GBIT MAC COMMON core */ -@@ -194,13 +257,6 @@ int __devinit bcma_bus_register(struct b +@@ -194,13 +289,6 @@ int __devinit bcma_bus_register(struct b bcma_core_gmac_cmn_init(&bus->drv_gmac_cmn); } @@ -1572,11 +2140,18 @@ /* Register found cores */ bcma_register_cores(bus); -@@ -211,7 +267,17 @@ int __devinit bcma_bus_register(struct b +@@ -211,7 +299,24 @@ int __devinit bcma_bus_register(struct b 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); @@ -1590,7 +2165,7 @@ } int __init bcma_bus_early_register(struct bcma_bus *bus, -@@ -248,18 +314,18 @@ int __init bcma_bus_early_register(struc +@@ -248,18 +353,18 @@ int __init bcma_bus_early_register(struc return -1; } @@ -1613,9 +2188,194 @@ } bcma_info(bus, "Early bus registered\n"); +--- a/drivers/bcma/scan.c ++++ b/drivers/bcma/scan.c +@@ -84,6 +84,8 @@ static const struct bcma_device_id_name + { 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" }, + }; + +@@ -137,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)) +@@ -159,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); +@@ -175,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) { +@@ -189,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)) +@@ -199,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; --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c -@@ -507,7 +507,9 @@ static bool bcma_sprom_onchip_available( +@@ -72,12 +72,12 @@ fail: + * R/W ops. + **************************************************/ + +-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)); + } + + /************************************************** +@@ -124,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; +@@ -154,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; + } + +@@ -208,15 +212,13 @@ static void bcma_sprom_extract_r8(struct + 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; +- + for (i = 0; i < 3; i++) { + v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i]; + *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v); + } + + SPEX(board_rev, SSB_SPROM8_BOARDREV, ~0, 0); ++ SPEX(board_type, SSB_SPROM1_SPID, ~0, 0); + + SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0, + SSB_SPROM4_TXPID2G0_SHIFT); +@@ -501,13 +503,15 @@ static bool bcma_sprom_onchip_available( + 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; @@ -1625,19 +2385,68 @@ present = chip_status & BCMA_CC_CHIPST_43228_OTP_PRESENT; break; default: -@@ -593,8 +595,11 @@ int bcma_sprom_get(struct bcma_bus *bus) +@@ -547,7 +551,9 @@ int bcma_sprom_get(struct bcma_bus *bus) + { + u16 offset = BCMA_CC_SPROM; + u16 *sprom; +- 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; +@@ -576,29 +582,37 @@ int bcma_sprom_get(struct bcma_bus *bus) + } + } + +- sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), +- GFP_KERNEL); +- if (!sprom) +- return -ENOMEM; +- + 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, false); + + 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; ++ ++ kfree(sprom); ++ } + + 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); - err = bcma_sprom_valid(sprom); +- err = bcma_sprom_valid(sprom); - if (err) +- goto out; +- +- bcma_sprom_extract_r8(bus, sprom); + if (err) { -+ bcma_warn(bus, "invalid sprom read from the PCIe card, try to use fallback sprom\n"); ++ 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); - goto out; ++ } else { ++ bcma_sprom_extract_r8(bus, sprom); ++ kfree(sprom); + } - bcma_sprom_extract_r8(bus, sprom); - +-out: +- kfree(sprom); + return err; + } --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h @@ -10,7 +10,7 @@ @@ -1649,15 +2458,25 @@ struct bcma_device; struct bcma_bus; -@@ -134,6 +134,7 @@ struct bcma_host_ops { +@@ -134,12 +134,17 @@ 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_ARM_CR4 0x83e ++#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 -@@ -157,6 +158,7 @@ struct bcma_host_ops { + + /* 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 +@@ -157,6 +162,7 @@ struct bcma_host_ops { /* Chip IDs of SoCs */ #define BCMA_CHIP_ID_BCM4706 0x5300 @@ -1665,7 +2484,7 @@ #define BCMA_CHIP_ID_BCM4716 0x4716 #define BCMA_PKG_ID_BCM4716 8 #define BCMA_PKG_ID_BCM4717 9 -@@ -166,7 +168,11 @@ struct bcma_host_ops { +@@ -166,7 +172,65 @@ struct bcma_host_ops { #define BCMA_CHIP_ID_BCM4749 0x4749 #define BCMA_CHIP_ID_BCM5356 0x5356 #define BCMA_CHIP_ID_BCM5357 0x5357 @@ -1674,10 +2493,64 @@ +#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; -@@ -251,7 +257,7 @@ struct bcma_bus { +@@ -251,7 +315,7 @@ struct bcma_bus { u8 num; struct bcma_drv_cc drv_cc; @@ -1686,7 +2559,7 @@ struct bcma_drv_mips drv_mips; struct bcma_drv_gmac_cmn drv_gmac_cmn; -@@ -345,6 +351,7 @@ extern void bcma_core_set_clockmode(stru +@@ -345,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); @@ -1706,6 +2579,15 @@ /** 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 /* NAND flash */ ++#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 @@ -100,6 +103,8 @@ #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 */ @@ -1755,9 +2637,24 @@ #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 */ -@@ -325,6 +356,60 @@ +@@ -299,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 */ +@@ -324,7 +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 */ +/* NAND flash MLC controller registers (corerev >= 38) */ +#define BCMA_CC_NAND_REVISION 0x0C00 @@ -1816,7 +2713,31 @@ /* Divider allocation in 4716/47162/5356 */ #define BCMA_CC_PMU5_MAINPLL_CPU 1 -@@ -415,6 +500,13 @@ +@@ -350,6 +442,23 @@ + #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 + /* HT clock for systems with PMU-enabled chipcommon */ +@@ -415,6 +524,44 @@ /* 4313 Chip specific ChipControl register bits */ #define BCMA_CCTRL_4313_12MA_LED_DRIVE 0x00000007 /* 12 mA drive strengh for later 4313 */ @@ -1827,10 +2748,41 @@ +#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) */ -@@ -425,11 +517,35 @@ struct bcma_chipcommon_pmu { +@@ -425,11 +572,36 @@ struct bcma_chipcommon_pmu { #ifdef CONFIG_BCMA_DRIVER_MIPS struct bcma_pflash { @@ -1849,6 +2801,7 @@ + u32 size; + + struct mtd_info *mtd; ++ void *priv; +}; +#endif + @@ -1866,7 +2819,7 @@ struct bcma_serial_port { void *regs; unsigned long clockspeed; -@@ -445,15 +561,30 @@ struct bcma_drv_cc { +@@ -445,15 +617,30 @@ struct bcma_drv_cc { u32 capabilities; u32 capabilities_ext; u8 setup_done:1; @@ -1897,7 +2850,7 @@ }; /* Register access */ -@@ -470,14 +601,16 @@ struct bcma_drv_cc { +@@ -470,14 +657,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); @@ -1916,7 +2869,7 @@ void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value); -@@ -490,9 +623,12 @@ u32 bcma_chipco_gpio_outen(struct bcma_d +@@ -490,9 +679,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); @@ -1929,9 +2882,24 @@ extern void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value); +@@ -504,4 +696,6 @@ extern void bcma_chipco_regctl_maskset(s + 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_ */ --- a/include/linux/bcma/bcma_driver_mips.h +++ b/include/linux/bcma/bcma_driver_mips.h -@@ -35,13 +35,15 @@ struct bcma_device; +@@ -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; @@ -1942,12 +2910,34 @@ #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 +@@ -179,6 +179,8 @@ struct pci_dev; + #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 + --- a/include/linux/bcma/bcma_regs.h +++ b/include/linux/bcma/bcma_regs.h @@ -11,11 +11,13 @@ diff --git a/target/linux/generic/patches-3.7/020-ssb_update.patch b/target/linux/generic/patches-3.7/020-ssb_update.patch index d44c812..54ea356 100644 --- a/target/linux/generic/patches-3.7/020-ssb_update.patch +++ b/target/linux/generic/patches-3.7/020-ssb_update.patch @@ -30,7 +30,7 @@ ARRAY_SIZE(wgt634u_devices)); --- a/drivers/ssb/Kconfig +++ b/drivers/ssb/Kconfig -@@ -136,6 +136,11 @@ config SSB_DRIVER_MIPS +@@ -136,10 +136,15 @@ config SSB_DRIVER_MIPS If unsure, say N @@ -42,6 +42,11 @@ # Assumption: We are on embedded, if we compile the MIPS core. config SSB_EMBEDDED bool +- depends on SSB_DRIVER_MIPS ++ depends on SSB_DRIVER_MIPS && SSB_PCICORE_HOSTMODE + default y + + config SSB_DRIVER_EXTIF @@ -160,4 +165,12 @@ config SSB_DRIVER_GIGE If unsure, say N @@ -98,7 +103,7 @@ #include "ssb_private.h" -@@ -280,10 +282,76 @@ static void calc_fast_powerup_delay(stru +@@ -280,13 +282,79 @@ static void calc_fast_powerup_delay(stru cc->fast_pwrup_delay = tmp; } @@ -174,7 +179,11 @@ + 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_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); @@ -333,16 +342,62 @@ /* Turn off UART clock before switching clocksource. */ --- a/drivers/ssb/driver_chipcommon_pmu.c +++ b/drivers/ssb/driver_chipcommon_pmu.c -@@ -346,6 +346,8 @@ static void ssb_pmu_pll_init(struct ssb_ +@@ -110,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) { +@@ -138,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); +@@ -249,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) { +@@ -275,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); +@@ -346,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", -@@ -434,6 +436,7 @@ static void ssb_pmu_resources_init(struc +- 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); + } + } + +@@ -434,6 +435,7 @@ static void ssb_pmu_resources_init(struc min_msk = 0xCBB; break; case 0x4322: @@ -350,7 +405,30 @@ /* We keep the default settings: * min_msk = 0xCBB * max_msk = 0x7FFFF -@@ -615,6 +618,33 @@ void ssb_pmu_set_ldo_paref(struct ssb_ch +@@ -469,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) { +@@ -523,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, +@@ -615,6 +616,32 @@ void ssb_pmu_set_ldo_paref(struct ssb_ch EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage); EXPORT_SYMBOL(ssb_pmu_set_ldo_paref); @@ -374,9 +452,8 @@ + case 0x5354: + ssb_pmu_get_alp_clock_clk0(cc); + default: -+ ssb_printk(KERN_ERR PFX -+ "ERROR: PMU alp clock unknown for device %04X\n", -+ bus->chip_id); ++ ssb_err("ERROR: PMU alp clock unknown for device %04X\n", ++ bus->chip_id); + return 0; + } +} @@ -384,7 +461,27 @@ u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc) { struct ssb_bus *bus = cc->dev->bus; -@@ -645,3 +675,32 @@ u32 ssb_pmu_get_controlclock(struct ssb_ +@@ -624,9 +651,8 @@ u32 ssb_pmu_get_cpu_clock(struct ssb_chi + /* 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; + } + } +@@ -639,9 +665,52 @@ u32 ssb_pmu_get_controlclock(struct ssb_ + 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; } } @@ -405,8 +502,23 @@ + pmu_ctl = SSB_CHIPCO_PMU_CTL_PLL_UPD; + break; + case 43222: -+ /* TODO: BCM43222 requires updating PLLs too */ -+ return; ++ 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", @@ -419,7 +531,7 @@ +EXPORT_SYMBOL_GPL(ssb_pmu_spuravoid_pllupdate); --- /dev/null +++ b/drivers/ssb/driver_chipcommon_sflash.c -@@ -0,0 +1,18 @@ +@@ -0,0 +1,166 @@ +/* + * Sonics Silicon Backplane + * ChipCommon serial flash interface @@ -431,9 +543,157 @@ + +#include "ssb_private.h" + ++static struct resource ssb_sflash_resource = { ++ .name = "ssb_sflash", ++ .start = SSB_FLASH2, ++ .end = 0, ++ .flags = IORESOURCE_MEM | IORESOURCE_READONLY, ++}; ++ ++struct platform_device ssb_sflash_dev = { ++ .name = "ssb_sflash", ++ .resource = &ssb_sflash_resource, ++ .num_resources = 1, ++}; ++ ++struct ssb_sflash_tbl_e { ++ char *name; ++ u32 id; ++ u32 blocksize; ++ u16 numblocks; ++}; ++ ++static const struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = { ++ { "M25P20", 0x11, 0x10000, 4, }, ++ { "M25P40", 0x12, 0x10000, 8, }, ++ ++ { "M25P16", 0x14, 0x10000, 32, }, ++ { "M25P32", 0x15, 0x10000, 64, }, ++ { "M25P64", 0x16, 0x10000, 128, }, ++ { "M25FL128", 0x17, 0x10000, 256, }, ++ { 0 }, ++}; ++ ++static const struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { ++ { "SST25WF512", 1, 0x1000, 16, }, ++ { "SST25VF512", 0x48, 0x1000, 16, }, ++ { "SST25WF010", 2, 0x1000, 32, }, ++ { "SST25VF010", 0x49, 0x1000, 32, }, ++ { "SST25WF020", 3, 0x1000, 64, }, ++ { "SST25VF020", 0x43, 0x1000, 64, }, ++ { "SST25WF040", 4, 0x1000, 128, }, ++ { "SST25VF040", 0x44, 0x1000, 128, }, ++ { "SST25VF040B", 0x8d, 0x1000, 128, }, ++ { "SST25WF080", 5, 0x1000, 256, }, ++ { "SST25VF080B", 0x8e, 0x1000, 256, }, ++ { "SST25VF016", 0x41, 0x1000, 512, }, ++ { "SST25VF032", 0x4a, 0x1000, 1024, }, ++ { "SST25VF064", 0x4b, 0x1000, 2048, }, ++ { 0 }, ++}; ++ ++static const struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { ++ { "AT45DB011", 0xc, 256, 512, }, ++ { "AT45DB021", 0x14, 256, 1024, }, ++ { "AT45DB041", 0x1c, 256, 2048, }, ++ { "AT45DB081", 0x24, 256, 4096, }, ++ { "AT45DB161", 0x2c, 512, 4096, }, ++ { "AT45DB321", 0x34, 512, 8192, }, ++ { "AT45DB642", 0x3c, 1024, 8192, }, ++ { 0 }, ++}; ++ ++static void ssb_sflash_cmd(struct ssb_chipcommon *cc, u32 opcode) ++{ ++ int i; ++ chipco_write32(cc, SSB_CHIPCO_FLASHCTL, ++ SSB_CHIPCO_FLASHCTL_START | opcode); ++ for (i = 0; i < 1000; i++) { ++ if (!(chipco_read32(cc, SSB_CHIPCO_FLASHCTL) & ++ SSB_CHIPCO_FLASHCTL_BUSY)) ++ return; ++ cpu_relax(); ++ } ++ pr_err("SFLASH control command failed (timeout)!\n"); ++} ++ +/* Initialize serial flash access */ +int ssb_sflash_init(struct ssb_chipcommon *cc) +{ ++ struct ssb_sflash *sflash = &cc->dev->bus->mipscore.sflash; ++ const struct ssb_sflash_tbl_e *e; ++ u32 id, id2; ++ ++ switch (cc->capabilities & SSB_CHIPCO_CAP_FLASHT) { ++ case SSB_CHIPCO_FLASHT_STSER: ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_DP); ++ ++ chipco_write32(cc, SSB_CHIPCO_FLASHADDR, 0); ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_RES); ++ id = chipco_read32(cc, SSB_CHIPCO_FLASHDATA); ++ ++ chipco_write32(cc, SSB_CHIPCO_FLASHADDR, 1); ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_RES); ++ id2 = chipco_read32(cc, SSB_CHIPCO_FLASHDATA); ++ ++ switch (id) { ++ case 0xbf: ++ for (e = ssb_sflash_sst_tbl; e->name; e++) { ++ if (e->id == id2) ++ break; ++ } ++ break; ++ case 0x13: ++ return -ENOTSUPP; ++ default: ++ for (e = ssb_sflash_st_tbl; e->name; e++) { ++ if (e->id == id) ++ break; ++ } ++ break; ++ } ++ if (!e->name) { ++ pr_err("Unsupported ST serial flash (id: 0x%X, id2: 0x%X)\n", ++ id, id2); ++ return -ENOTSUPP; ++ } ++ ++ break; ++ case SSB_CHIPCO_FLASHT_ATSER: ++ ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_AT_STATUS); ++ id = chipco_read32(cc, SSB_CHIPCO_FLASHDATA) & 0x3c; ++ ++ for (e = ssb_sflash_at_tbl; e->name; e++) { ++ if (e->id == id) ++ break; ++ } ++ if (!e->name) { ++ pr_err("Unsupported Atmel serial flash (id: 0x%X)\n", ++ id); ++ return -ENOTSUPP; ++ } ++ ++ break; ++ default: ++ pr_err("Unsupported flash type\n"); ++ return -ENOTSUPP; ++ } ++ ++ sflash->window = SSB_FLASH2; ++ sflash->blocksize = e->blocksize; ++ sflash->numblocks = e->numblocks; ++ sflash->size = sflash->blocksize * sflash->numblocks; ++ sflash->present = true; ++ ++ pr_info("Found %s serial flash (blocksize: 0x%X, blocks: %d)\n", ++ e->name, e->blocksize, e->numblocks); ++ ++ /* Prepare platform device, but don't register it yet. It's too early, ++ * malloc (required by device_private_init) is not available yet. */ ++ ssb_sflash_dev.resource[0].end = ssb_sflash_dev.resource[0].start + ++ sflash->size; ++ ssb_sflash_dev.dev.platform_data = sflash; ++ + pr_err("Serial flash support is not implemented yet!\n"); + + return -ENOTSUPP; @@ -537,7 +797,7 @@ } --- /dev/null +++ b/drivers/ssb/driver_gpio.c -@@ -0,0 +1,176 @@ +@@ -0,0 +1,210 @@ +/* + * Sonics Silicon Backplane + * GPIO driver @@ -614,6 +874,16 @@ + 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; @@ -626,6 +896,7 @@ + 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 @@ -674,6 +945,16 @@ + 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; @@ -684,6 +965,7 @@ + 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 @@ -714,9 +996,88 @@ + + 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 -@@ -178,9 +178,9 @@ static void ssb_mips_serial_init(struct +@@ -10,6 +10,7 @@ + + #include <linux/ssb/ssb.h> + ++#include <linux/mtd/physmap.h> + #include <linux/serial.h> + #include <linux/serial_core.h> + #include <linux/serial_reg.h> +@@ -17,6 +18,25 @@ + + #include "ssb_private.h" + ++static const char * const part_probes[] = { "bcm47xxpart", NULL }; ++ ++static struct physmap_flash_data ssb_pflash_data = { ++ .part_probe_types = part_probes, ++}; ++ ++static struct resource ssb_pflash_resource = { ++ .name = "ssb_pflash", ++ .flags = IORESOURCE_MEM, ++}; ++ ++struct platform_device ssb_pflash_dev = { ++ .name = "physmap-flash", ++ .dev = { ++ .platform_data = &ssb_pflash_data, ++ }, ++ .resource = &ssb_pflash_resource, ++ .num_resources = 1, ++}; + + static inline u32 mips_read32(struct ssb_mipscore *mcore, + u16 offset) +@@ -147,21 +167,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 +199,9 @@ static void ssb_mips_serial_init(struct { struct ssb_bus *bus = mcore->dev->bus; @@ -728,23 +1089,27 @@ mcore->nr_serial_ports = ssb_chipco_serial_init(&bus->chipco, mcore->serial_ports); else mcore->nr_serial_ports = 0; -@@ -191,10 +191,11 @@ static void ssb_mips_flash_detect(struct +@@ -189,32 +210,43 @@ static void ssb_mips_serial_init(struct + static void ssb_mips_flash_detect(struct ssb_mipscore *mcore) + { struct ssb_bus *bus = mcore->dev->bus; ++ struct ssb_pflash *pflash = &mcore->pflash; /* When there is no chipcommon on the bus there is 4MB flash */ - if (!bus->chipco.dev) { - mcore->flash_buswidth = 2; - mcore->flash_window = SSB_FLASH1; - mcore->flash_window_size = SSB_FLASH1_SZ; +- return; + if (!ssb_chipco_available(&bus->chipco)) { -+ mcore->pflash.present = true; -+ mcore->pflash.buswidth = 2; -+ mcore->pflash.window = SSB_FLASH1; -+ mcore->pflash.window_size = SSB_FLASH1_SZ; - return; ++ pflash->present = true; ++ pflash->buswidth = 2; ++ pflash->window = SSB_FLASH1; ++ pflash->window_size = SSB_FLASH1_SZ; ++ goto ssb_pflash; } -@@ -202,17 +203,19 @@ static void ssb_mips_flash_detect(struct + /* There is ChipCommon, so use it to read info about flash */ switch (bus->chipco.capabilities & SSB_CHIPCO_CAP_FLASHT) { case SSB_CHIPCO_FLASHT_STSER: case SSB_CHIPCO_FLASHT_ATSER: @@ -756,20 +1121,29 @@ pr_debug("Found parallel flash\n"); - mcore->flash_window = SSB_FLASH2; - mcore->flash_window_size = SSB_FLASH2_SZ; -+ mcore->pflash.present = true; -+ mcore->pflash.window = SSB_FLASH2; -+ mcore->pflash.window_size = SSB_FLASH2_SZ; ++ pflash->present = true; ++ pflash->window = SSB_FLASH2; ++ pflash->window_size = SSB_FLASH2_SZ; if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG) & SSB_CHIPCO_CFG_DS16) == 0) - mcore->flash_buswidth = 1; -+ mcore->pflash.buswidth = 1; ++ pflash->buswidth = 1; else - mcore->flash_buswidth = 2; -+ mcore->pflash.buswidth = 2; ++ pflash->buswidth = 2; break; } ++ ++ssb_pflash: ++ if (pflash->present) { ++ ssb_pflash_data.width = pflash->buswidth; ++ ssb_pflash_resource.start = pflash->window; ++ ssb_pflash_resource.end = pflash->window + pflash->window_size; ++ } } -@@ -225,9 +228,9 @@ u32 ssb_cpu_clock(struct ssb_mipscore *m + + u32 ssb_cpu_clock(struct ssb_mipscore *mcore) +@@ -225,9 +257,9 @@ u32 ssb_cpu_clock(struct ssb_mipscore *m if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU) return ssb_pmu_get_cpu_clock(&bus->chipco); @@ -781,7 +1155,16 @@ ssb_chipco_get_clockcpu(&bus->chipco, &pll_type, &n, &m); } else return 0; -@@ -263,9 +266,9 @@ void ssb_mipscore_init(struct ssb_mipsco +@@ -255,7 +287,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); +@@ -263,9 +295,9 @@ void ssb_mipscore_init(struct ssb_mipsco hz = 100000000; ns = 1000000000 / hz; @@ -793,6 +1176,71 @@ 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 */ +@@ -303,7 +335,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 @@ @@ -809,7 +1257,7 @@ #include <linux/ssb/ssb.h> #include <linux/ssb/ssb_embedded.h> #include <linux/ssb/ssb_driver_pci.h> -@@ -32,6 +34,39 @@ int ssb_watchdog_timer_set(struct ssb_bu +@@ -32,6 +34,38 @@ int ssb_watchdog_timer_set(struct ssb_bu } EXPORT_SYMBOL(ssb_watchdog_timer_set); @@ -836,9 +1284,8 @@ + bus->busnumber, &wdt, + sizeof(wdt)); + if (IS_ERR(pdev)) { -+ ssb_dprintk(KERN_INFO PFX -+ "can not register watchdog device, err: %li\n", -+ PTR_ERR(pdev)); ++ ssb_dbg("can not register watchdog device, err: %li\n", ++ PTR_ERR(pdev)); + return PTR_ERR(pdev); + } + @@ -859,7 +1306,18 @@ #include <linux/ssb/ssb.h> #include <linux/ssb/ssb_regs.h> #include <linux/ssb/ssb_driver_gige.h> -@@ -433,6 +434,11 @@ static void ssb_devices_unregister(struc +@@ -274,8 +275,8 @@ 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_device_put(sdev); +@@ -433,10 +434,23 @@ static void ssb_devices_unregister(struc if (sdev->dev) device_unregister(sdev->dev); } @@ -871,7 +1329,63 @@ } void ssb_bus_unregister(struct ssb_bus *bus) -@@ -561,6 +567,8 @@ static int __devinit ssb_attach_queued_b + { ++ 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); +@@ -482,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; + } +@@ -522,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; +@@ -534,6 +545,22 @@ static int ssb_devices_register(struct s + dev_idx++; + } + ++#ifdef CONFIG_SSB_DRIVER_MIPS ++ if (bus->mipscore.pflash.present) { ++ err = platform_device_register(&ssb_pflash_dev); ++ if (err) ++ pr_err("Error registering parallel flash\n"); ++ } ++#endif ++ ++#ifdef CONFIG_SSB_SFLASH ++ if (bus->mipscore.sflash.present) { ++ err = platform_device_register(&ssb_sflash_dev); ++ if (err) ++ pr_err("Error registering serial flash\n"); ++ } ++#endif ++ + return 0; + error: + /* Unwind the already registered devices. */ +@@ -561,6 +588,8 @@ static int __devinit ssb_attach_queued_b if (err) goto error; ssb_pcicore_init(&bus->pcicore); @@ -880,7 +1394,7 @@ ssb_bus_may_powerdown(bus); err = ssb_devices_register(bus); -@@ -796,7 +804,14 @@ static int __devinit ssb_bus_register(st +@@ -796,7 +825,13 @@ static int __devinit ssb_bus_register(st if (err) goto err_pcmcia_exit; ssb_chipcommon_init(&bus->chipco); @@ -888,14 +1402,62 @@ ssb_mipscore_init(&bus->mipscore); + err = ssb_gpio_init(bus); + if (err == -ENOTSUPP) -+ ssb_dprintk(KERN_DEBUG PFX "GPIO driver not activated\n"); ++ ssb_dbg("GPIO driver not activated\n"); + else if (err) -+ ssb_dprintk(KERN_ERR PFX -+ "Error registering GPIO driver: %i\n", err); ++ ssb_dbg("Error registering GPIO driver: %i\n", err); err = ssb_fetch_invariants(bus, get_invariants); if (err) { ssb_bus_may_powerdown(bus); -@@ -1118,8 +1133,7 @@ static u32 ssb_tmslow_reject_bitmask(str +@@ -847,11 +882,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; +@@ -872,8 +907,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; +@@ -895,8 +930,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; +@@ -915,8 +950,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; +@@ -1118,8 +1153,7 @@ static u32 ssb_tmslow_reject_bitmask(str case SSB_IDLOW_SSBREV_27: /* same here */ return SSB_TMSLOW_REJECT; /* this is a guess */ default: @@ -905,9 +1467,589 @@ } return (SSB_TMSLOW_REJECT | SSB_TMSLOW_REJECT_23); } +@@ -1311,7 +1345,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); +@@ -1334,7 +1368,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); +@@ -1442,15 +1476,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 +@@ -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); +@@ -231,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 word; +@@ -278,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; +@@ -286,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); +@@ -309,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; + } + +@@ -339,10 +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; + u16 loc[3]; + + if (out->revision == 3) /* rev 3 moved MAC */ +@@ -352,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, +@@ -372,6 +384,7 @@ 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(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); +@@ -398,8 +411,7 @@ 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); ++ + SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8); + SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0); + +@@ -410,6 +422,8 @@ static void sprom_extract_r123(struct ss + 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 */ +@@ -454,23 +468,20 @@ 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(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8); + SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0); +@@ -530,7 +541,7 @@ static void sprom_extract_r45(struct ssb + static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) + { + int i; +- 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 +@@ -539,11 +550,10 @@ static void sprom_extract_r8(struct ssb_ + 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); +- } ++ 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); +@@ -743,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); + +@@ -752,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) { +@@ -769,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); + } +@@ -791,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! */ +@@ -810,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) +@@ -835,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); +--- a/drivers/ssb/pcihost_wrapper.c ++++ b/drivers/ssb/pcihost_wrapper.c +@@ -38,7 +38,7 @@ static int ssb_pcihost_resume(struct pci + struct ssb_bus *ssb = pci_get_drvdata(dev); + int err; + +- pci_set_power_state(dev, 0); ++ pci_set_power_state(dev, PCI_D0); + err = pci_enable_device(dev); + if (err) + return err; +--- a/drivers/ssb/pcmcia.c ++++ b/drivers/ssb/pcmcia.c +@@ -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; +@@ -700,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; +@@ -722,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; + } +@@ -733,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; + } +@@ -843,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 +@@ -125,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; +@@ -152,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; +@@ -320,15 +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) { +@@ -370,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; + } + } +@@ -379,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; +@@ -388,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; +@@ -398,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; +@@ -420,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/sprom.c ++++ b/drivers/ssb/sprom.c +@@ -54,7 +54,7 @@ static int hex2sprom(u16 *sprom, const c + while (cnt < sprom_size_words) { + memcpy(tmp, dump, 4); + dump += 4; +- err = strict_strtoul(tmp, 16, &parsed); ++ err = kstrtoul(tmp, 16, &parsed); + if (err) + return err; + sprom[cnt++] = swab16((u16)parsed); +@@ -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 -@@ -3,6 +3,7 @@ +@@ -3,21 +3,33 @@ #include <linux/ssb/ssb.h> #include <linux/types.h> @@ -915,7 +2057,37 @@ #define PFX "ssb: " -@@ -210,5 +211,63 @@ static inline void b43_pci_ssb_bridge_ex + + #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 +@@ -210,5 +222,76 @@ static inline void b43_pci_ssb_bridge_ex /* 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); @@ -936,6 +2108,14 @@ +} +#endif /* CONFIG_SSB_SFLASH */ + ++#ifdef CONFIG_SSB_DRIVER_MIPS ++extern struct platform_device ssb_pflash_dev; ++#endif ++ ++#ifdef CONFIG_SSB_SFLASH ++extern struct platform_device ssb_sflash_dev; ++#endif ++ +#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); @@ -971,11 +2151,16 @@ + +#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_ */ @@ -992,7 +2177,85 @@ #include <linux/ssb/ssb_regs.h> -@@ -432,7 +434,11 @@ struct ssb_bus { +@@ -24,9 +26,9 @@ struct ssb_sprom_core_pwr_info { + + struct ssb_sprom { + u8 revision; +- 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 */ +@@ -338,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 */ +@@ -432,7 +482,11 @@ struct ssb_bus { #ifdef CONFIG_SSB_EMBEDDED /* Lock for GPIO register access. */ spinlock_t gpio_lock; @@ -1135,9 +2398,51 @@ + #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 +@@ -97,21 +97,16 @@ static inline bool ssb_gige_must_flush_p + return 0; + } + +-#ifdef CONFIG_BCM47XX +-#include <asm/mach-bcm47xx/nvram.h> + /* 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); +@@ -175,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 -@@ -13,6 +13,12 @@ struct ssb_serial_port { +@@ -13,6 +13,24 @@ struct ssb_serial_port { unsigned int reg_shift; }; @@ -1147,10 +2452,22 @@ + u32 window; + u32 window_size; +}; ++ ++#ifdef CONFIG_SSB_SFLASH ++struct ssb_sflash { ++ bool present; ++ u32 window; ++ u32 blocksize; ++ u16 numblocks; ++ u32 size; ++ ++ void *priv; ++}; ++#endif struct ssb_mipscore { struct ssb_device *dev; -@@ -20,9 +26,7 @@ struct ssb_mipscore { +@@ -20,9 +38,10 @@ struct ssb_mipscore { int nr_serial_ports; struct ssb_serial_port serial_ports[4]; @@ -1158,12 +2475,35 @@ - u32 flash_window; - u32 flash_window_size; + struct ssb_pflash pflash; ++#ifdef CONFIG_SSB_SFLASH ++ struct ssb_sflash sflash; ++#endif }; extern void ssb_mipscore_init(struct ssb_mipscore *mcore); +@@ -41,6 +60,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 -@@ -289,11 +289,11 @@ +@@ -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 +@@ -289,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 */ @@ -1180,7 +2520,7 @@ #define SSB_SPROM4_AGAIN01 0x005E /* Antenna Gain (in dBm Q5.2) */ #define SSB_SPROM4_AGAIN0 0x00FF /* Antenna 0 */ #define SSB_SPROM4_AGAIN0_SHIFT 0 -@@ -485,7 +485,7 @@ +@@ -485,7 +486,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 @@ -1223,46 +2563,3 @@ break; #endif } ---- a/drivers/ssb/pci.c -+++ b/drivers/ssb/pci.c -@@ -339,6 +339,21 @@ 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; -@@ -398,8 +413,7 @@ 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); -+ - SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8); - SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0); - -@@ -410,6 +424,8 @@ static void sprom_extract_r123(struct ss - 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 */ diff --git a/target/linux/generic/patches-3.7/025-bcma_backport.patch b/target/linux/generic/patches-3.7/025-bcma_backport.patch index 3cba3ca..950ac93 100644 --- a/target/linux/generic/patches-3.7/025-bcma_backport.patch +++ b/target/linux/generic/patches-3.7/025-bcma_backport.patch @@ -1,6 +1,25 @@ +--- 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/drivers/bcma/Kconfig +++ b/drivers/bcma/Kconfig -@@ -65,6 +65,14 @@ config BCMA_DRIVER_GMAC_CMN +@@ -26,6 +26,7 @@ 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" +@@ -65,6 +66,14 @@ config BCMA_DRIVER_GMAC_CMN If unsure, say N @@ -27,7 +46,16 @@ obj-$(CONFIG_BCMA) += bcma.o --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h -@@ -31,6 +31,8 @@ int __init bcma_bus_early_register(struc +@@ -22,6 +22,8 @@ + struct bcma_bus; + + /* main.c */ ++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, +@@ -31,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 @@ -36,7 +64,11 @@ /* scan.c */ int bcma_bus_scan(struct bcma_bus *bus); -@@ -48,8 +50,8 @@ void bcma_chipco_serial_init(struct bcma +@@ -45,11 +49,12 @@ int bcma_sprom_get(struct bcma_bus *bus) + /* driver_chipcommon.c */ + #ifdef CONFIG_BCMA_DRIVER_MIPS + void bcma_chipco_serial_init(struct bcma_drv_cc *cc); ++extern struct platform_device bcma_pflash_dev; #endif /* CONFIG_BCMA_DRIVER_MIPS */ /* driver_chipcommon_pmu.c */ @@ -47,7 +79,7 @@ #ifdef CONFIG_BCMA_SFLASH /* driver_chipcommon_sflash.c */ -@@ -84,9 +86,21 @@ extern void __exit bcma_host_pci_exit(vo +@@ -84,9 +89,26 @@ extern void __exit bcma_host_pci_exit(vo /* driver_pci.c */ u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address); @@ -61,14 +93,89 @@ +#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 +@@ -9,6 +9,25 @@ + #include <linux/export.h> + #include <linux/bcma/bcma.h> + ++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,13 +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); + +@@ -43,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)); +@@ -104,7 +126,13 @@ void bcma_core_pll_ctl(struct bcma_devic + if (i) + bcma_err(core->bus, "PLL enable timeout\n"); + } else { +- 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); --- a/drivers/bcma/driver_chipcommon.c +++ b/drivers/bcma/driver_chipcommon.c @@ -4,12 +4,15 @@ @@ -87,7 +194,7 @@ #include <linux/bcma/bcma.h> static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, -@@ -22,20 +25,120 @@ static inline u32 bcma_cc_write32_masked +@@ -22,23 +25,130 @@ static inline u32 bcma_cc_write32_masked return value; } @@ -210,9 +317,21 @@ + 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); -@@ -56,15 +159,33 @@ void bcma_core_chipcommon_init(struct bc +- 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) +@@ -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))); } @@ -249,7 +368,7 @@ } void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value) -@@ -84,28 +205,99 @@ u32 bcma_chipco_gpio_in(struct bcma_drv_ +@@ -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) { @@ -354,7 +473,7 @@ } #ifdef CONFIG_BCMA_DRIVER_MIPS -@@ -118,8 +310,7 @@ void bcma_chipco_serial_init(struct bcma +@@ -118,8 +317,7 @@ void bcma_chipco_serial_init(struct bcma struct bcma_serial_port *ports = cc->serial_ports; if (ccrev >= 11 && ccrev != 15) { @@ -364,8 +483,40 @@ if (ccrev >= 21) { /* Turn off UART clock before switching clocksource. */ bcma_cc_write32(cc, BCMA_CC_CORECTL, +@@ -141,7 +339,7 @@ void bcma_chipco_serial_init(struct bcma + 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_nflash.c +++ b/drivers/bcma/driver_chipcommon_nflash.c +@@ -5,11 +5,11 @@ + * Licensed under the GNU/GPL. See COPYING for details. + */ + ++#include "bcma_private.h" ++ + #include <linux/platform_device.h> + #include <linux/bcma/bcma.h> + +-#include "bcma_private.h" +- + struct platform_device bcma_nflash_dev = { + .name = "bcma_nflash", + .num_resources = 0, +@@ -21,7 +21,7 @@ int bcma_nflash_init(struct bcma_drv_cc + struct bcma_bus *bus = cc->core->bus; + + if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4706 && +- cc->core->id.rev != 0x38) { ++ cc->core->id.rev != 38) { + bcma_err(bus, "NAND flash on unsupported board!\n"); + return -ENOTSUPP; + } @@ -32,6 +32,9 @@ int bcma_nflash_init(struct bcma_drv_cc } @@ -393,7 +544,143 @@ void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value) { -@@ -144,7 +145,7 @@ static void bcma_pmu_workarounds(struct +@@ -55,6 +56,109 @@ void bcma_chipco_regctl_maskset(struct b + } + EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset); + ++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 BCMA_CHIP_ID_BCM43142: ++ if (xtalfreq == 0) ++ xtalfreq = 20000; ++ bcma_pmu2_pll_init0(cc, xtalfreq); ++ break; ++ } ++} ++ + static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) + { + struct bcma_bus *bus = cc->core->bus; +@@ -65,6 +169,25 @@ static void bcma_pmu_resources_init(stru + min_msk = 0x200D; + max_msk = 0xFFFF; + 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: + bcma_debug(bus, "PMU resource config unknown or not needed for device 0x%04X\n", + bus->chipinfo.id); +@@ -144,7 +267,7 @@ static void bcma_pmu_workarounds(struct } } @@ -402,7 +689,7 @@ { u32 pmucap; -@@ -153,7 +154,10 @@ void bcma_pmu_init(struct bcma_drv_cc *c +@@ -153,7 +276,10 @@ void bcma_pmu_init(struct bcma_drv_cc *c bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n", cc->pmu.rev, pmucap); @@ -413,7 +700,12 @@ if (cc->pmu.rev == 1) bcma_cc_mask32(cc, BCMA_CC_PMU_CTL, ~BCMA_CC_PMU_CTL_NOILPONW); -@@ -165,24 +169,40 @@ void bcma_pmu_init(struct bcma_drv_cc *c +@@ -161,28 +287,45 @@ void bcma_pmu_init(struct bcma_drv_cc *c + bcma_cc_set32(cc, BCMA_CC_PMU_CTL, + BCMA_CC_PMU_CTL_NOILPONW); + ++ bcma_pmu_pll_init(cc); + bcma_pmu_resources_init(cc); bcma_pmu_workarounds(cc); } @@ -459,7 +751,7 @@ default: bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n", bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK); -@@ -193,7 +213,7 @@ u32 bcma_pmu_alp_clock(struct bcma_drv_c +@@ -193,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. */ @@ -468,7 +760,7 @@ { u32 tmp, div, ndiv, p1, p2, fc; struct bcma_bus *bus = cc->core->bus; -@@ -222,14 +242,14 @@ static u32 bcma_pmu_clock(struct bcma_dr +@@ -222,14 +365,14 @@ static u32 bcma_pmu_clock(struct bcma_dr ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT; /* Do calculation in Mhz */ @@ -485,16 +777,16 @@ { u32 tmp, ndiv, p1div, p2div; u32 clock; -@@ -260,7 +280,7 @@ static u32 bcma_pmu_clock_bcm4706(struct +@@ -260,7 +403,7 @@ static u32 bcma_pmu_clock_bcm4706(struct } /* query bus clock frequency for PMU-enabled chipcommon */ -static u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc) -+static u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc) ++u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc) { struct bcma_bus *bus = cc->core->bus; -@@ -268,40 +288,42 @@ static u32 bcma_pmu_get_clockcontrol(str +@@ -268,40 +411,43 @@ static u32 bcma_pmu_get_clockcontrol(str case BCMA_CHIP_ID_BCM4716: case BCMA_CHIP_ID_BCM4748: case BCMA_CHIP_ID_BCM47162: @@ -528,6 +820,7 @@ } return BCMA_CC_PMU_HT_CLOCK; } ++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) @@ -548,7 +841,7 @@ BCMA_CC_PMU4706_MAINPLL_PLL0, BCMA_CC_PMU5_MAINPLL_CPU); case BCMA_CHIP_ID_BCM5356: -@@ -316,10 +338,11 @@ u32 bcma_pmu_get_clockcpu(struct bcma_dr +@@ -316,10 +462,11 @@ u32 bcma_pmu_get_clockcpu(struct bcma_dr break; } @@ -562,7 +855,7 @@ } static void bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc *cc, u32 offset, -@@ -365,7 +388,7 @@ void bcma_pmu_spuravoid_pllupdate(struct +@@ -365,7 +512,7 @@ void bcma_pmu_spuravoid_pllupdate(struct tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT; bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp); @@ -571,7 +864,7 @@ break; case BCMA_CHIP_ID_BCM4331: -@@ -386,7 +409,7 @@ void bcma_pmu_spuravoid_pllupdate(struct +@@ -386,7 +533,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 0x03000a08); } @@ -580,7 +873,7 @@ break; case BCMA_CHIP_ID_BCM43224: -@@ -419,7 +442,7 @@ void bcma_pmu_spuravoid_pllupdate(struct +@@ -419,7 +566,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 0x88888815); } @@ -589,7 +882,7 @@ break; case BCMA_CHIP_ID_BCM4716: -@@ -453,7 +476,7 @@ void bcma_pmu_spuravoid_pllupdate(struct +@@ -453,7 +600,7 @@ void bcma_pmu_spuravoid_pllupdate(struct 0x88888815); } @@ -598,7 +891,7 @@ break; case BCMA_CHIP_ID_BCM43227: -@@ -489,7 +512,7 @@ void bcma_pmu_spuravoid_pllupdate(struct +@@ -489,7 +636,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 0x88888815); } @@ -609,8 +902,17 @@ bcma_err(bus, "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n", --- a/drivers/bcma/driver_chipcommon_sflash.c +++ b/drivers/bcma/driver_chipcommon_sflash.c -@@ -12,7 +12,7 @@ +@@ -5,14 +5,14 @@ + * Licensed under the GNU/GPL. See COPYING for details. + */ + ++#include "bcma_private.h" ++ + #include <linux/platform_device.h> + #include <linux/bcma/bcma.h> +-#include "bcma_private.h" +- static struct resource bcma_sflash_resource = { .name = "bcma_sflash", - .start = BCMA_SFLASH, @@ -618,11 +920,13 @@ .end = 0, .flags = IORESOURCE_MEM | IORESOURCE_READONLY, }; -@@ -31,15 +31,42 @@ struct bcma_sflash_tbl_e { +@@ -30,16 +30,43 @@ struct bcma_sflash_tbl_e { + u16 numblocks; }; - static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { +-static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { - { "", 0x14, 0x10000, 32, }, ++static const struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { + { "M25P20", 0x11, 0x10000, 4, }, + { "M25P40", 0x12, 0x10000, 8, }, + @@ -633,7 +937,8 @@ { 0 }, }; - static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { +-static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { ++static const struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { + { "SST25WF512", 1, 0x1000, 16, }, + { "SST25VF512", 0x48, 0x1000, 16, }, + { "SST25WF010", 2, 0x1000, 32, }, @@ -651,7 +956,8 @@ { 0 }, }; - static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { +-static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { ++static const struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { + { "AT45DB011", 0xc, 256, 512, }, + { "AT45DB021", 0x14, 256, 1024, }, + { "AT45DB041", 0x1c, 256, 2048, }, @@ -662,6 +968,15 @@ { 0 }, }; +@@ -62,7 +89,7 @@ int bcma_sflash_init(struct bcma_drv_cc + { + struct bcma_bus *bus = cc->core->bus; + struct bcma_sflash *sflash = &cc->sflash; +- struct bcma_sflash_tbl_e *e; ++ const struct bcma_sflash_tbl_e *e; + u32 id, id2; + + switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { @@ -84,6 +111,8 @@ int bcma_sflash_init(struct bcma_drv_cc break; } @@ -682,7 +997,7 @@ sflash->size = sflash->blocksize * sflash->numblocks; --- /dev/null +++ b/drivers/bcma/driver_gpio.c -@@ -0,0 +1,98 @@ +@@ -0,0 +1,114 @@ +/* + * Broadcom specific AMBA + * GPIO driver @@ -758,6 +1073,16 @@ + 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; @@ -770,6 +1095,7 @@ + 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 @@ -781,9 +1107,48 @@ + + 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 -@@ -74,11 +74,16 @@ static u32 bcma_core_mips_irqflag(struct +@@ -14,11 +14,33 @@ + + #include <linux/bcma/bcma.h> + ++#include <linux/mtd/physmap.h> ++#include <linux/platform_device.h> + #include <linux/serial.h> + #include <linux/serial_core.h> + #include <linux/serial_reg.h> + #include <linux/time.h> + ++static const char * const part_probes[] = { "bcm47xxpart", NULL }; ++ ++static struct physmap_flash_data bcma_pflash_data = { ++ .part_probe_types = part_probes, ++}; ++ ++static struct resource bcma_pflash_resource = { ++ .name = "bcma_pflash", ++ .flags = IORESOURCE_MEM, ++}; ++ ++struct platform_device bcma_pflash_dev = { ++ .name = "physmap-flash", ++ .dev = { ++ .platform_data = &bcma_pflash_data, ++ }, ++ .resource = &bcma_pflash_resource, ++ .num_resources = 1, ++}; ++ + /* The 47162a0 hangs when reading MIPS DMP registers registers */ + static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev) + { +@@ -74,28 +96,41 @@ static u32 bcma_core_mips_irqflag(struct return dev->core_index; flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30); @@ -799,9 +1164,11 @@ + * If disabled, 5 is returned. + * If not supported, 6 is returned. */ - unsigned int bcma_core_mips_irq(struct bcma_device *dev) +-unsigned int bcma_core_mips_irq(struct bcma_device *dev) ++static unsigned int bcma_core_mips_irq(struct bcma_device *dev) { -@@ -87,13 +92,15 @@ unsigned int bcma_core_mips_irq(struct b + struct bcma_device *mdev = dev->bus->drv_mips.core; + u32 irqflag; unsigned int irq; irqflag = bcma_core_mips_irqflag(dev); @@ -816,10 +1183,19 @@ - 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_mips_irq); ++EXPORT_SYMBOL(bcma_core_irq); -@@ -114,7 +121,7 @@ static void bcma_core_mips_set_irq(struc + static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq) + { +@@ -114,7 +149,7 @@ 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)); @@ -828,7 +1204,7 @@ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0); /* assign the new one */ -@@ -123,9 +130,9 @@ static void bcma_core_mips_set_irq(struc +@@ -123,9 +158,9 @@ static void bcma_core_mips_set_irq(struc bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) | (1 << irqflag)); } else { @@ -841,7 +1217,7 @@ struct bcma_device *core; /* backplane irq line is in use, find out who uses -@@ -133,7 +140,7 @@ static void bcma_core_mips_set_irq(struc +@@ -133,7 +168,7 @@ static void bcma_core_mips_set_irq(struc */ list_for_each_entry(core, &bus->cores, list) { if ((1 << bcma_core_mips_irqflag(core)) == @@ -850,7 +1226,7 @@ bcma_core_mips_set_irq(core, 0); break; } -@@ -143,15 +150,31 @@ static void bcma_core_mips_set_irq(struc +@@ -143,15 +178,31 @@ static void bcma_core_mips_set_irq(struc 1 << irqflag); } @@ -885,7 +1261,7 @@ for (i = 0; i <= 6; i++) printk(" %s%s", irq_name[i], i == irq ? "*" : " "); printk("\n"); -@@ -171,7 +194,7 @@ u32 bcma_cpu_clock(struct bcma_drv_mips +@@ -171,7 +222,7 @@ u32 bcma_cpu_clock(struct bcma_drv_mips struct bcma_bus *bus = mcore->core->bus; if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU) @@ -894,11 +1270,12 @@ bcma_err(bus, "No PMU available, need this to get the cpu clock\n"); return 0; -@@ -181,85 +204,109 @@ EXPORT_SYMBOL(bcma_cpu_clock); +@@ -181,85 +232,143 @@ EXPORT_SYMBOL(bcma_cpu_clock); static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore) { struct bcma_bus *bus = mcore->core->bus; + struct bcma_drv_cc *cc = &bus->drv_cc; ++ struct bcma_pflash *pflash = &cc->pflash; - switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) { + switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { @@ -912,18 +1289,23 @@ bcma_debug(bus, "Found parallel flash\n"); - bus->drv_cc.pflash.window = 0x1c000000; - bus->drv_cc.pflash.window_size = 0x02000000; -+ cc->pflash.present = true; -+ cc->pflash.window = BCMA_SOC_FLASH2; -+ cc->pflash.window_size = BCMA_SOC_FLASH2_SZ; ++ pflash->present = true; ++ pflash->window = BCMA_SOC_FLASH2; ++ pflash->window_size = BCMA_SOC_FLASH2_SZ; - if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) & + if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) & BCMA_CC_FLASH_CFG_DS) == 0) - bus->drv_cc.pflash.buswidth = 1; -+ cc->pflash.buswidth = 1; ++ pflash->buswidth = 1; else - bus->drv_cc.pflash.buswidth = 2; -+ cc->pflash.buswidth = 2; ++ pflash->buswidth = 2; ++ ++ bcma_pflash_data.width = pflash->buswidth; ++ bcma_pflash_resource.start = pflash->window; ++ bcma_pflash_resource.end = pflash->window + pflash->window_size; ++ break; default: bcma_err(bus, "Flash type not supported\n"); @@ -954,6 +1336,32 @@ + 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"); ++ } ++} ++ void bcma_core_mips_init(struct bcma_drv_mips *mcore) { struct bcma_bus *bus; @@ -998,6 +1406,8 @@ - break; + bcma_core_mips_early_init(mcore); + ++ bcma_fix_i2s_irqflag(bus); ++ + switch (bus->chipinfo.id) { + case BCMA_CHIP_ID_BCM4716: + case BCMA_CHIP_ID_BCM4748: @@ -1034,7 +1444,7 @@ + break; + default: + list_for_each_entry(core, &bus->cores, list) { -+ core->irq = bcma_core_mips_irq(core) + 2; ++ core->irq = bcma_core_irq(core); } + bcma_err(bus, + "Unknown device (0x%x) found, can not configure IRQs\n", @@ -1065,7 +1475,130 @@ bcma_core_enable(pc->core, 0); return !mips_busprobe32(tmp, pc->core->io_addr); -@@ -396,6 +391,11 @@ void __devinit bcma_core_pci_hostmode_in +@@ -99,19 +94,19 @@ static int bcma_extpci_read_config(struc + 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 { +@@ -124,11 +119,9 @@ static int bcma_extpci_read_config(struc + goto out; + + if (mips_busprobe32(val, mmio)) { +- val = 0xffffffff; ++ val = 0xFFFFFFFF; + goto unmap; + } +- +- val = readl(mmio); + } + val >>= (8 * (off & 3)); + +@@ -156,7 +149,7 @@ static int bcma_extpci_write_config(stru + const void *buf, int len) + { + int err = -EINVAL; +- u32 addr = 0, val = 0; ++ u32 addr, val; + void __iomem *mmio = 0; + u16 chipid = pc->core->bus->chipinfo.id; + +@@ -164,16 +157,22 @@ static int bcma_extpci_write_config(stru + 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); +@@ -185,19 +184,17 @@ static int bcma_extpci_write_config(stru + 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; +@@ -205,13 +202,14 @@ static int bcma_extpci_write_config(stru + 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); + +@@ -282,7 +280,7 @@ static u8 __devinit bcma_find_pci_capabi + /* 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 */ +@@ -396,12 +394,19 @@ void __devinit bcma_core_pci_hostmode_in bcma_info(bus, "PCIEcore in host mode found\n"); @@ -1077,7 +1610,24 @@ pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL); if (!pc_host) { bcma_err(bus, "can not allocate memory"); -@@ -452,6 +452,8 @@ void __devinit bcma_core_pci_hostmode_in + 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; +@@ -427,7 +432,7 @@ void __devinit bcma_core_pci_hostmode_in + /* Reset RC */ + usleep_range(3000, 5000); + pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE); +- usleep_range(1000, 2000); ++ msleep(50); + pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST | + BCMA_CORE_PCI_CTL_RST_OE); + +@@ -452,6 +457,8 @@ void __devinit bcma_core_pci_hostmode_in pc_host->mem_resource.start = BCMA_SOC_PCI_MEM; pc_host->mem_resource.end = BCMA_SOC_PCI_MEM + BCMA_SOC_PCI_MEM_SZ - 1; @@ -1086,7 +1636,7 @@ pci_membase_1G = BCMA_SOC_PCIE_DMA_H32; pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, tmp | BCMA_SOC_PCI_MEM); -@@ -459,6 +461,8 @@ void __devinit bcma_core_pci_hostmode_in +@@ -459,6 +466,8 @@ void __devinit bcma_core_pci_hostmode_in pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM; pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM + BCMA_SOC_PCI_MEM_SZ - 1; @@ -1095,7 +1645,25 @@ pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32; pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG; pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, -@@ -534,7 +538,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ +@@ -485,6 +494,17 @@ void __devinit bcma_core_pci_hostmode_in + + 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)); +@@ -534,7 +554,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ static void bcma_core_pci_fixup_addresses(struct pci_dev *dev) { struct resource *res; @@ -1104,7 +1672,7 @@ if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { /* This is not a device on the PCI-core bridge. */ -@@ -547,8 +551,12 @@ static void bcma_core_pci_fixup_addresse +@@ -547,8 +567,12 @@ static void bcma_core_pci_fixup_addresse for (pos = 0; pos < 6; pos++) { res = &dev->resource[pos]; @@ -1119,6 +1687,23 @@ } } DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_addresses); +@@ -569,7 +593,7 @@ int bcma_core_pci_plat_dev_init(struct p + 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; +@@ -588,6 +612,6 @@ int bcma_core_pci_pcibios_map_irq(const + + 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 +++ b/drivers/bcma/host_pci.c @@ -238,7 +238,7 @@ static void __devexit bcma_host_pci_remo @@ -1144,9 +1729,17 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, +@@ -275,6 +275,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_ + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, + { 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, }, + }; --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c -@@ -81,6 +81,18 @@ struct bcma_device *bcma_find_core(struc +@@ -81,6 +81,37 @@ struct bcma_device *bcma_find_core(struc } EXPORT_SYMBOL_GPL(bcma_find_core); @@ -1162,10 +1755,56 @@ + 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) { struct bcma_device *core = container_of(dev, struct bcma_device, dev); -@@ -152,6 +164,17 @@ static int bcma_register_cores(struct bc +@@ -108,6 +139,11 @@ static int bcma_register_cores(struct bc + 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", bus->num, dev_id); +@@ -137,6 +173,14 @@ static int bcma_register_cores(struct bc + dev_id++; + } + ++#ifdef CONFIG_BCMA_DRIVER_MIPS ++ if (bus->drv_cc.pflash.present) { ++ err = platform_device_register(&bcma_pflash_dev); ++ if (err) ++ bcma_err(bus, "Error registering parallel flash\n"); ++ } ++#endif ++ + #ifdef CONFIG_BCMA_SFLASH + if (bus->drv_cc.sflash.present) { + err = platform_device_register(&bcma_sflash_dev); +@@ -152,6 +196,17 @@ static int bcma_register_cores(struct bc bcma_err(bus, "Error registering NAND flash\n"); } #endif @@ -1183,7 +1822,7 @@ return 0; } -@@ -165,6 +188,8 @@ static void bcma_unregister_cores(struct +@@ -165,6 +220,8 @@ static void bcma_unregister_cores(struct if (core->dev_registered) device_unregister(&core->dev); } @@ -1192,7 +1831,7 @@ } int __devinit bcma_bus_register(struct bcma_bus *bus) -@@ -183,6 +208,20 @@ int __devinit bcma_bus_register(struct b +@@ -183,6 +240,20 @@ int __devinit bcma_bus_register(struct b return -1; } @@ -1213,28 +1852,28 @@ /* Init CC core */ core = bcma_find_core(bus, bcma_cc_core_id(bus)); if (core) { -@@ -198,10 +237,17 @@ int __devinit bcma_bus_register(struct b +@@ -198,10 +269,17 @@ int __devinit bcma_bus_register(struct 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); ++ if (core) { + bus->drv_pci[0].core = core; + bcma_core_pci_init(&bus->drv_pci[0]); + } + + /* Init PCIE core */ + core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 1); -+ if (core) { + if (core) { +- bus->drv_pci.core = core; +- bcma_core_pci_init(&bus->drv_pci); + bus->drv_pci[1].core = core; + bcma_core_pci_init(&bus->drv_pci[1]); } /* Init GBIT MAC COMMON core */ -@@ -211,13 +257,6 @@ int __devinit bcma_bus_register(struct b +@@ -211,13 +289,6 @@ int __devinit bcma_bus_register(struct b bcma_core_gmac_cmn_init(&bus->drv_gmac_cmn); } @@ -1248,7 +1887,21 @@ /* Register found cores */ bcma_register_cores(bus); -@@ -275,18 +314,18 @@ int __init bcma_bus_early_register(struc +@@ -229,6 +300,13 @@ int __devinit bcma_bus_register(struct b + 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); +@@ -275,18 +353,18 @@ int __init bcma_bus_early_register(struc return -1; } @@ -1271,32 +1924,278 @@ } bcma_info(bus, "Early bus registered\n"); +--- a/drivers/bcma/scan.c ++++ b/drivers/bcma/scan.c +@@ -84,6 +84,8 @@ static const struct bcma_device_id_name + { 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" }, + }; + +@@ -137,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)) +@@ -159,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); +@@ -175,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) { +@@ -189,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)) +@@ -199,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; --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c -@@ -595,8 +595,11 @@ int bcma_sprom_get(struct bcma_bus *bus) +@@ -72,12 +72,12 @@ fail: + * R/W ops. + **************************************************/ + +-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)); + } + + /************************************************** +@@ -124,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; +@@ -154,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; + } + +@@ -208,15 +212,13 @@ static void bcma_sprom_extract_r8(struct + 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; +- + for (i = 0; i < 3; i++) { + v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i]; + *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v); + } + + SPEX(board_rev, SSB_SPROM8_BOARDREV, ~0, 0); ++ SPEX(board_type, SSB_SPROM1_SPID, ~0, 0); + + SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0, + SSB_SPROM4_TXPID2G0_SHIFT); +@@ -501,7 +503,7 @@ static bool bcma_sprom_onchip_available( + 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 */ +@@ -549,7 +551,9 @@ int bcma_sprom_get(struct bcma_bus *bus) + { + u16 offset = BCMA_CC_SPROM; + u16 *sprom; +- 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; +@@ -578,29 +582,37 @@ int bcma_sprom_get(struct bcma_bus *bus) + } + } + +- sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), +- GFP_KERNEL); +- if (!sprom) +- return -ENOMEM; +- + 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, false); + + 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; ++ ++ kfree(sprom); ++ } + + 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); - err = bcma_sprom_valid(sprom); +- err = bcma_sprom_valid(sprom); - if (err) +- goto out; +- +- bcma_sprom_extract_r8(bus, sprom); + if (err) { -+ bcma_warn(bus, "invalid sprom read from the PCIe card, try to use fallback sprom\n"); ++ 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); - goto out; ++ } else { ++ bcma_sprom_extract_r8(bus, sprom); ++ kfree(sprom); + } - bcma_sprom_extract_r8(bus, sprom); - +-out: +- kfree(sprom); + return err; + } --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h -@@ -134,6 +134,7 @@ struct bcma_host_ops { +@@ -134,12 +134,17 @@ 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_ARM_CR4 0x83e ++#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 -@@ -157,6 +158,7 @@ struct bcma_host_ops { + + /* 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 +@@ -157,6 +162,7 @@ struct bcma_host_ops { /* Chip IDs of SoCs */ #define BCMA_CHIP_ID_BCM4706 0x5300 @@ -1304,7 +2203,7 @@ #define BCMA_CHIP_ID_BCM4716 0x4716 #define BCMA_PKG_ID_BCM4716 8 #define BCMA_PKG_ID_BCM4717 9 -@@ -166,7 +168,11 @@ struct bcma_host_ops { +@@ -166,7 +172,65 @@ struct bcma_host_ops { #define BCMA_CHIP_ID_BCM4749 0x4749 #define BCMA_CHIP_ID_BCM5356 0x5356 #define BCMA_CHIP_ID_BCM5357 0x5357 @@ -1313,10 +2212,64 @@ +#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; -@@ -251,7 +257,7 @@ struct bcma_bus { +@@ -251,7 +315,7 @@ struct bcma_bus { u8 num; struct bcma_drv_cc drv_cc; @@ -1325,7 +2278,7 @@ struct bcma_drv_mips drv_mips; struct bcma_drv_gmac_cmn drv_gmac_cmn; -@@ -345,6 +351,7 @@ extern void bcma_core_set_clockmode(stru +@@ -345,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); @@ -1345,6 +2298,15 @@ /** 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 /* NAND flash */ ++#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 @@ -101,6 +104,7 @@ #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 */ @@ -1363,7 +2325,90 @@ #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 */ -@@ -510,6 +517,7 @@ struct bcma_chipcommon_pmu { +@@ -323,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 */ +@@ -348,6 +357,11 @@ + #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 */ + /* NAND flash MLC controller registers (corerev >= 38) */ + #define BCMA_CC_NAND_REVISION 0x0C00 +@@ -428,6 +442,23 @@ + #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 + /* HT clock for systems with PMU-enabled chipcommon */ +@@ -500,6 +531,37 @@ + #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) + */ +@@ -510,6 +572,7 @@ struct bcma_chipcommon_pmu { #ifdef CONFIG_BCMA_DRIVER_MIPS struct bcma_pflash { @@ -1371,7 +2416,15 @@ u8 buswidth; u32 window; u32 window_size; -@@ -532,6 +540,7 @@ struct mtd_info; +@@ -524,6 +587,7 @@ struct bcma_sflash { + u32 size; + + struct mtd_info *mtd; ++ void *priv; + }; + #endif + +@@ -532,6 +596,7 @@ struct mtd_info; struct bcma_nflash { bool present; @@ -1379,7 +2432,7 @@ struct mtd_info *mtd; }; -@@ -552,6 +561,7 @@ struct bcma_drv_cc { +@@ -552,6 +617,7 @@ struct bcma_drv_cc { u32 capabilities; u32 capabilities_ext; u8 setup_done:1; @@ -1387,7 +2440,7 @@ /* Fast Powerup Delay constant */ u16 fast_pwrup_delay; struct bcma_chipcommon_pmu pmu; -@@ -567,6 +577,14 @@ struct bcma_drv_cc { +@@ -567,6 +633,14 @@ struct bcma_drv_cc { int nr_serial_ports; struct bcma_serial_port serial_ports[4]; #endif /* CONFIG_BCMA_DRIVER_MIPS */ @@ -1402,7 +2455,7 @@ }; /* Register access */ -@@ -583,14 +601,16 @@ struct bcma_drv_cc { +@@ -583,14 +657,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); @@ -1421,7 +2474,7 @@ void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value); -@@ -603,9 +623,12 @@ u32 bcma_chipco_gpio_outen(struct bcma_d +@@ -603,9 +679,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); @@ -1434,9 +2487,24 @@ extern void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value); +@@ -617,4 +696,6 @@ extern void bcma_chipco_regctl_maskset(s + 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_ */ --- a/include/linux/bcma/bcma_driver_mips.h +++ b/include/linux/bcma/bcma_driver_mips.h -@@ -35,13 +35,15 @@ struct bcma_device; +@@ -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; @@ -1447,12 +2515,34 @@ #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 +@@ -179,6 +179,8 @@ struct pci_dev; + #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 + --- a/include/linux/bcma/bcma_regs.h +++ b/include/linux/bcma/bcma_regs.h @@ -37,6 +37,7 @@ diff --git a/target/linux/generic/patches-3.8/020-ssb_update.patch b/target/linux/generic/patches-3.8/020-ssb_update.patch index a1b4a1f..22dae59 100644 --- a/target/linux/generic/patches-3.8/020-ssb_update.patch +++ b/target/linux/generic/patches-3.8/020-ssb_update.patch @@ -1,6 +1,6 @@ --- a/drivers/ssb/Kconfig +++ b/drivers/ssb/Kconfig -@@ -136,6 +136,11 @@ config SSB_DRIVER_MIPS +@@ -136,10 +136,15 @@ config SSB_DRIVER_MIPS If unsure, say N @@ -12,6 +12,11 @@ # Assumption: We are on embedded, if we compile the MIPS core. config SSB_EMBEDDED bool +- depends on SSB_DRIVER_MIPS ++ depends on SSB_DRIVER_MIPS && SSB_PCICORE_HOSTMODE + default y + + config SSB_DRIVER_EXTIF --- a/drivers/ssb/Makefile +++ b/drivers/ssb/Makefile @@ -11,6 +11,7 @@ ssb-$(CONFIG_SSB_SDIOHOST) += sdio.o @@ -174,7 +179,7 @@ "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n", --- /dev/null +++ b/drivers/ssb/driver_chipcommon_sflash.c -@@ -0,0 +1,140 @@ +@@ -0,0 +1,166 @@ +/* + * Sonics Silicon Backplane + * ChipCommon serial flash interface @@ -186,6 +191,19 @@ + +#include "ssb_private.h" + ++static struct resource ssb_sflash_resource = { ++ .name = "ssb_sflash", ++ .start = SSB_FLASH2, ++ .end = 0, ++ .flags = IORESOURCE_MEM | IORESOURCE_READONLY, ++}; ++ ++struct platform_device ssb_sflash_dev = { ++ .name = "ssb_sflash", ++ .resource = &ssb_sflash_resource, ++ .num_resources = 1, ++}; ++ +struct ssb_sflash_tbl_e { + char *name; + u32 id; @@ -193,7 +211,7 @@ + u16 numblocks; +}; + -+static struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = { ++static const struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = { + { "M25P20", 0x11, 0x10000, 4, }, + { "M25P40", 0x12, 0x10000, 8, }, + @@ -204,7 +222,7 @@ + { 0 }, +}; + -+static struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { ++static const struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { + { "SST25WF512", 1, 0x1000, 16, }, + { "SST25VF512", 0x48, 0x1000, 16, }, + { "SST25WF010", 2, 0x1000, 32, }, @@ -222,7 +240,7 @@ + { 0 }, +}; + -+static struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { ++static const struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { + { "AT45DB011", 0xc, 256, 512, }, + { "AT45DB021", 0x14, 256, 1024, }, + { "AT45DB041", 0x1c, 256, 2048, }, @@ -250,7 +268,8 @@ +/* Initialize serial flash access */ +int ssb_sflash_init(struct ssb_chipcommon *cc) +{ -+ struct ssb_sflash_tbl_e *e; ++ struct ssb_sflash *sflash = &cc->dev->bus->mipscore.sflash; ++ const struct ssb_sflash_tbl_e *e; + u32 id, id2; + + switch (cc->capabilities & SSB_CHIPCO_CAP_FLASHT) { @@ -308,9 +327,21 @@ + return -ENOTSUPP; + } + ++ sflash->window = SSB_FLASH2; ++ sflash->blocksize = e->blocksize; ++ sflash->numblocks = e->numblocks; ++ sflash->size = sflash->blocksize * sflash->numblocks; ++ sflash->present = true; ++ + pr_info("Found %s serial flash (blocksize: 0x%X, blocks: %d)\n", + e->name, e->blocksize, e->numblocks); + ++ /* Prepare platform device, but don't register it yet. It's too early, ++ * malloc (required by device_private_init) is not available yet. */ ++ ssb_sflash_dev.resource[0].end = ssb_sflash_dev.resource[0].start + ++ sflash->size; ++ ssb_sflash_dev.dev.platform_data = sflash; ++ + pr_err("Serial flash support is not implemented yet!\n"); + + return -ENOTSUPP; @@ -626,7 +657,7 @@ /* Set dev to NULL to not unregister * dev on error unwinding. */ sdev->dev = NULL; -@@ -549,6 +545,14 @@ static int ssb_devices_register(struct s +@@ -549,6 +545,22 @@ static int ssb_devices_register(struct s dev_idx++; } @@ -638,10 +669,18 @@ + } +#endif + ++#ifdef CONFIG_SSB_SFLASH ++ if (bus->mipscore.sflash.present) { ++ err = platform_device_register(&ssb_sflash_dev); ++ if (err) ++ pr_err("Error registering serial flash\n"); ++ } ++#endif ++ return 0; error: /* Unwind the already registered devices. */ -@@ -817,10 +821,9 @@ static int ssb_bus_register(struct ssb_b +@@ -817,10 +829,9 @@ static int ssb_bus_register(struct ssb_b ssb_mipscore_init(&bus->mipscore); err = ssb_gpio_init(bus); if (err == -ENOTSUPP) @@ -654,7 +693,7 @@ err = ssb_fetch_invariants(bus, get_invariants); if (err) { ssb_bus_may_powerdown(bus); -@@ -870,11 +873,11 @@ int ssb_bus_pcibus_register(struct ssb_b +@@ -870,11 +881,11 @@ int ssb_bus_pcibus_register(struct ssb_b err = ssb_bus_register(bus, ssb_pci_get_invariants, 0); if (!err) { @@ -670,7 +709,7 @@ } return err; -@@ -895,8 +898,8 @@ int ssb_bus_pcmciabus_register(struct ss +@@ -895,8 +906,8 @@ int ssb_bus_pcmciabus_register(struct ss err = ssb_bus_register(bus, ssb_pcmcia_get_invariants, baseaddr); if (!err) { @@ -681,7 +720,7 @@ } return err; -@@ -917,8 +920,8 @@ int ssb_bus_sdiobus_register(struct ssb_ +@@ -917,8 +928,8 @@ int ssb_bus_sdiobus_register(struct ssb_ err = ssb_bus_register(bus, ssb_sdio_get_invariants, ~0); if (!err) { @@ -692,7 +731,7 @@ } return err; -@@ -936,8 +939,8 @@ int ssb_bus_ssbbus_register(struct ssb_b +@@ -936,8 +947,8 @@ int ssb_bus_ssbbus_register(struct ssb_b err = ssb_bus_register(bus, get_invariants, baseaddr); if (!err) { @@ -703,7 +742,7 @@ } return err; -@@ -1331,7 +1334,7 @@ out: +@@ -1331,7 +1342,7 @@ out: #endif return err; error: @@ -712,7 +751,7 @@ goto out; } EXPORT_SYMBOL(ssb_bus_may_powerdown); -@@ -1354,7 +1357,7 @@ int ssb_bus_powerup(struct ssb_bus *bus, +@@ -1354,7 +1365,7 @@ int ssb_bus_powerup(struct ssb_bus *bus, return 0; error: @@ -721,7 +760,7 @@ return err; } EXPORT_SYMBOL(ssb_bus_powerup); -@@ -1462,15 +1465,13 @@ static int __init ssb_modinit(void) +@@ -1462,15 +1473,13 @@ static int __init ssb_modinit(void) err = b43_pci_ssb_bridge_init(); if (err) { @@ -1028,6 +1067,17 @@ } } err = sprom_extract(bus, sprom, buf, bus->sprom_size); +--- a/drivers/ssb/pcihost_wrapper.c ++++ b/drivers/ssb/pcihost_wrapper.c +@@ -38,7 +38,7 @@ static int ssb_pcihost_resume(struct pci + struct ssb_bus *ssb = pci_get_drvdata(dev); + int err; + +- pci_set_power_state(dev, 0); ++ pci_set_power_state(dev, PCI_D0); + err = pci_enable_device(dev); + if (err) + return err; --- a/drivers/ssb/pcmcia.c +++ b/drivers/ssb/pcmcia.c @@ -143,7 +143,7 @@ int ssb_pcmcia_switch_coreidx(struct ssb @@ -1247,6 +1297,15 @@ bus->pcicore.dev = dev; --- a/drivers/ssb/sprom.c +++ b/drivers/ssb/sprom.c +@@ -54,7 +54,7 @@ static int hex2sprom(u16 *sprom, const c + while (cnt < sprom_size_words) { + memcpy(tmp, dump, 4); + dump += 4; +- err = strict_strtoul(tmp, 16, &parsed); ++ err = kstrtoul(tmp, 16, &parsed); + if (err) + return err; + sprom[cnt++] = swab16((u16)parsed); @@ -127,13 +127,13 @@ ssize_t ssb_attr_sprom_store(struct ssb_ goto out_kfree; err = ssb_devices_freeze(bus, &freeze); @@ -1297,7 +1356,7 @@ #endif #ifdef CONFIG_SSB_DEBUG -@@ -217,6 +228,21 @@ extern u32 ssb_chipco_watchdog_timer_set +@@ -217,6 +228,25 @@ extern u32 ssb_chipco_watchdog_timer_set u32 ticks); extern u32 ssb_chipco_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms); @@ -1316,6 +1375,10 @@ +extern struct platform_device ssb_pflash_dev; +#endif + ++#ifdef CONFIG_SSB_SFLASH ++extern struct platform_device ssb_sflash_dev; ++#endif ++ #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); @@ -1443,7 +1506,36 @@ #endif /* LINUX_SSB_DRIVER_GIGE_H_ */ --- a/include/linux/ssb/ssb_driver_mips.h +++ b/include/linux/ssb/ssb_driver_mips.h -@@ -45,6 +45,11 @@ void ssb_mipscore_init(struct ssb_mipsco +@@ -20,6 +20,18 @@ struct ssb_pflash { + u32 window_size; + }; + ++#ifdef CONFIG_SSB_SFLASH ++struct ssb_sflash { ++ bool present; ++ u32 window; ++ u32 blocksize; ++ u16 numblocks; ++ u32 size; ++ ++ void *priv; ++}; ++#endif ++ + struct ssb_mipscore { + struct ssb_device *dev; + +@@ -27,6 +39,9 @@ struct ssb_mipscore { + struct ssb_serial_port serial_ports[4]; + + struct ssb_pflash pflash; ++#ifdef CONFIG_SSB_SFLASH ++ struct ssb_sflash sflash; ++#endif + }; + + extern void ssb_mipscore_init(struct ssb_mipscore *mcore); +@@ -45,6 +60,11 @@ void ssb_mipscore_init(struct ssb_mipsco { } @@ -1457,7 +1549,15 @@ #endif /* LINUX_SSB_MIPSCORE_H_ */ --- a/include/linux/ssb/ssb_regs.h +++ b/include/linux/ssb/ssb_regs.h -@@ -289,11 +289,11 @@ +@@ -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 +@@ -289,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 */ diff --git a/target/linux/generic/patches-3.8/025-bcma_backport.patch b/target/linux/generic/patches-3.8/025-bcma_backport.patch index 360ee71..7373c02 100644 --- a/target/linux/generic/patches-3.8/025-bcma_backport.patch +++ b/target/linux/generic/patches-3.8/025-bcma_backport.patch @@ -9,9 +9,28 @@ p->uartclk = bcma_port->baud_base; p->regshift = bcma_port->reg_shift; p->iotype = UPIO_MEM; +--- a/drivers/bcma/Kconfig ++++ b/drivers/bcma/Kconfig +@@ -26,6 +26,7 @@ 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" --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h -@@ -31,6 +31,8 @@ int __init bcma_bus_early_register(struc +@@ -22,6 +22,8 @@ + struct bcma_bus; + + /* main.c */ ++bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value, ++ int timeout); + int bcma_bus_register(struct bcma_bus *bus); + void bcma_bus_unregister(struct bcma_bus *bus); + int __init bcma_bus_early_register(struct bcma_bus *bus, +@@ -31,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 @@ -20,7 +39,7 @@ /* scan.c */ int bcma_bus_scan(struct bcma_bus *bus); -@@ -45,6 +47,7 @@ int bcma_sprom_get(struct bcma_bus *bus) +@@ -45,6 +49,7 @@ int bcma_sprom_get(struct bcma_bus *bus) /* driver_chipcommon.c */ #ifdef CONFIG_BCMA_DRIVER_MIPS void bcma_chipco_serial_init(struct bcma_drv_cc *cc); @@ -30,7 +49,60 @@ /* driver_chipcommon_pmu.c */ --- a/drivers/bcma/core.c +++ b/drivers/bcma/core.c -@@ -104,7 +104,13 @@ void bcma_core_pll_ctl(struct bcma_devic +@@ -9,6 +9,25 @@ + #include <linux/export.h> + #include <linux/bcma/bcma.h> + ++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,13 +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); + +@@ -43,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)); +@@ -104,7 +126,13 @@ void bcma_core_pll_ctl(struct bcma_devic if (i) bcma_err(core->bus, "PLL enable timeout\n"); } else { @@ -63,7 +135,25 @@ static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc) { -@@ -213,6 +214,7 @@ u32 bcma_chipco_gpio_out(struct bcma_drv +@@ -139,8 +140,15 @@ void bcma_core_chipcommon_init(struct bc + 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) +@@ -213,6 +221,7 @@ u32 bcma_chipco_gpio_out(struct bcma_drv return res; } @@ -71,7 +161,7 @@ u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value) { -@@ -225,6 +227,7 @@ u32 bcma_chipco_gpio_outen(struct bcma_d +@@ -225,6 +234,7 @@ u32 bcma_chipco_gpio_outen(struct bcma_d return res; } @@ -79,7 +169,7 @@ /* * If the bit is set to 0, chipcommon controlls this GPIO, -@@ -329,7 +332,7 @@ void bcma_chipco_serial_init(struct bcma +@@ -329,7 +339,7 @@ void bcma_chipco_serial_init(struct bcma return; } @@ -106,7 +196,151 @@ .num_resources = 0, --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c -@@ -174,19 +174,35 @@ u32 bcma_pmu_get_alp_clock(struct bcma_d +@@ -56,6 +56,109 @@ void bcma_chipco_regctl_maskset(struct b + } + EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset); + ++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 BCMA_CHIP_ID_BCM43142: ++ if (xtalfreq == 0) ++ xtalfreq = 20000; ++ bcma_pmu2_pll_init0(cc, xtalfreq); ++ break; ++ } ++} ++ + static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) + { + struct bcma_bus *bus = cc->core->bus; +@@ -66,6 +169,25 @@ static void bcma_pmu_resources_init(stru + min_msk = 0x200D; + max_msk = 0xFFFF; + 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: + bcma_debug(bus, "PMU resource config unknown or not needed for device 0x%04X\n", + bus->chipinfo.id); +@@ -165,6 +287,7 @@ void bcma_pmu_init(struct bcma_drv_cc *c + bcma_cc_set32(cc, BCMA_CC_PMU_CTL, + BCMA_CC_PMU_CTL_NOILPONW); + ++ bcma_pmu_pll_init(cc); + bcma_pmu_resources_init(cc); + bcma_pmu_workarounds(cc); + } +@@ -174,19 +297,35 @@ u32 bcma_pmu_get_alp_clock(struct bcma_d struct bcma_bus *bus = cc->core->bus; switch (bus->chipinfo.id) { @@ -146,7 +380,7 @@ default: bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n", bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK); -@@ -264,7 +280,7 @@ static u32 bcma_pmu_pll_clock_bcm4706(st +@@ -264,7 +403,7 @@ static u32 bcma_pmu_pll_clock_bcm4706(st } /* query bus clock frequency for PMU-enabled chipcommon */ @@ -155,7 +389,7 @@ { struct bcma_bus *bus = cc->core->bus; -@@ -293,6 +309,7 @@ static u32 bcma_pmu_get_bus_clock(struct +@@ -293,6 +432,7 @@ static u32 bcma_pmu_get_bus_clock(struct } return BCMA_CC_PMU_HT_CLOCK; } @@ -163,7 +397,7 @@ /* query cpu clock frequency for PMU-enabled chipcommon */ u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc) -@@ -372,7 +389,7 @@ void bcma_pmu_spuravoid_pllupdate(struct +@@ -372,7 +512,7 @@ void bcma_pmu_spuravoid_pllupdate(struct tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT; bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp); @@ -172,7 +406,7 @@ break; case BCMA_CHIP_ID_BCM4331: -@@ -393,7 +410,7 @@ void bcma_pmu_spuravoid_pllupdate(struct +@@ -393,7 +533,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 0x03000a08); } @@ -181,7 +415,7 @@ break; case BCMA_CHIP_ID_BCM43224: -@@ -426,7 +443,7 @@ void bcma_pmu_spuravoid_pllupdate(struct +@@ -426,7 +566,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 0x88888815); } @@ -190,7 +424,7 @@ break; case BCMA_CHIP_ID_BCM4716: -@@ -460,7 +477,7 @@ void bcma_pmu_spuravoid_pllupdate(struct +@@ -460,7 +600,7 @@ void bcma_pmu_spuravoid_pllupdate(struct 0x88888815); } @@ -199,7 +433,7 @@ break; case BCMA_CHIP_ID_BCM43227: -@@ -496,7 +513,7 @@ void bcma_pmu_spuravoid_pllupdate(struct +@@ -496,7 +636,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 0x88888815); } @@ -224,6 +458,42 @@ static struct resource bcma_sflash_resource = { .name = "bcma_sflash", .start = BCMA_SOC_FLASH2, +@@ -30,7 +30,7 @@ struct bcma_sflash_tbl_e { + u16 numblocks; + }; + +-static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { ++static const struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { + { "M25P20", 0x11, 0x10000, 4, }, + { "M25P40", 0x12, 0x10000, 8, }, + +@@ -41,7 +41,7 @@ static struct bcma_sflash_tbl_e bcma_sfl + { 0 }, + }; + +-static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { ++static const struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { + { "SST25WF512", 1, 0x1000, 16, }, + { "SST25VF512", 0x48, 0x1000, 16, }, + { "SST25WF010", 2, 0x1000, 32, }, +@@ -59,7 +59,7 @@ static struct bcma_sflash_tbl_e bcma_sfl + { 0 }, + }; + +-static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { ++static const struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { + { "AT45DB011", 0xc, 256, 512, }, + { "AT45DB021", 0x14, 256, 1024, }, + { "AT45DB041", 0x1c, 256, 2048, }, +@@ -89,7 +89,7 @@ int bcma_sflash_init(struct bcma_drv_cc + { + struct bcma_bus *bus = cc->core->bus; + struct bcma_sflash *sflash = &cc->sflash; +- struct bcma_sflash_tbl_e *e; ++ const struct bcma_sflash_tbl_e *e; + u32 id, id2; + + switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { --- a/drivers/bcma/driver_gpio.c +++ b/drivers/bcma/driver_gpio.c @@ -73,6 +73,16 @@ static void bcma_gpio_free(struct gpio_c @@ -732,6 +1002,16 @@ + return bcma_core_irq(pc_host->pdev->core); } EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq); +--- a/drivers/bcma/host_pci.c ++++ b/drivers/bcma/host_pci.c +@@ -275,6 +275,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_ + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, + { 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, }, + }; --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -81,8 +81,8 @@ struct bcma_device *bcma_find_core(struc @@ -745,7 +1025,33 @@ { struct bcma_device *core; -@@ -120,6 +120,11 @@ static int bcma_register_cores(struct bc +@@ -93,6 +93,25 @@ static struct bcma_device *bcma_find_cor + 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) + { + struct bcma_device *core = container_of(dev, struct bcma_device, dev); +@@ -120,6 +139,11 @@ static int bcma_register_cores(struct bc continue; } @@ -757,7 +1063,7 @@ core->dev.release = bcma_release_core_dev; core->dev.bus = &bcma_bus_type; dev_set_name(&core->dev, "bcma%d:%d", bus->num, dev_id); -@@ -149,6 +154,14 @@ static int bcma_register_cores(struct bc +@@ -149,6 +173,14 @@ static int bcma_register_cores(struct bc dev_id++; } @@ -774,7 +1080,16 @@ err = platform_device_register(&bcma_sflash_dev); --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c -@@ -137,19 +137,19 @@ static void bcma_scan_switch_core(struct +@@ -84,6 +84,8 @@ static const struct bcma_device_id_name + { 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" }, + }; + +@@ -137,19 +139,19 @@ static void bcma_scan_switch_core(struct addr); } @@ -797,7 +1112,7 @@ { u32 ent = bcma_erom_get_ent(bus, eromptr); if (!(ent & SCAN_ER_VALID)) -@@ -159,14 +159,14 @@ static s32 bcma_erom_get_ci(struct bcma_ +@@ -159,14 +161,14 @@ static s32 bcma_erom_get_ci(struct bcma_ return ent; } @@ -814,7 +1129,7 @@ { u32 ent = bcma_erom_get_ent(bus, eromptr); bcma_erom_push_ent(eromptr); -@@ -175,7 +175,7 @@ static bool bcma_erom_is_bridge(struct b +@@ -175,7 +177,7 @@ static bool bcma_erom_is_bridge(struct b ((ent & SCAN_ADDR_TYPE) == SCAN_ADDR_TYPE_BRIDGE)); } @@ -823,7 +1138,7 @@ { u32 ent; while (1) { -@@ -189,7 +189,7 @@ static void bcma_erom_skip_component(str +@@ -189,7 +191,7 @@ static void bcma_erom_skip_component(str bcma_erom_push_ent(eromptr); } @@ -832,7 +1147,7 @@ { u32 ent = bcma_erom_get_ent(bus, eromptr); if (!(ent & SCAN_ER_VALID)) -@@ -199,7 +199,7 @@ static s32 bcma_erom_get_mst_port(struct +@@ -199,7 +201,7 @@ static s32 bcma_erom_get_mst_port(struct return ent; } @@ -843,7 +1158,99 @@ u32 addrl, addrh, sizel, sizeh = 0; --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c -@@ -217,6 +217,7 @@ static void bcma_sprom_extract_r8(struct +@@ -72,12 +72,12 @@ fail: + * R/W ops. + **************************************************/ + +-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)); + } + + /************************************************** +@@ -124,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; +@@ -154,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; + } + +@@ -208,15 +212,13 @@ static void bcma_sprom_extract_r8(struct + 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; +- + for (i = 0; i < 3; i++) { + v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i]; + *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v); } SPEX(board_rev, SSB_SPROM8_BOARDREV, ~0, 0); @@ -851,17 +1258,98 @@ SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT); +@@ -501,7 +503,7 @@ static bool bcma_sprom_onchip_available( + 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 */ +@@ -549,7 +551,9 @@ int bcma_sprom_get(struct bcma_bus *bus) + { + u16 offset = BCMA_CC_SPROM; + u16 *sprom; +- 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; +@@ -578,32 +582,37 @@ int bcma_sprom_get(struct bcma_bus *bus) + } + } + +- sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), +- GFP_KERNEL); +- if (!sprom) +- return -ENOMEM; +- + 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, false); + + 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; ++ ++ kfree(sprom); ++ } + + 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); + +- err = bcma_sprom_valid(sprom); + if (err) { +- bcma_warn(bus, "invalid sprom read from the PCIe card, try to use fallback sprom\n"); ++ 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); +- goto out; ++ } else { ++ bcma_sprom_extract_r8(bus, sprom); ++ kfree(sprom); + } + +- bcma_sprom_extract_r8(bus, sprom); +- +-out: +- kfree(sprom); + return err; + } --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h -@@ -134,6 +134,7 @@ struct bcma_host_ops { +@@ -134,12 +134,17 @@ 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_ARM_CR4 0x83e ++#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 -@@ -173,6 +174,60 @@ struct bcma_host_ops { + + /* 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 +@@ -173,6 +178,60 @@ struct bcma_host_ops { #define BCMA_CHIP_ID_BCM53572 53572 #define BCMA_PKG_ID_BCM47188 9 @@ -951,7 +1439,90 @@ #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 */ -@@ -528,6 +532,7 @@ struct bcma_sflash { +@@ -326,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 */ +@@ -351,6 +357,11 @@ + #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 */ + /* NAND flash MLC controller registers (corerev >= 38) */ + #define BCMA_CC_NAND_REVISION 0x0C00 +@@ -431,6 +442,23 @@ + #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 + /* HT clock for systems with PMU-enabled chipcommon */ +@@ -503,6 +531,37 @@ + #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) + */ +@@ -528,6 +587,7 @@ struct bcma_sflash { u32 size; struct mtd_info *mtd; @@ -959,7 +1530,7 @@ }; #endif -@@ -606,6 +611,8 @@ void bcma_chipco_bcm4331_ext_pa_lines_ct +@@ -606,6 +666,8 @@ void bcma_chipco_bcm4331_ext_pa_lines_ct extern u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks); @@ -968,7 +1539,7 @@ void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value); u32 bcma_chipco_irq_status(struct bcma_drv_cc *cc, u32 mask); -@@ -634,4 +641,6 @@ extern void bcma_chipco_regctl_maskset(s +@@ -634,4 +696,6 @@ extern void bcma_chipco_regctl_maskset(s u32 offset, u32 mask, u32 set); extern void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid); diff --git a/target/linux/generic/patches-3.9/020-ssb_update.patch b/target/linux/generic/patches-3.9/020-ssb_update.patch index c87c2f6..9908d69 100644 --- a/target/linux/generic/patches-3.9/020-ssb_update.patch +++ b/target/linux/generic/patches-3.9/020-ssb_update.patch @@ -1,3 +1,14 @@ +--- a/drivers/ssb/Kconfig ++++ b/drivers/ssb/Kconfig +@@ -144,7 +144,7 @@ config SSB_SFLASH + # Assumption: We are on embedded, if we compile the MIPS core. + config SSB_EMBEDDED + bool +- depends on SSB_DRIVER_MIPS ++ depends on SSB_DRIVER_MIPS && SSB_PCICORE_HOSTMODE + default y + + config SSB_DRIVER_EXTIF --- a/drivers/ssb/driver_chipcommon.c +++ b/drivers/ssb/driver_chipcommon.c @@ -354,7 +354,7 @@ void ssb_chipcommon_init(struct ssb_chip @@ -148,6 +159,87 @@ default: ssb_printk(KERN_ERR PFX "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n", +--- a/drivers/ssb/driver_chipcommon_sflash.c ++++ b/drivers/ssb/driver_chipcommon_sflash.c +@@ -9,6 +9,19 @@ + + #include "ssb_private.h" + ++static struct resource ssb_sflash_resource = { ++ .name = "ssb_sflash", ++ .start = SSB_FLASH2, ++ .end = 0, ++ .flags = IORESOURCE_MEM | IORESOURCE_READONLY, ++}; ++ ++struct platform_device ssb_sflash_dev = { ++ .name = "ssb_sflash", ++ .resource = &ssb_sflash_resource, ++ .num_resources = 1, ++}; ++ + struct ssb_sflash_tbl_e { + char *name; + u32 id; +@@ -16,7 +29,7 @@ struct ssb_sflash_tbl_e { + u16 numblocks; + }; + +-static struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = { ++static const struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = { + { "M25P20", 0x11, 0x10000, 4, }, + { "M25P40", 0x12, 0x10000, 8, }, + +@@ -27,7 +40,7 @@ static struct ssb_sflash_tbl_e ssb_sflas + { 0 }, + }; + +-static struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { ++static const struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { + { "SST25WF512", 1, 0x1000, 16, }, + { "SST25VF512", 0x48, 0x1000, 16, }, + { "SST25WF010", 2, 0x1000, 32, }, +@@ -45,7 +58,7 @@ static struct ssb_sflash_tbl_e ssb_sflas + { 0 }, + }; + +-static struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { ++static const struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { + { "AT45DB011", 0xc, 256, 512, }, + { "AT45DB021", 0x14, 256, 1024, }, + { "AT45DB041", 0x1c, 256, 2048, }, +@@ -73,7 +86,8 @@ static void ssb_sflash_cmd(struct ssb_ch + /* Initialize serial flash access */ + int ssb_sflash_init(struct ssb_chipcommon *cc) + { +- struct ssb_sflash_tbl_e *e; ++ struct ssb_sflash *sflash = &cc->dev->bus->mipscore.sflash; ++ const struct ssb_sflash_tbl_e *e; + u32 id, id2; + + switch (cc->capabilities & SSB_CHIPCO_CAP_FLASHT) { +@@ -131,9 +145,21 @@ int ssb_sflash_init(struct ssb_chipcommo + return -ENOTSUPP; + } + ++ sflash->window = SSB_FLASH2; ++ sflash->blocksize = e->blocksize; ++ sflash->numblocks = e->numblocks; ++ sflash->size = sflash->blocksize * sflash->numblocks; ++ sflash->present = true; ++ + pr_info("Found %s serial flash (blocksize: 0x%X, blocks: %d)\n", + e->name, e->blocksize, e->numblocks); + ++ /* Prepare platform device, but don't register it yet. It's too early, ++ * malloc (required by device_private_init) is not available yet. */ ++ ssb_sflash_dev.resource[0].end = ssb_sflash_dev.resource[0].start + ++ sflash->size; ++ ssb_sflash_dev.dev.platform_data = sflash; ++ + pr_err("Serial flash support is not implemented yet!\n"); + + return -ENOTSUPP; --- a/drivers/ssb/driver_mipscore.c +++ b/drivers/ssb/driver_mipscore.c @@ -167,21 +167,22 @@ static void set_irq(struct ssb_device *d @@ -318,7 +410,22 @@ /* Set dev to NULL to not unregister * dev on error unwinding. */ sdev->dev = NULL; -@@ -825,10 +821,9 @@ static int ssb_bus_register(struct ssb_b +@@ -557,6 +553,14 @@ static int ssb_devices_register(struct s + } + #endif + ++#ifdef CONFIG_SSB_SFLASH ++ if (bus->mipscore.sflash.present) { ++ err = platform_device_register(&ssb_sflash_dev); ++ if (err) ++ pr_err("Error registering serial flash\n"); ++ } ++#endif ++ + return 0; + error: + /* Unwind the already registered devices. */ +@@ -825,10 +829,9 @@ static int ssb_bus_register(struct ssb_b ssb_mipscore_init(&bus->mipscore); err = ssb_gpio_init(bus); if (err == -ENOTSUPP) @@ -331,7 +438,7 @@ err = ssb_fetch_invariants(bus, get_invariants); if (err) { ssb_bus_may_powerdown(bus); -@@ -878,11 +873,11 @@ int ssb_bus_pcibus_register(struct ssb_b +@@ -878,11 +881,11 @@ int ssb_bus_pcibus_register(struct ssb_b err = ssb_bus_register(bus, ssb_pci_get_invariants, 0); if (!err) { @@ -347,7 +454,7 @@ } return err; -@@ -903,8 +898,8 @@ int ssb_bus_pcmciabus_register(struct ss +@@ -903,8 +906,8 @@ int ssb_bus_pcmciabus_register(struct ss err = ssb_bus_register(bus, ssb_pcmcia_get_invariants, baseaddr); if (!err) { @@ -358,7 +465,7 @@ } return err; -@@ -925,8 +920,8 @@ int ssb_bus_sdiobus_register(struct ssb_ +@@ -925,8 +928,8 @@ int ssb_bus_sdiobus_register(struct ssb_ err = ssb_bus_register(bus, ssb_sdio_get_invariants, ~0); if (!err) { @@ -369,7 +476,7 @@ } return err; -@@ -944,8 +939,8 @@ int ssb_bus_ssbbus_register(struct ssb_b +@@ -944,8 +947,8 @@ int ssb_bus_ssbbus_register(struct ssb_b err = ssb_bus_register(bus, get_invariants, baseaddr); if (!err) { @@ -380,7 +487,7 @@ } return err; -@@ -1339,7 +1334,7 @@ out: +@@ -1339,7 +1342,7 @@ out: #endif return err; error: @@ -389,7 +496,7 @@ goto out; } EXPORT_SYMBOL(ssb_bus_may_powerdown); -@@ -1362,7 +1357,7 @@ int ssb_bus_powerup(struct ssb_bus *bus, +@@ -1362,7 +1365,7 @@ int ssb_bus_powerup(struct ssb_bus *bus, return 0; error: @@ -398,7 +505,7 @@ return err; } EXPORT_SYMBOL(ssb_bus_powerup); -@@ -1470,15 +1465,13 @@ static int __init ssb_modinit(void) +@@ -1470,15 +1473,13 @@ static int __init ssb_modinit(void) err = b43_pci_ssb_bridge_init(); if (err) { @@ -705,6 +812,17 @@ } } err = sprom_extract(bus, sprom, buf, bus->sprom_size); +--- a/drivers/ssb/pcihost_wrapper.c ++++ b/drivers/ssb/pcihost_wrapper.c +@@ -38,7 +38,7 @@ static int ssb_pcihost_resume(struct pci + struct ssb_bus *ssb = pci_get_drvdata(dev); + int err; + +- pci_set_power_state(dev, 0); ++ pci_set_power_state(dev, PCI_D0); + err = pci_enable_device(dev); + if (err) + return err; --- a/drivers/ssb/pcmcia.c +++ b/drivers/ssb/pcmcia.c @@ -143,7 +143,7 @@ int ssb_pcmcia_switch_coreidx(struct ssb @@ -924,6 +1042,15 @@ bus->pcicore.dev = dev; --- a/drivers/ssb/sprom.c +++ b/drivers/ssb/sprom.c +@@ -54,7 +54,7 @@ static int hex2sprom(u16 *sprom, const c + while (cnt < sprom_size_words) { + memcpy(tmp, dump, 4); + dump += 4; +- err = strict_strtoul(tmp, 16, &parsed); ++ err = kstrtoul(tmp, 16, &parsed); + if (err) + return err; + sprom[cnt++] = swab16((u16)parsed); @@ -127,13 +127,13 @@ ssize_t ssb_attr_sprom_store(struct ssb_ goto out_kfree; err = ssb_devices_freeze(bus, &freeze); @@ -974,6 +1101,17 @@ #endif #ifdef CONFIG_SSB_DEBUG +@@ -232,6 +243,10 @@ static inline int ssb_sflash_init(struct + extern struct platform_device ssb_pflash_dev; + #endif + ++#ifdef CONFIG_SSB_SFLASH ++extern struct platform_device ssb_sflash_dev; ++#endif ++ + #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); --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h @@ -26,9 +26,9 @@ struct ssb_sprom_core_pwr_info { @@ -1054,9 +1192,48 @@ /* chip_package */ #define SSB_CHIPPACK_BCM4712S 1 /* Small 200pin 4712 */ #define SSB_CHIPPACK_BCM4712M 2 /* Medium 225pin 4712 */ +--- a/include/linux/ssb/ssb_driver_mips.h ++++ b/include/linux/ssb/ssb_driver_mips.h +@@ -20,6 +20,18 @@ struct ssb_pflash { + u32 window_size; + }; + ++#ifdef CONFIG_SSB_SFLASH ++struct ssb_sflash { ++ bool present; ++ u32 window; ++ u32 blocksize; ++ u16 numblocks; ++ u32 size; ++ ++ void *priv; ++}; ++#endif ++ + struct ssb_mipscore { + struct ssb_device *dev; + +@@ -27,6 +39,9 @@ struct ssb_mipscore { + struct ssb_serial_port serial_ports[4]; + + struct ssb_pflash pflash; ++#ifdef CONFIG_SSB_SFLASH ++ struct ssb_sflash sflash; ++#endif + }; + + extern void ssb_mipscore_init(struct ssb_mipscore *mcore); --- a/include/linux/ssb/ssb_regs.h +++ b/include/linux/ssb/ssb_regs.h -@@ -289,11 +289,11 @@ +@@ -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 +@@ -289,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 */ diff --git a/target/linux/generic/patches-3.9/025-bcma_backport.patch b/target/linux/generic/patches-3.9/025-bcma_backport.patch index a1a1ebc..04a4573 100644 --- a/target/linux/generic/patches-3.9/025-bcma_backport.patch +++ b/target/linux/generic/patches-3.9/025-bcma_backport.patch @@ -1,6 +1,80 @@ +--- a/drivers/bcma/Kconfig ++++ b/drivers/bcma/Kconfig +@@ -26,6 +26,7 @@ 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" +--- a/drivers/bcma/bcma_private.h ++++ b/drivers/bcma/bcma_private.h +@@ -22,6 +22,8 @@ + struct bcma_bus; + + /* main.c */ ++bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value, ++ int timeout); + int bcma_bus_register(struct bcma_bus *bus); + void bcma_bus_unregister(struct bcma_bus *bus); + int __init bcma_bus_early_register(struct bcma_bus *bus, --- a/drivers/bcma/core.c +++ b/drivers/bcma/core.c -@@ -104,7 +104,13 @@ void bcma_core_pll_ctl(struct bcma_devic +@@ -9,6 +9,25 @@ + #include <linux/export.h> + #include <linux/bcma/bcma.h> + ++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,13 +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); + +@@ -43,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)); +@@ -104,7 +126,13 @@ void bcma_core_pll_ctl(struct bcma_devic if (i) bcma_err(core->bus, "PLL enable timeout\n"); } else { @@ -33,7 +107,25 @@ static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc) { -@@ -213,6 +214,7 @@ u32 bcma_chipco_gpio_out(struct bcma_drv +@@ -139,8 +140,15 @@ void bcma_core_chipcommon_init(struct bc + 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) +@@ -213,6 +221,7 @@ u32 bcma_chipco_gpio_out(struct bcma_drv return res; } @@ -41,7 +133,7 @@ u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value) { -@@ -225,6 +227,7 @@ u32 bcma_chipco_gpio_outen(struct bcma_d +@@ -225,6 +234,7 @@ u32 bcma_chipco_gpio_outen(struct bcma_d return res; } @@ -51,7 +143,151 @@ * If the bit is set to 0, chipcommon controlls this GPIO, --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c -@@ -174,19 +174,35 @@ u32 bcma_pmu_get_alp_clock(struct bcma_d +@@ -56,6 +56,109 @@ void bcma_chipco_regctl_maskset(struct b + } + EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset); + ++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 BCMA_CHIP_ID_BCM43142: ++ if (xtalfreq == 0) ++ xtalfreq = 20000; ++ bcma_pmu2_pll_init0(cc, xtalfreq); ++ break; ++ } ++} ++ + static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) + { + struct bcma_bus *bus = cc->core->bus; +@@ -66,6 +169,25 @@ static void bcma_pmu_resources_init(stru + min_msk = 0x200D; + max_msk = 0xFFFF; + 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: + bcma_debug(bus, "PMU resource config unknown or not needed for device 0x%04X\n", + bus->chipinfo.id); +@@ -165,6 +287,7 @@ void bcma_pmu_init(struct bcma_drv_cc *c + bcma_cc_set32(cc, BCMA_CC_PMU_CTL, + BCMA_CC_PMU_CTL_NOILPONW); + ++ bcma_pmu_pll_init(cc); + bcma_pmu_resources_init(cc); + bcma_pmu_workarounds(cc); + } +@@ -174,19 +297,35 @@ u32 bcma_pmu_get_alp_clock(struct bcma_d struct bcma_bus *bus = cc->core->bus; switch (bus->chipinfo.id) { @@ -91,7 +327,7 @@ default: bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n", bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK); -@@ -373,7 +389,7 @@ void bcma_pmu_spuravoid_pllupdate(struct +@@ -373,7 +512,7 @@ void bcma_pmu_spuravoid_pllupdate(struct tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT; bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp); @@ -100,7 +336,7 @@ break; case BCMA_CHIP_ID_BCM4331: -@@ -394,7 +410,7 @@ void bcma_pmu_spuravoid_pllupdate(struct +@@ -394,7 +533,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 0x03000a08); } @@ -109,7 +345,7 @@ break; case BCMA_CHIP_ID_BCM43224: -@@ -427,7 +443,7 @@ void bcma_pmu_spuravoid_pllupdate(struct +@@ -427,7 +566,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 0x88888815); } @@ -118,7 +354,7 @@ break; case BCMA_CHIP_ID_BCM4716: -@@ -461,7 +477,7 @@ void bcma_pmu_spuravoid_pllupdate(struct +@@ -461,7 +600,7 @@ void bcma_pmu_spuravoid_pllupdate(struct 0x88888815); } @@ -127,7 +363,7 @@ break; case BCMA_CHIP_ID_BCM43227: -@@ -497,7 +513,7 @@ void bcma_pmu_spuravoid_pllupdate(struct +@@ -497,7 +636,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 0x88888815); } @@ -136,9 +372,83 @@ break; default: bcma_err(bus, "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n", +--- a/drivers/bcma/driver_chipcommon_sflash.c ++++ b/drivers/bcma/driver_chipcommon_sflash.c +@@ -30,7 +30,7 @@ struct bcma_sflash_tbl_e { + u16 numblocks; + }; + +-static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { ++static const struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { + { "M25P20", 0x11, 0x10000, 4, }, + { "M25P40", 0x12, 0x10000, 8, }, + +@@ -41,7 +41,7 @@ static struct bcma_sflash_tbl_e bcma_sfl + { 0 }, + }; + +-static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { ++static const struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { + { "SST25WF512", 1, 0x1000, 16, }, + { "SST25VF512", 0x48, 0x1000, 16, }, + { "SST25WF010", 2, 0x1000, 32, }, +@@ -59,7 +59,7 @@ static struct bcma_sflash_tbl_e bcma_sfl + { 0 }, + }; + +-static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { ++static const struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { + { "AT45DB011", 0xc, 256, 512, }, + { "AT45DB021", 0x14, 256, 1024, }, + { "AT45DB041", 0x1c, 256, 2048, }, +@@ -89,7 +89,7 @@ int bcma_sflash_init(struct bcma_drv_cc + { + struct bcma_bus *bus = cc->core->bus; + struct bcma_sflash *sflash = &cc->sflash; +- struct bcma_sflash_tbl_e *e; ++ const struct bcma_sflash_tbl_e *e; + u32 id, id2; + + switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { +--- a/drivers/bcma/host_pci.c ++++ b/drivers/bcma/host_pci.c +@@ -275,6 +275,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_ + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, + { 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, }, + }; --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c -@@ -120,6 +120,11 @@ static int bcma_register_cores(struct bc +@@ -93,6 +93,25 @@ struct bcma_device *bcma_find_core_unit( + 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) + { + struct bcma_device *core = container_of(dev, struct bcma_device, dev); +@@ -120,6 +139,11 @@ static int bcma_register_cores(struct bc continue; } @@ -152,7 +462,16 @@ dev_set_name(&core->dev, "bcma%d:%d", bus->num, dev_id); --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c -@@ -137,19 +137,19 @@ static void bcma_scan_switch_core(struct +@@ -84,6 +84,8 @@ static const struct bcma_device_id_name + { 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" }, + }; + +@@ -137,19 +139,19 @@ static void bcma_scan_switch_core(struct addr); } @@ -175,7 +494,7 @@ { u32 ent = bcma_erom_get_ent(bus, eromptr); if (!(ent & SCAN_ER_VALID)) -@@ -159,14 +159,14 @@ static s32 bcma_erom_get_ci(struct bcma_ +@@ -159,14 +161,14 @@ static s32 bcma_erom_get_ci(struct bcma_ return ent; } @@ -192,7 +511,7 @@ { u32 ent = bcma_erom_get_ent(bus, eromptr); bcma_erom_push_ent(eromptr); -@@ -175,7 +175,7 @@ static bool bcma_erom_is_bridge(struct b +@@ -175,7 +177,7 @@ static bool bcma_erom_is_bridge(struct b ((ent & SCAN_ADDR_TYPE) == SCAN_ADDR_TYPE_BRIDGE)); } @@ -201,7 +520,7 @@ { u32 ent; while (1) { -@@ -189,7 +189,7 @@ static void bcma_erom_skip_component(str +@@ -189,7 +191,7 @@ static void bcma_erom_skip_component(str bcma_erom_push_ent(eromptr); } @@ -210,7 +529,7 @@ { u32 ent = bcma_erom_get_ent(bus, eromptr); if (!(ent & SCAN_ER_VALID)) -@@ -199,7 +199,7 @@ static s32 bcma_erom_get_mst_port(struct +@@ -199,7 +201,7 @@ static s32 bcma_erom_get_mst_port(struct return ent; } @@ -221,7 +540,99 @@ u32 addrl, addrh, sizel, sizeh = 0; --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c -@@ -217,6 +217,7 @@ static void bcma_sprom_extract_r8(struct +@@ -72,12 +72,12 @@ fail: + * R/W ops. + **************************************************/ + +-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)); + } + + /************************************************** +@@ -124,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; +@@ -154,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; + } + +@@ -208,15 +212,13 @@ static void bcma_sprom_extract_r8(struct + 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; +- + for (i = 0; i < 3; i++) { + v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i]; + *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v); } SPEX(board_rev, SSB_SPROM8_BOARDREV, ~0, 0); @@ -229,17 +640,98 @@ SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT); +@@ -501,7 +503,7 @@ static bool bcma_sprom_onchip_available( + 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 */ +@@ -549,7 +551,9 @@ int bcma_sprom_get(struct bcma_bus *bus) + { + u16 offset = BCMA_CC_SPROM; + u16 *sprom; +- 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; +@@ -578,32 +582,37 @@ int bcma_sprom_get(struct bcma_bus *bus) + } + } + +- sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), +- GFP_KERNEL); +- if (!sprom) +- return -ENOMEM; +- + 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, false); + + 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; ++ ++ kfree(sprom); ++ } + + 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); + +- err = bcma_sprom_valid(sprom); + if (err) { +- bcma_warn(bus, "invalid sprom read from the PCIe card, try to use fallback sprom\n"); ++ 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); +- goto out; ++ } else { ++ bcma_sprom_extract_r8(bus, sprom); ++ kfree(sprom); + } + +- bcma_sprom_extract_r8(bus, sprom); +- +-out: +- kfree(sprom); + return err; + } --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h -@@ -134,6 +134,7 @@ struct bcma_host_ops { +@@ -134,12 +134,17 @@ 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_ARM_CR4 0x83e ++#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 -@@ -173,6 +174,60 @@ struct bcma_host_ops { + + /* 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 +@@ -173,6 +178,60 @@ struct bcma_host_ops { #define BCMA_CHIP_ID_BCM53572 53572 #define BCMA_PKG_ID_BCM47188 9 @@ -320,7 +812,90 @@ #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 */ -@@ -607,6 +611,8 @@ void bcma_chipco_bcm4331_ext_pa_lines_ct +@@ -326,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 */ +@@ -351,6 +357,11 @@ + #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 */ + /* NAND flash MLC controller registers (corerev >= 38) */ + #define BCMA_CC_NAND_REVISION 0x0C00 +@@ -431,6 +442,23 @@ + #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 + /* HT clock for systems with PMU-enabled chipcommon */ +@@ -503,6 +531,37 @@ + #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) + */ +@@ -607,6 +666,8 @@ void bcma_chipco_bcm4331_ext_pa_lines_ct extern u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks); |