diff options
Diffstat (limited to 'package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_phy.c')
-rw-r--r-- | package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_phy.c | 575 |
1 files changed, 307 insertions, 268 deletions
diff --git a/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_phy.c b/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_phy.c index 39ed81f850..406e0034d9 100644 --- a/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_phy.c +++ b/package/bcm43xx-mac80211/src/bcm43xx/bcm43xx_phy.c @@ -285,12 +285,195 @@ void bcm43xx_phy_write(struct bcm43xx_wldev *dev, u16 offset, u16 val) bcm43xx_write16(dev, BCM43xx_MMIO_PHY_DATA, val); } +static void bcm43xx_radio_set_txpower_a(struct bcm43xx_wldev *dev, u16 txpower); + +/* Adjust the transmission power output (G-PHY) */ +void bcm43xx_set_txpower_g(struct bcm43xx_wldev *dev, + const struct bcm43xx_bbatt *bbatt, + const struct bcm43xx_rfatt *rfatt, + u8 tx_control) +{ + struct bcm43xx_phy *phy = &dev->phy; + struct bcm43xx_txpower_lo_control *lo = phy->lo_control; + u16 bb, rf; + u16 tx_bias, tx_magn; + + bb = bbatt->att; + rf = rfatt->att; + tx_bias = lo->tx_bias; + tx_magn = lo->tx_magn; + if (unlikely(tx_bias == 0xFF)) + tx_bias = 0; + + /* Save the values for later */ + phy->tx_control = tx_control; + memcpy(&phy->rfatt, rfatt, sizeof(*rfatt)); + memcpy(&phy->bbatt, bbatt, sizeof(*bbatt)); + + if (bcm43xx_debug(dev, BCM43xx_DBG_XMITPOWER)) { + dprintk(KERN_DEBUG PFX "Tuning TX-power to bbatt(%u), " + "rfatt(%u), tx_control(0x%02X), " + "tx_bias(0x%02X), tx_magn(0x%02X)\n", + bb, rf, tx_control, tx_bias, tx_magn); + } + + bcm43xx_phy_set_baseband_attenuation(dev, bb); + bcm43xx_shm_write16(dev, BCM43xx_SHM_SHARED, BCM43xx_SHM_SH_RFATT, rf); + if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) { + bcm43xx_radio_write16(dev, 0x43, + (rf & 0x000F) | (tx_control & 0x0070)); + } else { + bcm43xx_radio_write16(dev, 0x43, + (bcm43xx_radio_read16(dev, 0x43) + & 0xFFF0) | (rf & 0x000F)); + bcm43xx_radio_write16(dev, 0x52, + (bcm43xx_radio_read16(dev, 0x52) + & ~0x0070) | (tx_control & 0x0070)); + } + if (has_tx_magnification(phy)) { + bcm43xx_radio_write16(dev, 0x52, tx_magn | tx_bias); + } else { + bcm43xx_radio_write16(dev, 0x52, + (bcm43xx_radio_read16(dev, 0x52) + & 0xFFF0) | (tx_bias & 0x000F)); + } + if (phy->type == BCM43xx_PHYTYPE_G) + bcm43xx_lo_g_adjust(dev); +} + +static void default_baseband_attenuation(struct bcm43xx_wldev *dev, + struct bcm43xx_bbatt *bb) +{ + struct bcm43xx_phy *phy = &dev->phy; + + if (phy->radio_ver == 0x2050 && phy->radio_rev < 6) + bb->att = 0; + else + bb->att = 2; +} + +static void default_radio_attenuation(struct bcm43xx_wldev *dev, + struct bcm43xx_rfatt *rf) +{ + struct ssb_bus *bus = dev->dev->bus; + struct bcm43xx_phy *phy = &dev->phy; + + rf->with_padmix = 0; + + if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM && + bus->boardinfo.type == SSB_BOARD_BCM4309G) { + if (bus->boardinfo.rev < 0x43) { + rf->att = 2; + return; + } else if (bus->boardinfo.rev < 0x51) { + rf->att = 3; + return; + } + } + + if (phy->type == BCM43xx_PHYTYPE_A) { + rf->att = 0x60; + return; + } + + switch (phy->radio_ver) { + case 0x2053: + switch (phy->radio_rev) { + case 1: + rf->att = 6; + return; + } + break; + case 0x2050: + switch (phy->radio_rev) { + case 0: + rf->att = 5; + return; + case 1: + if (phy->type == BCM43xx_PHYTYPE_G) { + if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM && + bus->boardinfo.type == SSB_BOARD_BCM4309G && + bus->boardinfo.rev >= 30) + rf->att = 3; + else if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM && + bus->boardinfo.type == SSB_BOARD_BU4306) + rf->att = 3; + else + rf->att = 1; + } else { + if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM && + bus->boardinfo.type == SSB_BOARD_BCM4309G && + bus->boardinfo.rev >= 30) + rf->att = 7; + else + rf->att = 6; + } + return; + case 2: + if (phy->type == BCM43xx_PHYTYPE_G) { + if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM && + bus->boardinfo.type == SSB_BOARD_BCM4309G && + bus->boardinfo.rev >= 30) + rf->att = 3; + else if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM && + bus->boardinfo.type == SSB_BOARD_BU4306) + rf->att = 5; + else if (bus->chip_id == 0x4320) + rf->att = 4; + else + rf->att = 3; + } else + rf->att = 6; + return; + case 3: + rf->att = 5; + return; + case 4: + case 5: + rf->att = 1; + return; + case 6: + case 7: + rf->att = 5; + return; + case 8: + rf->att = 0xA; + rf->with_padmix = 1; + return; + case 9: + default: + rf->att = 5; + return; + } + } + rf->att = 5; +} + +static u16 default_tx_control(struct bcm43xx_wldev *dev) +{ + struct bcm43xx_phy *phy = &dev->phy; + + if (phy->radio_ver != 0x2050) + return 0; + if (phy->radio_rev == 1) + return BCM43xx_TXCTL_PA2DB | BCM43xx_TXCTL_TXMIX; + if (phy->radio_rev < 6) + return BCM43xx_TXCTL_PA2DB; + if (phy->radio_rev == 8) + return BCM43xx_TXCTL_TXMIX; + return 0; +} + /* This func is called "PHY calibrate" in the specs... */ void bcm43xx_phy_early_init(struct bcm43xx_wldev *dev) { struct bcm43xx_phy *phy = &dev->phy; struct bcm43xx_txpower_lo_control *lo = phy->lo_control; + default_baseband_attenuation(dev, &phy->bbatt); + default_radio_attenuation(dev, &phy->rfatt); + phy->tx_control = (default_tx_control(dev) << 4); + bcm43xx_read32(dev, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */ if (phy->type == BCM43xx_PHYTYPE_B || phy->type == BCM43xx_PHYTYPE_G) { @@ -510,9 +693,12 @@ static void bcm43xx_phy_init_pctl(struct bcm43xx_wldev *dev) { struct ssb_bus *bus = dev->dev->bus; struct bcm43xx_phy *phy = &dev->phy; + struct bcm43xx_rfatt old_rfatt; + struct bcm43xx_bbatt old_bbatt; + u8 old_tx_control = 0; - if ((bus->board_vendor == SSB_BOARDVENDOR_BCM) && - (bus->board_type == SSB_BOARD_BU4306)) + if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) && + (bus->boardinfo.type == SSB_BOARD_BU4306)) return; bcm43xx_phy_write(dev, 0x0028, 0x8018); @@ -531,10 +717,22 @@ static void bcm43xx_phy_init_pctl(struct bcm43xx_wldev *dev) (bcm43xx_radio_read16(dev, 0x0076) & 0x00F7) | 0x0084); } else { - if (phy->radio_rev == 8) - bcm43xx_radio_set_txpower_bg(dev, 0xB, 0x1F, 0); - else - bcm43xx_radio_set_txpower_bg(dev, 0xB, 9, 0); + struct bcm43xx_rfatt rfatt; + struct bcm43xx_bbatt bbatt; + + memcpy(&old_rfatt, &phy->rfatt, sizeof(old_rfatt)); + memcpy(&old_bbatt, &phy->bbatt, sizeof(old_bbatt)); + old_tx_control = phy->tx_control; + + bbatt.att = 11; + if (phy->radio_rev == 8) { + rfatt.att = 15; + rfatt.with_padmix = 1; + } else { + rfatt.att = 9; + rfatt.with_padmix = 0; + } + bcm43xx_set_txpower_g(dev, &bbatt, &rfatt, 0); } bcm43xx_dummy_transmission(dev); phy->cur_idle_tssi = bcm43xx_phy_read(dev, BCM43xx_PHY_ITSSI); @@ -547,13 +745,14 @@ static void bcm43xx_phy_init_pctl(struct bcm43xx_wldev *dev) phy->cur_idle_tssi = 0; } } - if (phy->radio_ver == 0x2050 && phy->analog == 0) { bcm43xx_radio_write16(dev, 0x0076, bcm43xx_radio_read16(dev, 0x0076) & 0xFF7B); - } else - bcm43xx_radio_set_txpower_bg(dev, -1, -1, -1); + } else { + bcm43xx_set_txpower_g(dev, &old_bbatt, + &old_rfatt, old_tx_control); + } } bcm43xx_hardware_pctl_init(dev); bcm43xx_shm_clear_tssi(dev); @@ -758,23 +957,19 @@ static void bcm43xx_phy_setupg(struct bcm43xx_wldev *dev) if (phy->rev == 1) { for (i = 0; i < BCM43xx_TAB_RETARD_SIZE; i++) bcm43xx_ofdmtab_write32(dev, 0x2400, i, bcm43xx_tab_retard[i]); - for (i = 0; i < 4; i++) { - bcm43xx_ofdmtab_write16(dev, 0x5404, i, 0x0020); - bcm43xx_ofdmtab_write16(dev, 0x5408, i, 0x0020); - bcm43xx_ofdmtab_write16(dev, 0x540C, i, 0x0020); - bcm43xx_ofdmtab_write16(dev, 0x5410, i, 0x0020); - } + for (i = 4; i < 20; i++) + bcm43xx_ofdmtab_write16(dev, 0x5400, i, 0x0020); bcm43xx_phy_agcsetup(dev); - if ((bus->board_vendor == SSB_BOARDVENDOR_BCM) && - (bus->board_type == SSB_BOARD_BU4306) && - (bus->board_rev == 0x17)) + if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) && + (bus->boardinfo.type == SSB_BOARD_BU4306) && + (bus->boardinfo.rev == 0x17)) return; bcm43xx_ofdmtab_write16(dev, 0x5001, 0, 0x0002); bcm43xx_ofdmtab_write16(dev, 0x5002, 0, 0x0001); } else { - for (i = 0; i <= 0x2F; i++) + for (i = 0; i < 0x20; i++) bcm43xx_ofdmtab_write16(dev, 0x1000, i, 0x0820); bcm43xx_phy_agcsetup(dev); bcm43xx_phy_read(dev, 0x0400); /* dummy read */ @@ -782,9 +977,9 @@ static void bcm43xx_phy_setupg(struct bcm43xx_wldev *dev) bcm43xx_ofdmtab_write16(dev, 0x3C02, 0, 0x000F); bcm43xx_ofdmtab_write16(dev, 0x3C03, 0, 0x0014); - if ((bus->board_vendor == SSB_BOARDVENDOR_BCM) && - (bus->board_type == SSB_BOARD_BU4306) && - (bus->board_rev == 0x17)) + if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) && + (bus->boardinfo.type == SSB_BOARD_BU4306) && + (bus->boardinfo.rev == 0x17)) return; bcm43xx_ofdmtab_write16(dev, 0x0401, 0, 0x0002); @@ -955,6 +1150,8 @@ static void bcm43xx_phy_inita(struct bcm43xx_wldev *dev) struct bcm43xx_phy *phy = &dev->phy; u16 tval; + might_sleep(); + if (phy->type == BCM43xx_PHYTYPE_A) { bcm43xx_phy_setupa(dev); } else { @@ -974,9 +1171,9 @@ static void bcm43xx_phy_inita(struct bcm43xx_wldev *dev) bcm43xx_phy_read(dev, BCM43xx_PHY_A_CRS) | (1 << 14)); bcm43xx_radio_init2060(dev); - if ((bus->board_vendor == SSB_BOARDVENDOR_BCM) && - ((bus->board_type == SSB_BOARD_BU4306) || - (bus->board_type == SSB_BOARD_BU4309))) { + if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) && + ((bus->boardinfo.type == SSB_BOARD_BU4306) || + (bus->boardinfo.type == SSB_BOARD_BU4309))) { if (phy->lofcal == 0xFFFF) { TODO();//TODO: LOF Cal bcm43xx_radio_set_tx_iq(dev); @@ -1056,7 +1253,7 @@ static void bcm43xx_phy_initb2(struct bcm43xx_wldev *dev) bcm43xx_phy_write(dev, 0x002A, 0x88A3); if (phy->radio_ver != 0x2050) bcm43xx_phy_write(dev, 0x002A, 0x88C2); - bcm43xx_radio_set_txpower_bg(dev, -1, -1, -1); + bcm43xx_set_txpower_g(dev, &phy->bbatt, &phy->rfatt, phy->tx_control); bcm43xx_phy_init_pctl(dev); } @@ -1110,7 +1307,7 @@ static void bcm43xx_phy_initb4(struct bcm43xx_wldev *dev) bcm43xx_phy_write(dev, 0x002A, 0x88A3); if (phy->radio_ver == 0x2050) bcm43xx_phy_write(dev, 0x002A, 0x88C2); - bcm43xx_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF); + bcm43xx_set_txpower_g(dev, &phy->bbatt, &phy->rfatt, phy->tx_control); if (dev->dev->bus->sprom.r1.boardflags_lo & BCM43xx_BFL_RSSI) { bcm43xx_calc_nrssi_slope(dev); bcm43xx_calc_nrssi_threshold(dev); @@ -1130,8 +1327,8 @@ static void bcm43xx_phy_initb5(struct bcm43xx_wldev *dev) bcm43xx_radio_read16(dev, 0x007A) | 0x0050); } - if ((bus->board_vendor != SSB_BOARDVENDOR_BCM) && - (bus->board_type != SSB_BOARD_BU4306)) { + if ((bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM) && + (bus->boardinfo.type != SSB_BOARD_BU4306)) { value = 0x2120; for (offset = 0x00A8 ; offset < 0x00C7; offset++) { bcm43xx_phy_write(dev, offset, value); @@ -1217,7 +1414,7 @@ static void bcm43xx_phy_initb5(struct bcm43xx_wldev *dev) bcm43xx_phy_write(dev, 0x0032, 0x00CA); bcm43xx_phy_write(dev, 0x002A, 0x88A3); - bcm43xx_radio_set_txpower_bg(dev, -1, -1, -1); + bcm43xx_set_txpower_g(dev, &phy->bbatt, &phy->rfatt, phy->tx_control); if (phy->radio_ver == 0x2050) bcm43xx_radio_write16(dev, 0x005D, 0x000D); @@ -1328,7 +1525,7 @@ static void bcm43xx_phy_initb6(struct bcm43xx_wldev *dev) else bcm43xx_phy_write(dev, 0x2A, 0x8AC0); bcm43xx_phy_write(dev, 0x0038, 0x0668); - bcm43xx_radio_set_txpower_bg(dev, -1, -1, -1); + bcm43xx_set_txpower_g(dev, &phy->bbatt, &phy->rfatt, phy->tx_control); if (phy->radio_rev <= 5) { bcm43xx_phy_write(dev, 0x5D, (bcm43xx_phy_read(dev, 0x5D) @@ -1391,7 +1588,7 @@ static void bcm43xx_calc_loopback_gain(struct bcm43xx_wldev *dev) backup_phy[13] = bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x2B)); backup_phy[14] = bcm43xx_phy_read(dev, BCM43xx_PHY_PGACTL); backup_phy[15] = bcm43xx_phy_read(dev, BCM43xx_PHY_LO_LEAKAGE); - backup_bband = phy->bbatt; + backup_bband = phy->bbatt.att; backup_radio[0] = bcm43xx_radio_read16(dev, 0x52); backup_radio[1] = bcm43xx_radio_read16(dev, 0x43); backup_radio[2] = bcm43xx_radio_read16(dev, 0x7A); @@ -1689,23 +1886,20 @@ void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_wldev *dev, u16 baseband_attenuation) { struct bcm43xx_phy *phy = &dev->phy; - u16 value; if (phy->analog == 0) { - value = (bcm43xx_read16(dev, 0x03E6) & 0xFFF0); - value |= (baseband_attenuation & 0x000F); - bcm43xx_write16(dev, 0x03E6, value); - return; - } - - if (phy->analog > 1) { - value = bcm43xx_phy_read(dev, 0x0060) & ~0x003C; - value |= (baseband_attenuation << 2) & 0x003C; + bcm43xx_write16(dev, BCM43xx_MMIO_PHY0, + (bcm43xx_read16(dev, BCM43xx_MMIO_PHY0) + & 0xFFF0) | baseband_attenuation); + } else if (phy->analog == 1) { + bcm43xx_phy_write(dev, BCM43xx_PHY_DACCTL, + (bcm43xx_phy_read(dev, BCM43xx_PHY_DACCTL) + & 0xFFC3) | (baseband_attenuation << 2)); } else { - value = bcm43xx_phy_read(dev, 0x0060) & ~0x0078; - value |= (baseband_attenuation << 3) & 0x0078; + bcm43xx_phy_write(dev, BCM43xx_PHY_DACCTL, + (bcm43xx_phy_read(dev, BCM43xx_PHY_DACCTL) + & 0xFF87) | (baseband_attenuation << 3)); } - bcm43xx_phy_write(dev, 0x0060, value); } /* http://bcm-specs.sipsolutions.net/EstimatePowerOut @@ -1738,20 +1932,21 @@ static s8 bcm43xx_phy_estimate_power_out(struct bcm43xx_wldev *dev, s8 tssi) return dbm; } -static void put_attenuation_into_ranges(struct bcm43xx_wldev *dev, - int *_rfatt, int *_bbatt) +void bcm43xx_put_attenuation_into_ranges(struct bcm43xx_wldev *dev, + int *_bbatt, int *_rfatt) { int rfatt = *_rfatt; int bbatt = *_bbatt; + struct bcm43xx_txpower_lo_control *lo = dev->phy.lo_control; /* Get baseband and radio attenuation values into their permitted ranges. * Radio attenuation affects power level 4 times as much as baseband. */ /* Range constants */ - const int rf_min = 0; - const int rf_max = 9; - const int bb_min = 0; - const int bb_max = 11; + const int rf_min = lo->rfatt_list.min_val; + const int rf_max = lo->rfatt_list.max_val; + const int bb_min = lo->bbatt_list.min_val; + const int bb_max = lo->bbatt_list.max_val; while (1) { if (rfatt > rf_max && @@ -1802,9 +1997,13 @@ void bcm43xx_phy_xmitpower(struct bcm43xx_wldev *dev) if (phy->cur_idle_tssi == 0) return; - if ((bus->board_vendor == SSB_BOARDVENDOR_BCM) && - (bus->board_type == SSB_BOARD_BU4306)) + if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) && + (bus->boardinfo.type == SSB_BOARD_BU4306)) return; +#ifdef CONFIG_BCM43XX_MAC80211_DEBUG + if (phy->manual_txpower_control) + return; +#endif switch (phy->type) { case BCM43xx_PHYTYPE_A: { @@ -1816,13 +2015,13 @@ void bcm43xx_phy_xmitpower(struct bcm43xx_wldev *dev) case BCM43xx_PHYTYPE_B: case BCM43xx_PHYTYPE_G: { u16 tmp; - u16 txpower; s8 v0, v1, v2, v3; s8 average; - u8 max_pwr; - s16 desired_pwr, estimated_pwr, pwr_adjust; - int radio_att_delta, baseband_att_delta; - int radio_attenuation, baseband_attenuation; + int max_pwr; + int desired_pwr, estimated_pwr, pwr_adjust; + int rfatt_delta, bbatt_delta; + int rfatt, bbatt; + u8 tx_control; unsigned long phylock_flags; tmp = bcm43xx_shm_read16(dev, BCM43xx_SHM_SHARED, 0x0058); @@ -1858,10 +2057,14 @@ void bcm43xx_phy_xmitpower(struct bcm43xx_wldev *dev) estimated_pwr = bcm43xx_phy_estimate_power_out(dev, average); max_pwr = dev->dev->bus->sprom.r1.maxpwr_bg; - if ((dev->dev->bus->sprom.r1.boardflags_lo & BCM43xx_BFL_PACTRL) && (phy->type == BCM43xx_PHYTYPE_G)) max_pwr -= 0x3; + if (unlikely(max_pwr <= 0)) { + printk(KERN_ERR PFX "Invalid max-TX-power value in SPROM.\n"); + max_pwr = 60; /* fake it */ + dev->dev->bus->sprom.r1.maxpwr_bg = max_pwr; + } /*TODO: max_pwr = min(REG - dev->dev->bus->sprom.antennagain_bgphy - 0x6, max_pwr) @@ -1871,53 +2074,56 @@ void bcm43xx_phy_xmitpower(struct bcm43xx_wldev *dev) desired_pwr = phy->power_level; /* Convert the desired_pwr to Q5.2 and limit it. */ desired_pwr = limit_value((desired_pwr << 2), 0, max_pwr); + if (bcm43xx_debug(dev, BCM43xx_DBG_XMITPOWER)) { + dprintk(KERN_DEBUG PFX + "Current TX power output: " Q52_FMT " dBm, " + "Desired TX power output: " Q52_FMT " dBm\n", + Q52_ARG(estimated_pwr), Q52_ARG(desired_pwr)); + } pwr_adjust = desired_pwr - estimated_pwr; - radio_att_delta = -((pwr_adjust + 7) >> 3); - baseband_att_delta = (-(pwr_adjust >> 1)) - (4 * radio_att_delta); - if ((radio_att_delta == 0) && (baseband_att_delta == 0)) { + rfatt_delta = -((pwr_adjust + 7) >> 3); + bbatt_delta = (-(pwr_adjust >> 1)) - (4 * rfatt_delta); + if ((rfatt_delta == 0) && (bbatt_delta == 0)) { bcm43xx_lo_g_ctl_mark_cur_used(dev); return; } /* Calculate the new attenuation values. */ - baseband_attenuation = phy->bbatt; - baseband_attenuation += baseband_att_delta; - radio_attenuation = phy->rfatt; - radio_attenuation += radio_att_delta; - put_attenuation_into_ranges(dev, &radio_attenuation, - &baseband_attenuation); - - txpower = phy->txctl1; + bbatt = phy->bbatt.att; + bbatt += bbatt_delta; + rfatt = phy->rfatt.att; + rfatt += rfatt_delta; + + bcm43xx_put_attenuation_into_ranges(dev, &bbatt, &rfatt); + tx_control = phy->tx_control; if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 2)) { - if (radio_attenuation <= 1) { - if (txpower == 0) { - txpower = 3; - radio_attenuation += 2; - baseband_attenuation += 2; + if (rfatt <= 1) { + if (tx_control == 0) { + tx_control = BCM43xx_TXCTL_PA2DB | BCM43xx_TXCTL_TXMIX; + rfatt += 2; + bbatt += 2; } else if (dev->dev->bus->sprom.r1.boardflags_lo & BCM43xx_BFL_PACTRL) { - baseband_attenuation += 4 * (radio_attenuation - 2); - radio_attenuation = 2; + bbatt += 4 * (rfatt - 2); + rfatt = 2; } - } else if (radio_attenuation > 4 && txpower != 0) { - txpower = 0; - if (baseband_attenuation < 3) { - radio_attenuation -= 3; - baseband_attenuation += 2; + } else if (rfatt > 4 && tx_control) { + tx_control = 0; + if (bbatt < 3) { + rfatt -= 3; + bbatt += 2; } else { - radio_attenuation -= 2; - baseband_attenuation -= 2; + rfatt -= 2; + bbatt -= 2; } } } - phy->txctl1 = txpower; - baseband_attenuation = limit_value(baseband_attenuation, 0, 11); - radio_attenuation = limit_value(radio_attenuation, 0, 9); + phy->tx_control = tx_control; + bcm43xx_put_attenuation_into_ranges(dev, &bbatt, &rfatt); bcm43xx_phy_lock(dev, phylock_flags); bcm43xx_radio_lock(dev); - bcm43xx_radio_set_txpower_bg(dev, baseband_attenuation, - radio_attenuation, txpower); + bcm43xx_set_txpower_g(dev, &phy->bbatt, &phy->rfatt, phy->tx_control); bcm43xx_lo_g_ctl_mark_cur_used(dev); bcm43xx_radio_unlock(dev); bcm43xx_phy_unlock(dev, phylock_flags); @@ -2324,6 +2530,8 @@ static void bcm43xx_synth_pu_workaround(struct bcm43xx_wldev *dev, u8 channel) { struct bcm43xx_phy *phy = &dev->phy; + might_sleep(); + if (phy->radio_ver != 0x2050 || phy->radio_rev >= 6) { /* We do not need the workaround. */ return; @@ -2336,7 +2544,7 @@ static void bcm43xx_synth_pu_workaround(struct bcm43xx_wldev *dev, u8 channel) bcm43xx_write16(dev, BCM43xx_MMIO_CHANNEL, channel2freq_bg(1)); } - udelay(100); + msleep(1); bcm43xx_write16(dev, BCM43xx_MMIO_CHANNEL, channel2freq_bg(channel)); } @@ -3843,10 +4051,10 @@ void bcm43xx_radio_init2060(struct bcm43xx_wldev *dev) bcm43xx_radio_write16(dev, 0x0081, bcm43xx_radio_read16(dev, 0x0081) & ~0x0010); bcm43xx_radio_write16(dev, 0x0081, bcm43xx_radio_read16(dev, 0x0081) & ~0x0020); bcm43xx_radio_write16(dev, 0x0081, bcm43xx_radio_read16(dev, 0x0081) & ~0x0020); - udelay(400); + msleep(1); /* delay 400usec */ bcm43xx_radio_write16(dev, 0x0081, (bcm43xx_radio_read16(dev, 0x0081) & ~0x0020) | 0x0010); - udelay(400); + msleep(1); /* delay 400usec */ bcm43xx_radio_write16(dev, 0x0005, (bcm43xx_radio_read16(dev, 0x0005) & ~0x0008) | 0x0008); bcm43xx_radio_write16(dev, 0x0085, bcm43xx_radio_read16(dev, 0x0085) & ~0x0010); @@ -3860,7 +4068,8 @@ void bcm43xx_radio_init2060(struct bcm43xx_wldev *dev) err = bcm43xx_radio_selectchannel(dev, BCM43xx_DEFAULT_CHANNEL_A, 0); assert(err == 0); - udelay(1000); + + msleep(1); } static inline @@ -3995,9 +4204,8 @@ int bcm43xx_radio_selectchannel(struct bcm43xx_wldev *dev, } phy->channel = channel; - //XXX: Using the longer of 2 timeouts (8000 vs 2000 usecs). Specs states - // that 2000 usecs might suffice. - udelay(8000); + /* Wait for the radio to tune to the channel and stabilize. */ + msleep(8); return 0; } @@ -4069,7 +4277,7 @@ static u16 bcm43xx_get_txgain_dac(u16 txpower) return ret; } -void bcm43xx_radio_set_txpower_a(struct bcm43xx_wldev *dev, u16 txpower) +static void bcm43xx_radio_set_txpower_a(struct bcm43xx_wldev *dev, u16 txpower) { struct bcm43xx_phy *phy = &dev->phy; u16 pamp, base, dac, t; @@ -4100,182 +4308,13 @@ void bcm43xx_radio_set_txpower_a(struct bcm43xx_wldev *dev, u16 txpower) //TODO: FuncPlaceholder (Adjust BB loft cancel) } -void bcm43xx_radio_set_txpower_bg(struct bcm43xx_wldev *dev, - s16 baseband_attenuation, - s16 radio_attenuation, - s16 _tx_magn) -{ - struct bcm43xx_phy *phy = &dev->phy; - u8 tx_bias = phy->lo_control->tx_bias; - u8 tx_magn; - - if (baseband_attenuation < 0) - baseband_attenuation = phy->bbatt; - if (radio_attenuation < 0) - radio_attenuation = phy->rfatt; - if (_tx_magn < 0) - _tx_magn = phy->lo_control->tx_magn; - tx_magn = _tx_magn; - phy->bbatt = baseband_attenuation; - phy->rfatt = radio_attenuation; - - /* Set Baseband Attenuation on device. */ - bcm43xx_phy_set_baseband_attenuation(dev, baseband_attenuation); - - /* Set Radio Attenuation on device. */ - bcm43xx_shm_write16(dev, BCM43xx_SHM_SHARED, - 0x0064, radio_attenuation); - if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) { - bcm43xx_phy_write(dev, 0x0043, radio_attenuation); - } else { - bcm43xx_radio_write16(dev, 0x0043, - (bcm43xx_radio_read16(dev, 0x0043) - & 0xFFF0) | radio_attenuation); - } - - if (phy->radio_ver == 0x2050) {//FIXME: It seems like tx_magn and tx_bias are swapped in this func. - if (phy->radio_rev < 6) { - bcm43xx_radio_write16(dev, 0x0043, - (bcm43xx_radio_read16(dev, 0x0043) - & 0xFF8F) | tx_magn); - } else if (phy->radio_rev != 8) { - bcm43xx_radio_write16(dev, 0x0052, - (bcm43xx_radio_read16(dev, 0x0052) - & 0xFF8F) | tx_magn); - } else { - bcm43xx_radio_write16(dev, 0x52, - (bcm43xx_radio_read16(dev, 0x52) & 0xFF00) | - tx_magn | tx_bias); - } - } - if (phy->radio_rev != 8) { - bcm43xx_radio_write16(dev, 0x0052, - (bcm43xx_radio_read16(dev, 0x0052) - & 0xFFF0) | tx_bias); - } - if (phy->type == BCM43xx_PHYTYPE_G) - bcm43xx_lo_g_adjust(dev); -} - -u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_wldev *dev) -{ - struct bcm43xx_phy *phy = &dev->phy; - - if (phy->radio_ver == 0x2050 && phy->radio_rev < 6) - return 0; - return 2; -} - -u16 bcm43xx_default_radio_attenuation(struct bcm43xx_wldev *dev) -{ - struct ssb_bus *bus = dev->dev->bus; - struct bcm43xx_phy *phy = &dev->phy; - u16 att = 0xFFFF; - - if (phy->type == BCM43xx_PHYTYPE_A) - return 0x60; - - switch (phy->radio_ver) { - case 0x2053: - switch (phy->radio_rev) { - case 1: - att = 6; - break; - } - break; - case 0x2050: - switch (phy->radio_rev) { - case 0: - att = 5; - break; - case 1: - if (phy->type == BCM43xx_PHYTYPE_G) { - if (bus->board_vendor == SSB_BOARDVENDOR_BCM && - bus->board_type == SSB_BOARD_BCM4309G && - bus->board_rev >= 30) - att = 3; - else if (bus->board_vendor == SSB_BOARDVENDOR_BCM && - bus->board_type == SSB_BOARD_BU4306) - att = 3; - else - att = 1; - } else { - if (bus->board_vendor == SSB_BOARDVENDOR_BCM && - bus->board_type == SSB_BOARD_BCM4309G && - bus->board_rev >= 30) - att = 7; - else - att = 6; - } - break; - case 2: - if (phy->type == BCM43xx_PHYTYPE_G) { - if (bus->board_vendor == SSB_BOARDVENDOR_BCM && - bus->board_type == SSB_BOARD_BCM4309G && - bus->board_rev >= 30) - att = 3; - else if (bus->board_vendor == SSB_BOARDVENDOR_BCM && - bus->board_type == SSB_BOARD_BU4306) - att = 5; - else if (bus->chip_id == 0x4320) - att = 4; - else - att = 3; - } else - att = 6; - break; - case 3: - att = 5; - break; - case 4: - case 5: - att = 1; - break; - case 6: - case 7: - att = 5; - break; - case 8: - att = 0x1A; - break; - case 9: - default: - att = 5; - } - } - if (bus->board_vendor == SSB_BOARDVENDOR_BCM && - bus->board_type == SSB_BOARD_BCM4309G) { - if (bus->board_rev < 0x43) - att = 2; - else if (bus->board_rev < 0x51) - att = 3; - } - if (att == 0xFFFF) - att = 5; - - return att; -} - -u16 bcm43xx_default_txctl1(struct bcm43xx_wldev *dev) -{ - struct bcm43xx_phy *phy = &dev->phy; - - if (phy->radio_ver != 0x2050) - return 0; - if (phy->radio_rev == 1) - return 3; - if (phy->radio_rev < 6) - return 2; - if (phy->radio_rev == 8) - return 1; - return 0; -} - void bcm43xx_radio_turn_on(struct bcm43xx_wldev *dev) { struct bcm43xx_phy *phy = &dev->phy; int err; + might_sleep(); + if (phy->radio_on) return; |