From 85dd88a3c6f86d2ecd5c2233aca50752b5ccafbc Mon Sep 17 00:00:00 2001 From: hauke Date: Mon, 27 Jun 2011 20:18:49 +0000 Subject: [PATCH] kernel: update ssb and bcma to linux-next next-20110627 git-svn-id: svn://svn.openwrt.org/openwrt/trunk@27293 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../generic/patches-3.0/020-ssb_update.patch | 190 +++++++ .../patches-3.0/025-bcma_backport.patch | 494 ++++++++++++++++++ 2 files changed, 684 insertions(+) create mode 100644 target/linux/generic/patches-3.0/020-ssb_update.patch create mode 100644 target/linux/generic/patches-3.0/025-bcma_backport.patch diff --git a/target/linux/generic/patches-3.0/020-ssb_update.patch b/target/linux/generic/patches-3.0/020-ssb_update.patch new file mode 100644 index 000000000..3282ff0d7 --- /dev/null +++ b/target/linux/generic/patches-3.0/020-ssb_update.patch @@ -0,0 +1,190 @@ +--- a/drivers/ssb/driver_chipcommon_pmu.c ++++ b/drivers/ssb/driver_chipcommon_pmu.c +@@ -417,9 +417,9 @@ static void ssb_pmu_resources_init(struc + u32 min_msk = 0, max_msk = 0; + unsigned int i; + const struct pmu_res_updown_tab_entry *updown_tab = NULL; +- unsigned int updown_tab_size; ++ unsigned int updown_tab_size = 0; + const struct pmu_res_depend_tab_entry *depend_tab = NULL; +- unsigned int depend_tab_size; ++ unsigned int depend_tab_size = 0; + + switch (bus->chip_id) { + case 0x4312: +--- a/drivers/ssb/driver_gige.c ++++ b/drivers/ssb/driver_gige.c +@@ -106,8 +106,9 @@ void gige_pcicfg_write32(struct ssb_gige + gige_write32(dev, SSB_GIGE_PCICFG + offset, value); + } + +-static int ssb_gige_pci_read_config(struct pci_bus *bus, unsigned int devfn, +- int reg, int size, u32 *val) ++static int __devinit ssb_gige_pci_read_config(struct pci_bus *bus, ++ unsigned int devfn, int reg, ++ int size, u32 *val) + { + struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops); + unsigned long flags; +@@ -136,8 +137,9 @@ static int ssb_gige_pci_read_config(stru + return PCIBIOS_SUCCESSFUL; + } + +-static int ssb_gige_pci_write_config(struct pci_bus *bus, unsigned int devfn, +- int reg, int size, u32 val) ++static int __devinit ssb_gige_pci_write_config(struct pci_bus *bus, ++ unsigned int devfn, int reg, ++ int size, u32 val) + { + struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops); + unsigned long flags; +@@ -166,7 +168,8 @@ static int ssb_gige_pci_write_config(str + return PCIBIOS_SUCCESSFUL; + } + +-static int ssb_gige_probe(struct ssb_device *sdev, const struct ssb_device_id *id) ++static int __devinit ssb_gige_probe(struct ssb_device *sdev, ++ const struct ssb_device_id *id) + { + struct ssb_gige *dev; + u32 base, tmslow, tmshigh; +--- a/drivers/ssb/driver_pcicore.c ++++ b/drivers/ssb/driver_pcicore.c +@@ -314,7 +314,7 @@ int ssb_pcicore_pcibios_map_irq(const st + return ssb_mips_irq(extpci_core->dev) + 2; + } + +-static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) ++static void __devinit ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) + { + u32 val; + +@@ -379,7 +379,7 @@ static void ssb_pcicore_init_hostmode(st + register_pci_controller(&ssb_pcicore_controller); + } + +-static int pcicore_is_in_hostmode(struct ssb_pcicore *pc) ++static int __devinit pcicore_is_in_hostmode(struct ssb_pcicore *pc) + { + struct ssb_bus *bus = pc->dev->bus; + u16 chipid_top; +@@ -412,7 +412,7 @@ static int pcicore_is_in_hostmode(struct + * Workarounds. + **************************************************/ + +-static void ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc) ++static void __devinit ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc) + { + u16 tmp = pcicore_read16(pc, SSB_PCICORE_SPROM(0)); + if (((tmp & 0xF000) >> 12) != pc->dev->core_index) { +@@ -514,13 +514,13 @@ static void ssb_pcicore_pcie_setup_worka + * Generic and Clientmode operation code. + **************************************************/ + +-static void ssb_pcicore_init_clientmode(struct ssb_pcicore *pc) ++static void __devinit ssb_pcicore_init_clientmode(struct ssb_pcicore *pc) + { + /* Disable PCI interrupts. */ + ssb_write32(pc->dev, SSB_INTVEC, 0); + } + +-void ssb_pcicore_init(struct ssb_pcicore *pc) ++void __devinit ssb_pcicore_init(struct ssb_pcicore *pc) + { + struct ssb_device *dev = pc->dev; + +--- a/drivers/ssb/main.c ++++ b/drivers/ssb/main.c +@@ -557,7 +557,7 @@ error: + } + + /* Needs ssb_buses_lock() */ +-static int ssb_attach_queued_buses(void) ++static int __devinit ssb_attach_queued_buses(void) + { + struct ssb_bus *bus, *n; + int err = 0; +@@ -768,9 +768,9 @@ out: + return err; + } + +-static int ssb_bus_register(struct ssb_bus *bus, +- ssb_invariants_func_t get_invariants, +- unsigned long baseaddr) ++static int __devinit ssb_bus_register(struct ssb_bus *bus, ++ ssb_invariants_func_t get_invariants, ++ unsigned long baseaddr) + { + int err; + +@@ -851,8 +851,8 @@ err_disable_xtal: + } + + #ifdef CONFIG_SSB_PCIHOST +-int ssb_bus_pcibus_register(struct ssb_bus *bus, +- struct pci_dev *host_pci) ++int __devinit ssb_bus_pcibus_register(struct ssb_bus *bus, ++ struct pci_dev *host_pci) + { + int err; + +@@ -875,9 +875,9 @@ EXPORT_SYMBOL(ssb_bus_pcibus_register); + #endif /* CONFIG_SSB_PCIHOST */ + + #ifdef CONFIG_SSB_PCMCIAHOST +-int ssb_bus_pcmciabus_register(struct ssb_bus *bus, +- struct pcmcia_device *pcmcia_dev, +- unsigned long baseaddr) ++int __devinit ssb_bus_pcmciabus_register(struct ssb_bus *bus, ++ struct pcmcia_device *pcmcia_dev, ++ unsigned long baseaddr) + { + int err; + +@@ -897,8 +897,9 @@ EXPORT_SYMBOL(ssb_bus_pcmciabus_register + #endif /* CONFIG_SSB_PCMCIAHOST */ + + #ifdef CONFIG_SSB_SDIOHOST +-int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func, +- unsigned int quirks) ++int __devinit ssb_bus_sdiobus_register(struct ssb_bus *bus, ++ struct sdio_func *func, ++ unsigned int quirks) + { + int err; + +@@ -918,9 +919,9 @@ int ssb_bus_sdiobus_register(struct ssb_ + EXPORT_SYMBOL(ssb_bus_sdiobus_register); + #endif /* CONFIG_SSB_PCMCIAHOST */ + +-int ssb_bus_ssbbus_register(struct ssb_bus *bus, +- unsigned long baseaddr, +- ssb_invariants_func_t get_invariants) ++int __devinit ssb_bus_ssbbus_register(struct ssb_bus *bus, ++ unsigned long baseaddr, ++ ssb_invariants_func_t get_invariants) + { + int err; + +--- a/drivers/ssb/pcihost_wrapper.c ++++ b/drivers/ssb/pcihost_wrapper.c +@@ -53,8 +53,8 @@ static int ssb_pcihost_resume(struct pci + # define ssb_pcihost_resume NULL + #endif /* CONFIG_PM */ + +-static int ssb_pcihost_probe(struct pci_dev *dev, +- const struct pci_device_id *id) ++static int __devinit ssb_pcihost_probe(struct pci_dev *dev, ++ const struct pci_device_id *id) + { + struct ssb_bus *ssb; + int err = -ENOMEM; +@@ -110,7 +110,7 @@ static void ssb_pcihost_remove(struct pc + pci_set_drvdata(dev, NULL); + } + +-int ssb_pcihost_register(struct pci_driver *driver) ++int __devinit ssb_pcihost_register(struct pci_driver *driver) + { + driver->probe = ssb_pcihost_probe; + driver->remove = ssb_pcihost_remove; diff --git a/target/linux/generic/patches-3.0/025-bcma_backport.patch b/target/linux/generic/patches-3.0/025-bcma_backport.patch new file mode 100644 index 000000000..8f02d9e80 --- /dev/null +++ b/target/linux/generic/patches-3.0/025-bcma_backport.patch @@ -0,0 +1,494 @@ +--- a/drivers/bcma/Kconfig ++++ b/drivers/bcma/Kconfig +@@ -13,6 +13,11 @@ config BCMA + Bus driver for Broadcom specific Advanced Microcontroller Bus + Architecture. + ++# Support for Block-I/O. SELECT this from the driver that needs it. ++config BCMA_BLOCKIO ++ bool ++ depends on BCMA ++ + config BCMA_HOST_PCI_POSSIBLE + bool + depends on BCMA && PCI = y +--- a/drivers/bcma/Makefile ++++ b/drivers/bcma/Makefile +@@ -1,4 +1,4 @@ +-bcma-y += main.o scan.o core.o ++bcma-y += main.o scan.o core.o sprom.o + bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o + bcma-y += driver_pci.o + bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o +--- a/drivers/bcma/bcma_private.h ++++ b/drivers/bcma/bcma_private.h +@@ -13,12 +13,15 @@ + struct bcma_bus; + + /* main.c */ +-extern int bcma_bus_register(struct bcma_bus *bus); +-extern void bcma_bus_unregister(struct bcma_bus *bus); ++int bcma_bus_register(struct bcma_bus *bus); ++void bcma_bus_unregister(struct bcma_bus *bus); + + /* scan.c */ + int bcma_bus_scan(struct bcma_bus *bus); + ++/* sprom.c */ ++int bcma_sprom_get(struct bcma_bus *bus); ++ + #ifdef CONFIG_BCMA_HOST_PCI + /* host_pci.c */ + extern int __init bcma_host_pci_init(void); +--- a/drivers/bcma/core.c ++++ b/drivers/bcma/core.c +@@ -19,7 +19,7 @@ bool bcma_core_is_enabled(struct bcma_de + } + EXPORT_SYMBOL_GPL(bcma_core_is_enabled); + +-static void bcma_core_disable(struct bcma_device *core, u32 flags) ++void bcma_core_disable(struct bcma_device *core, u32 flags) + { + if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET) + return; +@@ -31,6 +31,7 @@ static void bcma_core_disable(struct bcm + bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET); + udelay(1); + } ++EXPORT_SYMBOL_GPL(bcma_core_disable); + + int bcma_core_enable(struct bcma_device *core, u32 flags) + { +--- a/drivers/bcma/driver_chipcommon_pmu.c ++++ b/drivers/bcma/driver_chipcommon_pmu.c +@@ -53,6 +53,7 @@ static void bcma_pmu_resources_init(stru + max_msk = 0xFFFF; + break; + case 43224: ++ case 43225: + break; + default: + pr_err("PMU resource config unknown for device 0x%04X\n", +@@ -74,6 +75,7 @@ void bcma_pmu_swreg_init(struct bcma_drv + case 0x4313: + case 0x4331: + case 43224: ++ case 43225: + break; + default: + pr_err("PMU switch/regulators init unknown for device " +@@ -96,11 +98,13 @@ void bcma_pmu_workarounds(struct bcma_dr + if (bus->chipinfo.rev == 0) { + pr_err("Workarounds for 43224 rev 0 not fully " + "implemented\n"); +- bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0); ++ bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x00F000F0); + } else { + bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0); + } + break; ++ case 43225: ++ break; + default: + pr_err("Workarounds unknown for device 0x%04X\n", + bus->chipinfo.id); +--- a/drivers/bcma/driver_pci.c ++++ b/drivers/bcma/driver_pci.c +@@ -161,3 +161,27 @@ void bcma_core_pci_init(struct bcma_drv_ + { + bcma_pcicore_serdes_workaround(pc); + } ++ ++int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core, ++ bool enable) ++{ ++ struct pci_dev *pdev = pc->core->bus->host_pci; ++ u32 coremask, tmp; ++ int err; ++ ++ err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp); ++ if (err) ++ goto out; ++ ++ coremask = BIT(core->core_index) << 8; ++ if (enable) ++ tmp |= coremask; ++ else ++ tmp &= ~coremask; ++ ++ err = pci_write_config_dword(pdev, BCMA_PCI_IRQMASK, tmp); ++ ++out: ++ return err; ++} ++EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl); +--- a/drivers/bcma/host_pci.c ++++ b/drivers/bcma/host_pci.c +@@ -65,6 +65,54 @@ static void bcma_host_pci_write32(struct + iowrite32(value, core->bus->mmio + offset); + } + ++#ifdef CONFIG_BCMA_BLOCKIO ++void bcma_host_pci_block_read(struct bcma_device *core, void *buffer, ++ size_t count, u16 offset, u8 reg_width) ++{ ++ void __iomem *addr = core->bus->mmio + offset; ++ if (core->bus->mapped_core != core) ++ bcma_host_pci_switch_core(core); ++ switch (reg_width) { ++ case sizeof(u8): ++ ioread8_rep(addr, buffer, count); ++ break; ++ case sizeof(u16): ++ WARN_ON(count & 1); ++ ioread16_rep(addr, buffer, count >> 1); ++ break; ++ case sizeof(u32): ++ WARN_ON(count & 3); ++ ioread32_rep(addr, buffer, count >> 2); ++ break; ++ default: ++ WARN_ON(1); ++ } ++} ++ ++void bcma_host_pci_block_write(struct bcma_device *core, const void *buffer, ++ size_t count, u16 offset, u8 reg_width) ++{ ++ void __iomem *addr = core->bus->mmio + offset; ++ if (core->bus->mapped_core != core) ++ bcma_host_pci_switch_core(core); ++ switch (reg_width) { ++ case sizeof(u8): ++ iowrite8_rep(addr, buffer, count); ++ break; ++ case sizeof(u16): ++ WARN_ON(count & 1); ++ iowrite16_rep(addr, buffer, count >> 1); ++ break; ++ case sizeof(u32): ++ WARN_ON(count & 3); ++ iowrite32_rep(addr, buffer, count >> 2); ++ break; ++ default: ++ WARN_ON(1); ++ } ++} ++#endif ++ + static u32 bcma_host_pci_aread32(struct bcma_device *core, u16 offset) + { + if (core->bus->mapped_core != core) +@@ -87,6 +135,10 @@ const struct bcma_host_ops bcma_host_pci + .write8 = bcma_host_pci_write8, + .write16 = bcma_host_pci_write16, + .write32 = bcma_host_pci_write32, ++#ifdef CONFIG_BCMA_BLOCKIO ++ .block_read = bcma_host_pci_block_read, ++ .block_write = bcma_host_pci_block_write, ++#endif + .aread32 = bcma_host_pci_aread32, + .awrite32 = bcma_host_pci_awrite32, + }; +@@ -175,6 +227,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_ + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, + { 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, 0x4727) }, + { 0, }, + }; +--- a/drivers/bcma/main.c ++++ b/drivers/bcma/main.c +@@ -89,6 +89,8 @@ static int bcma_register_cores(struct bc + switch (bus->hosttype) { + case BCMA_HOSTTYPE_PCI: + core->dev.parent = &bus->host_pci->dev; ++ core->dma_dev = &bus->host_pci->dev; ++ core->irq = bus->host_pci->irq; + break; + case BCMA_HOSTTYPE_NONE: + case BCMA_HOSTTYPE_SDIO: +@@ -144,6 +146,13 @@ int bcma_bus_register(struct bcma_bus *b + bcma_core_pci_init(&bus->drv_pci); + } + ++ /* Try to get SPROM */ ++ err = bcma_sprom_get(bus); ++ if (err) { ++ pr_err("Failed to get SPROM: %d\n", err); ++ return -ENOENT; ++ } ++ + /* Register found cores */ + bcma_register_cores(bus); + +@@ -151,13 +160,11 @@ int bcma_bus_register(struct bcma_bus *b + + return 0; + } +-EXPORT_SYMBOL_GPL(bcma_bus_register); + + void bcma_bus_unregister(struct bcma_bus *bus) + { + bcma_unregister_cores(bus); + } +-EXPORT_SYMBOL_GPL(bcma_bus_unregister); + + int __bcma_driver_register(struct bcma_driver *drv, struct module *owner) + { +--- /dev/null ++++ b/drivers/bcma/sprom.c +@@ -0,0 +1,162 @@ ++/* ++ * Broadcom specific AMBA ++ * SPROM reading ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++#include "bcma_private.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define SPOFF(offset) ((offset) / sizeof(u16)) ++ ++/************************************************** ++ * R/W ops. ++ **************************************************/ ++ ++static void bcma_sprom_read(struct bcma_bus *bus, u16 *sprom) ++{ ++ int i; ++ for (i = 0; i < SSB_SPROMSIZE_WORDS_R4; i++) ++ sprom[i] = bcma_read16(bus->drv_cc.core, ++ BCMA_CC_SPROM + (i * 2)); ++} ++ ++/************************************************** ++ * Validation. ++ **************************************************/ ++ ++static inline u8 bcma_crc8(u8 crc, u8 data) ++{ ++ /* Polynomial: x^8 + x^7 + x^6 + x^4 + x^2 + 1 */ ++ static const u8 t[] = { ++ 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, ++ 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, ++ 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, ++ 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, ++ 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, ++ 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, ++ 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, ++ 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, ++ 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, ++ 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, ++ 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, ++ 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, ++ 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, ++ 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, ++ 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, ++ 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, ++ 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, ++ 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, ++ 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, ++ 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, ++ 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, ++ 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, ++ 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, ++ 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, ++ 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, ++ 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, ++ 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, ++ 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, ++ 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, ++ 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, ++ 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, ++ 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F, ++ }; ++ return t[crc ^ data]; ++} ++ ++static u8 bcma_sprom_crc(const u16 *sprom) ++{ ++ int word; ++ u8 crc = 0xFF; ++ ++ for (word = 0; word < SSB_SPROMSIZE_WORDS_R4 - 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 ^= 0xFF; ++ ++ return crc; ++} ++ ++static int bcma_sprom_check_crc(const u16 *sprom) ++{ ++ u8 crc; ++ u8 expected_crc; ++ u16 tmp; ++ ++ crc = bcma_sprom_crc(sprom); ++ tmp = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_CRC; ++ expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT; ++ if (crc != expected_crc) ++ return -EPROTO; ++ ++ return 0; ++} ++ ++static int bcma_sprom_valid(const u16 *sprom) ++{ ++ u16 revision; ++ int err; ++ ++ err = bcma_sprom_check_crc(sprom); ++ if (err) ++ return err; ++ ++ revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_REV; ++ if (revision != 8) { ++ pr_err("Unsupported SPROM revision: %d\n", revision); ++ return -ENOENT; ++ } ++ ++ return 0; ++} ++ ++/************************************************** ++ * SPROM extraction. ++ **************************************************/ ++ ++static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) ++{ ++ u16 v; ++ int i; ++ ++ for (i = 0; i < 3; i++) { ++ v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i]; ++ *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v); ++ } ++} ++ ++int bcma_sprom_get(struct bcma_bus *bus) ++{ ++ u16 *sprom; ++ int err = 0; ++ ++ if (!bus->drv_cc.core) ++ return -EOPNOTSUPP; ++ ++ sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), ++ GFP_KERNEL); ++ if (!sprom) ++ return -ENOMEM; ++ ++ bcma_sprom_read(bus, sprom); ++ ++ err = bcma_sprom_valid(sprom); ++ if (err) ++ goto out; ++ ++ bcma_sprom_extract_r8(bus, sprom); ++ ++out: ++ kfree(sprom); ++ return err; ++} +--- a/include/linux/bcma/bcma.h ++++ b/include/linux/bcma/bcma.h +@@ -6,6 +6,7 @@ + + #include + #include ++#include /* SPROM sharing */ + + #include "bcma_regs.h" + +@@ -31,6 +32,12 @@ struct bcma_host_ops { + void (*write8)(struct bcma_device *core, u16 offset, u8 value); + void (*write16)(struct bcma_device *core, u16 offset, u16 value); + void (*write32)(struct bcma_device *core, u16 offset, u32 value); ++#ifdef CONFIG_BCMA_BLOCKIO ++ void (*block_read)(struct bcma_device *core, void *buffer, ++ size_t count, u16 offset, u8 reg_width); ++ void (*block_write)(struct bcma_device *core, const void *buffer, ++ size_t count, u16 offset, u8 reg_width); ++#endif + /* Agent ops */ + u32 (*aread32)(struct bcma_device *core, u16 offset); + void (*awrite32)(struct bcma_device *core, u16 offset, u32 value); +@@ -117,6 +124,8 @@ struct bcma_device { + struct bcma_device_id id; + + struct device dev; ++ struct device *dma_dev; ++ unsigned int irq; + bool dev_registered; + + u8 core_index; +@@ -179,6 +188,10 @@ struct bcma_bus { + + struct bcma_drv_cc drv_cc; + struct bcma_drv_pci drv_pci; ++ ++ /* We decided to share SPROM struct with SSB as long as we do not need ++ * any hacks for BCMA. This simplifies drivers code. */ ++ struct ssb_sprom sprom; + }; + + extern inline u32 bcma_read8(struct bcma_device *core, u16 offset) +@@ -208,6 +221,18 @@ void bcma_write32(struct bcma_device *co + { + core->bus->ops->write32(core, offset, value); + } ++#ifdef CONFIG_BCMA_BLOCKIO ++extern inline void bcma_block_read(struct bcma_device *core, void *buffer, ++ size_t count, u16 offset, u8 reg_width) ++{ ++ core->bus->ops->block_read(core, buffer, count, offset, reg_width); ++} ++extern inline void bcma_block_write(struct bcma_device *core, const void *buffer, ++ size_t count, u16 offset, u8 reg_width) ++{ ++ core->bus->ops->block_write(core, buffer, count, offset, reg_width); ++} ++#endif + extern inline u32 bcma_aread32(struct bcma_device *core, u16 offset) + { + return core->bus->ops->aread32(core, offset); +@@ -219,6 +244,7 @@ void bcma_awrite32(struct bcma_device *c + } + + 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); + + #endif /* LINUX_BCMA_H_ */ +--- a/include/linux/bcma/bcma_driver_chipcommon.h ++++ b/include/linux/bcma/bcma_driver_chipcommon.h +@@ -244,6 +244,7 @@ + #define BCMA_CC_REGCTL_DATA 0x065C + #define BCMA_CC_PLLCTL_ADDR 0x0660 + #define BCMA_CC_PLLCTL_DATA 0x0664 ++#define BCMA_CC_SPROM 0x0830 /* SPROM beginning */ + + /* Data for the PMU, if available. + * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU) +--- a/include/linux/bcma/bcma_driver_pci.h ++++ b/include/linux/bcma/bcma_driver_pci.h +@@ -85,5 +85,7 @@ struct bcma_drv_pci { + #define pcicore_write32(pc, offset, val) bcma_write32((pc)->core, offset, val) + + extern void bcma_core_pci_init(struct bcma_drv_pci *pc); ++extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, ++ struct bcma_device *core, bool enable); + + #endif /* LINUX_BCMA_DRIVER_PCI_H_ */