diff options
author | Gábor Stefanik <netrolller.3d@gmail.com> | 2009-08-26 20:51:26 +0200 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-08-28 14:40:53 -0400 |
commit | 06e4da268c0e8f3b8408403d65e47d2885a78ff2 (patch) | |
tree | 971fffcefbe06c5bba590953a06ced39947f1198 | |
parent | 68ec53292c7f09056152efa9a6ee2591c794f08c (diff) | |
download | linux-06e4da268c0e8f3b8408403d65e47d2885a78ff2.tar.bz2 |
ssb: Implement PMU LDO control and use it in b43
Implement the "PMU LDO set voltage" and "PMU LDO PA ref enable"
functions, and use them during LP-PHY baseband init in b43.
Signed-off-by: Gábor Stefanik <netrolller.3d@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/b43/phy_lp.c | 10 | ||||
-rw-r--r-- | drivers/ssb/driver_chipcommon_pmu.c | 94 | ||||
-rw-r--r-- | include/linux/ssb/ssb_driver_chipcommon.h | 10 |
3 files changed, 107 insertions, 7 deletions
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 1a57d3390e92..80f245c04042 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -234,19 +234,15 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) if ((bus->sprom.boardflags_lo & B43_BFL_FEM) && ((b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) || (bus->sprom.boardflags_hi & B43_BFH_PAREF))) { - /* TODO: - * Set the LDO voltage to 0x0028 - FIXME: What is this? - * Call sb_pmu_set_ldo_voltage with 4 and the LDO voltage - * as arguments - * Call sb_pmu_paref_ldo_enable with argument TRUE - */ + ssb_pmu_set_ldo_voltage(&bus->chipco, LDO_PAREF, 0x28); + ssb_pmu_set_ldo_paref(&bus->chipco, true); if (dev->phy.rev == 0) { b43_phy_maskset(dev, B43_LPPHY_LP_RF_SIGNAL_LUT, 0xFFCF, 0x0010); } b43_lptab_write(dev, B43_LPTAB16(11, 7), 60); } else { - //TODO: Call ssb_pmu_paref_ldo_enable with argument FALSE + ssb_pmu_set_ldo_paref(&bus->chipco, false); b43_phy_maskset(dev, B43_LPPHY_LP_RF_SIGNAL_LUT, 0xFFCF, 0x0020); b43_lptab_write(dev, B43_LPTAB16(11, 7), 100); diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c index 4aaddeec55a2..64abd11f6fbb 100644 --- a/drivers/ssb/driver_chipcommon_pmu.c +++ b/drivers/ssb/driver_chipcommon_pmu.c @@ -28,6 +28,21 @@ static void ssb_chipco_pll_write(struct ssb_chipcommon *cc, chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, value); } +static void ssb_chipco_regctl_maskset(struct ssb_chipcommon *cc, + u32 offset, u32 mask, u32 set) +{ + u32 value; + + chipco_read32(cc, SSB_CHIPCO_REGCTL_ADDR); + chipco_write32(cc, SSB_CHIPCO_REGCTL_ADDR, offset); + chipco_read32(cc, SSB_CHIPCO_REGCTL_ADDR); + value = chipco_read32(cc, SSB_CHIPCO_REGCTL_DATA); + value &= mask; + value |= set; + chipco_write32(cc, SSB_CHIPCO_REGCTL_DATA, value); + chipco_read32(cc, SSB_CHIPCO_REGCTL_DATA); +} + struct pmu0_plltab_entry { u16 freq; /* Crystal frequency in kHz.*/ u8 xf; /* Crystal frequency value for PMU control */ @@ -506,3 +521,82 @@ void ssb_pmu_init(struct ssb_chipcommon *cc) ssb_pmu_pll_init(cc); ssb_pmu_resources_init(cc); } + +void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc, + enum ssb_pmu_ldo_volt_id id, u32 voltage) +{ + struct ssb_bus *bus = cc->dev->bus; + u32 addr, shift, mask; + + switch (bus->chip_id) { + case 0x4328: + case 0x5354: + switch (id) { + case LDO_VOLT1: + addr = 2; + shift = 25; + mask = 0xF; + break; + case LDO_VOLT2: + addr = 3; + shift = 1; + mask = 0xF; + break; + case LDO_VOLT3: + addr = 3; + shift = 9; + mask = 0xF; + break; + case LDO_PAREF: + addr = 3; + shift = 17; + mask = 0x3F; + break; + default: + SSB_WARN_ON(1); + return; + } + break; + case 0x4312: + if (SSB_WARN_ON(id != LDO_PAREF)) + return; + addr = 0; + shift = 21; + mask = 0x3F; + break; + default: + return; + } + + ssb_chipco_regctl_maskset(cc, addr, ~(mask << shift), + (voltage & mask) << shift); +} + +void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on) +{ + struct ssb_bus *bus = cc->dev->bus; + int ldo; + + switch (bus->chip_id) { + case 0x4312: + ldo = SSB_PMURES_4312_PA_REF_LDO; + break; + case 0x4328: + ldo = SSB_PMURES_4328_PA_REF_LDO; + break; + case 0x5354: + ldo = SSB_PMURES_5354_PA_REF_LDO; + break; + default: + return; + } + + if (on) + chipco_set32(cc, SSB_CHIPCO_PMU_MINRES_MSK, 1 << ldo); + else + chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, ~(1 << ldo)); + chipco_read32(cc, SSB_CHIPCO_PMU_MINRES_MSK); //SPEC FIXME found via mmiotrace - dummy read? +} + +EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage); +EXPORT_SYMBOL(ssb_pmu_set_ldo_paref); diff --git a/include/linux/ssb/ssb_driver_chipcommon.h b/include/linux/ssb/ssb_driver_chipcommon.h index d3b1d18922f2..4e27acf0a92f 100644 --- a/include/linux/ssb/ssb_driver_chipcommon.h +++ b/include/linux/ssb/ssb_driver_chipcommon.h @@ -629,5 +629,15 @@ extern int ssb_chipco_serial_init(struct ssb_chipcommon *cc, /* PMU support */ extern void ssb_pmu_init(struct ssb_chipcommon *cc); +enum ssb_pmu_ldo_volt_id { + LDO_PAREF = 0, + LDO_VOLT1, + LDO_VOLT2, + LDO_VOLT3, +}; + +void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc, + enum ssb_pmu_ldo_volt_id id, u32 voltage); +void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on); #endif /* LINUX_SSB_CHIPCO_H_ */ |