diff options
Diffstat (limited to 'drivers/bcma')
-rw-r--r-- | drivers/bcma/core.c | 72 | ||||
-rw-r--r-- | drivers/bcma/driver_chipcommon.c | 14 | ||||
-rw-r--r-- | drivers/bcma/driver_pci.c | 2 | ||||
-rw-r--r-- | drivers/bcma/sprom.c | 14 |
4 files changed, 98 insertions, 4 deletions
diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c index 1ec7d45..4a04a49 100644 --- a/drivers/bcma/core.c +++ b/drivers/bcma/core.c @@ -50,3 +50,75 @@ int bcma_core_enable(struct bcma_device *core, u32 flags) return 0; } EXPORT_SYMBOL_GPL(bcma_core_enable); + +void bcma_core_set_clockmode(struct bcma_device *core, + enum bcma_clkmode clkmode) +{ + u16 i; + + WARN_ON(core->id.id != BCMA_CORE_CHIPCOMMON && + core->id.id != BCMA_CORE_PCIE && + core->id.id != BCMA_CORE_80211); + + switch (clkmode) { + case BCMA_CLKMODE_FAST: + bcma_set32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT); + udelay(64); + for (i = 0; i < 1500; i++) { + if (bcma_read32(core, BCMA_CLKCTLST) & + BCMA_CLKCTLST_HAVEHT) { + i = 0; + break; + } + udelay(10); + } + if (i) + pr_err("HT force timeout\n"); + break; + case BCMA_CLKMODE_DYNAMIC: + pr_warn("Dynamic clockmode not supported yet!\n"); + break; + } +} +EXPORT_SYMBOL_GPL(bcma_core_set_clockmode); + +void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, bool on) +{ + u16 i; + + WARN_ON(req & ~BCMA_CLKCTLST_EXTRESREQ); + WARN_ON(status & ~BCMA_CLKCTLST_EXTRESST); + + if (on) { + bcma_set32(core, BCMA_CLKCTLST, req); + for (i = 0; i < 10000; i++) { + if ((bcma_read32(core, BCMA_CLKCTLST) & status) == + status) { + i = 0; + break; + } + udelay(10); + } + if (i) + pr_err("PLL enable timeout\n"); + } else { + pr_warn("Disabling PLL not supported yet!\n"); + } +} +EXPORT_SYMBOL_GPL(bcma_core_pll_ctl); + +u32 bcma_core_dma_translation(struct bcma_device *core) +{ + switch (core->bus->hosttype) { + case BCMA_HOSTTYPE_PCI: + if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64) + return BCMA_DMA_TRANSLATION_DMA64_CMT; + else + return BCMA_DMA_TRANSLATION_DMA32_CMT; + default: + pr_err("DMA translation unknown for host %d\n", + core->bus->hosttype); + } + return BCMA_DMA_TRANSLATION_NONE; +} +EXPORT_SYMBOL(bcma_core_dma_translation); diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c index 6061022..fb54302 100644 --- a/drivers/bcma/driver_chipcommon.c +++ b/drivers/bcma/driver_chipcommon.c @@ -23,6 +23,9 @@ static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) { + u32 leddc_on = 10; + u32 leddc_off = 90; + if (cc->core->id.rev >= 11) cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP); @@ -38,6 +41,17 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) bcma_pmu_init(cc); if (cc->capabilities & BCMA_CC_CAP_PCTL) pr_err("Power control not implemented!\n"); + + if (cc->core->id.rev >= 16) { + if (cc->core->bus->sprom.leddc_on_time && + cc->core->bus->sprom.leddc_off_time) { + leddc_on = cc->core->bus->sprom.leddc_on_time; + leddc_off = cc->core->bus->sprom.leddc_off_time; + } + bcma_cc_write32(cc, BCMA_CC_GPIOTIMER, + ((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) | + (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT))); + } } /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */ diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c index dc6f34a..745d264 100644 --- a/drivers/bcma/driver_pci.c +++ b/drivers/bcma/driver_pci.c @@ -172,8 +172,10 @@ static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) chipid_top != 0x5300) return false; +#ifdef CONFIG_SSB_DRIVER_PCICORE if (bus->sprom.boardflags_lo & SSB_PCICORE_BFL_NOPCI) return false; +#endif /* CONFIG_SSB_DRIVER_PCICORE */ #if 0 /* TODO: on BCMA we use address from EROM instead of magic formula */ diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index 8e8d5cf..8b5b785 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c @@ -20,12 +20,12 @@ * R/W ops. **************************************************/ -static void bcma_sprom_read(struct bcma_bus *bus, u16 *sprom) +static void bcma_sprom_read(struct bcma_bus *bus, u16 offset, 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)); + offset + (i * 2)); } /************************************************** @@ -112,7 +112,7 @@ static int bcma_sprom_valid(const u16 *sprom) return err; revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_REV; - if (revision != 8) { + if (revision != 8 && revision != 9) { pr_err("Unsupported SPROM revision: %d\n", revision); return -ENOENT; } @@ -137,6 +137,7 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) int bcma_sprom_get(struct bcma_bus *bus) { + u16 offset; u16 *sprom; int err = 0; @@ -151,7 +152,12 @@ int bcma_sprom_get(struct bcma_bus *bus) if (!sprom) return -ENOMEM; - bcma_sprom_read(bus, sprom); + /* Most cards have SPROM moved by additional offset 0x30 (48 dwords). + * According to brcm80211 this applies to cards with PCIe rev >= 6 + * 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); err = bcma_sprom_valid(sprom); if (err) |