diff options
Diffstat (limited to 'drivers/bcma')
-rw-r--r-- | drivers/bcma/bcma_private.h | 4 | ||||
-rw-r--r-- | drivers/bcma/host_pci.c | 62 | ||||
-rw-r--r-- | drivers/bcma/main.c | 44 | ||||
-rw-r--r-- | drivers/bcma/scan.c | 19 | ||||
-rw-r--r-- | drivers/bcma/sprom.c | 61 |
5 files changed, 168 insertions, 22 deletions
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 30a3085d3354..0def898a1d15 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h @@ -18,6 +18,10 @@ void bcma_bus_unregister(struct bcma_bus *bus); int __init bcma_bus_early_register(struct bcma_bus *bus, struct bcma_device *core_cc, struct bcma_device *core_mips); +#ifdef CONFIG_PM +int bcma_bus_suspend(struct bcma_bus *bus); +int bcma_bus_resume(struct bcma_bus *bus); +#endif /* scan.c */ int bcma_bus_scan(struct bcma_bus *bus); diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index 1b51d8b7ac80..f59244e33971 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c @@ -21,48 +21,58 @@ static void bcma_host_pci_switch_core(struct bcma_device *core) pr_debug("Switched to core: 0x%X\n", core->id.id); } -static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset) +/* Provides access to the requested core. Returns base offset that has to be + * used. It makes use of fixed windows when possible. */ +static u16 bcma_host_pci_provide_access_to_core(struct bcma_device *core) { + switch (core->id.id) { + case BCMA_CORE_CHIPCOMMON: + return 3 * BCMA_CORE_SIZE; + case BCMA_CORE_PCIE: + return 2 * BCMA_CORE_SIZE; + } + if (core->bus->mapped_core != core) bcma_host_pci_switch_core(core); + return 0; +} + +static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset) +{ + offset += bcma_host_pci_provide_access_to_core(core); return ioread8(core->bus->mmio + offset); } static u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset) { - if (core->bus->mapped_core != core) - bcma_host_pci_switch_core(core); + offset += bcma_host_pci_provide_access_to_core(core); return ioread16(core->bus->mmio + offset); } static u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset) { - if (core->bus->mapped_core != core) - bcma_host_pci_switch_core(core); + offset += bcma_host_pci_provide_access_to_core(core); return ioread32(core->bus->mmio + offset); } static void bcma_host_pci_write8(struct bcma_device *core, u16 offset, u8 value) { - if (core->bus->mapped_core != core) - bcma_host_pci_switch_core(core); + offset += bcma_host_pci_provide_access_to_core(core); iowrite8(value, core->bus->mmio + offset); } static void bcma_host_pci_write16(struct bcma_device *core, u16 offset, u16 value) { - if (core->bus->mapped_core != core) - bcma_host_pci_switch_core(core); + offset += bcma_host_pci_provide_access_to_core(core); iowrite16(value, core->bus->mmio + offset); } static void bcma_host_pci_write32(struct bcma_device *core, u16 offset, u32 value) { - if (core->bus->mapped_core != core) - bcma_host_pci_switch_core(core); + offset += bcma_host_pci_provide_access_to_core(core); iowrite32(value, core->bus->mmio + offset); } @@ -224,6 +234,35 @@ static void bcma_host_pci_remove(struct pci_dev *dev) pci_set_drvdata(dev, NULL); } +#ifdef CONFIG_PM +static int bcma_host_pci_suspend(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct bcma_bus *bus = pci_get_drvdata(pdev); + + bus->mapped_core = NULL; + + return bcma_bus_suspend(bus); +} + +static int bcma_host_pci_resume(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct bcma_bus *bus = pci_get_drvdata(pdev); + + return bcma_bus_resume(bus); +} + +static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend, + bcma_host_pci_resume); +#define BCMA_PM_OPS (&bcma_pm_ops) + +#else /* CONFIG_PM */ + +#define BCMA_PM_OPS NULL + +#endif /* CONFIG_PM */ + static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, @@ -239,6 +278,7 @@ static struct pci_driver bcma_pci_bridge_driver = { .id_table = bcma_pci_bridge_tbl, .probe = bcma_host_pci_probe, .remove = bcma_host_pci_remove, + .driver.pm = BCMA_PM_OPS, }; int __init bcma_host_pci_init(void) diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 70c84b951098..ec31f7dd5549 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -169,10 +169,8 @@ int bcma_bus_register(struct bcma_bus *bus) err = bcma_sprom_get(bus); if (err == -ENOENT) { pr_err("No SPROM available\n"); - } else if (err) { + } else if (err) pr_err("Failed to get SPROM: %d\n", err); - return -ENOENT; - } /* Register found cores */ bcma_register_cores(bus); @@ -240,6 +238,46 @@ int __init bcma_bus_early_register(struct bcma_bus *bus, return 0; } +#ifdef CONFIG_PM +int bcma_bus_suspend(struct bcma_bus *bus) +{ + struct bcma_device *core; + + list_for_each_entry(core, &bus->cores, list) { + struct device_driver *drv = core->dev.driver; + if (drv) { + struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv); + if (adrv->suspend) + adrv->suspend(core); + } + } + return 0; +} + +int bcma_bus_resume(struct bcma_bus *bus) +{ + struct bcma_device *core; + + /* Init CC core */ + core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON); + if (core) { + bus->drv_cc.setup_done = false; + bcma_core_chipcommon_init(&bus->drv_cc); + } + + list_for_each_entry(core, &bus->cores, list) { + struct device_driver *drv = core->dev.driver; + if (drv) { + struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv); + if (adrv->resume) + adrv->resume(core); + } + } + + return 0; +} +#endif + int __bcma_driver_register(struct bcma_driver *drv, struct module *owner) { drv->drv.name = drv->name; diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index cad994857683..3a2f672db9ad 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c @@ -399,15 +399,18 @@ int bcma_bus_scan(struct bcma_bus *bus) core->bus = bus; err = bcma_get_next_core(bus, &eromptr, NULL, core_num, core); - if (err == -ENODEV) { - core_num++; - continue; - } else if (err == -ENXIO) - continue; - else if (err == -ESPIPE) - break; - else if (err < 0) + if (err < 0) { + kfree(core); + if (err == -ENODEV) { + core_num++; + continue; + } else if (err == -ENXIO) { + continue; + } else if (err == -ESPIPE) { + break; + } return err; + } core->core_index = core_num++; bus->nr_cores++; diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index d7292390d236..6f230fb087c5 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c @@ -129,6 +129,9 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) u16 v; int i; + 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); @@ -136,12 +139,70 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) bus->sprom.board_rev = sprom[SPOFF(SSB_SPROM8_BOARDREV)]; + 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; } int bcma_sprom_get(struct bcma_bus *bus) |