aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorNick Kossifidis <mick@madwifi.org>2008-07-19 23:41:26 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-08-01 15:31:32 -0400
commitdf75dcddf99647d68f3b6b874effe5365c5024d9 (patch)
treea1624d7e79ea0bb19ca4906507e3b10cef4d07c5 /drivers/net
parente2a0ccebc4ffabc1c7234cfd324299b5a936e0f2 (diff)
ath5k: Reorder calibration calls during reset and update hw_set_power
* Update ath5k_hw_reset and add some more documentation about PHY calibration * Fix ath5k_hw_set_power to use AR5K_SLEEP_CTL_SLE_ALLOW for Network sleep * Preserve sleep duration field while setting AR5K_SLEEP_CTL and reduce delays & checks for register's status (got this from decompiling & dumps, it works for me but it needs testing) Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis <mickflemm@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath5k/hw.c82
1 files changed, 59 insertions, 23 deletions
diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c
index 3937e46e4735..ad1a5b422c8c 100644
--- a/drivers/net/wireless/ath5k/hw.c
+++ b/drivers/net/wireless/ath5k/hw.c
@@ -1092,34 +1092,57 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
1092 data = 0; 1092 data = 0;
1093 1093
1094 /* 1094 /*
1095 * Enable calibration and wait until completion 1095 * Start automatic gain calibration
1096 *
1097 * During AGC calibration RX path is re-routed to
1098 * a signal detector so we don't receive anything.
1099 *
1100 * This method is used to calibrate some static offsets
1101 * used together with on-the fly I/Q calibration (the
1102 * one performed via ath5k_hw_phy_calibrate), that doesn't
1103 * interrupt rx path.
1104 *
1105 * If we are in a noisy environment AGC calibration may time
1106 * out.
1096 */ 1107 */
1097 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, 1108 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
1098 AR5K_PHY_AGCCTL_CAL); 1109 AR5K_PHY_AGCCTL_CAL);
1099 1110
1111 /* At the same time start I/Q calibration for QAM constellation
1112 * -no need for CCK- */
1113 ah->ah_calibration = false;
1114 if (!(mode == AR5K_MODE_11B)) {
1115 ah->ah_calibration = true;
1116 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
1117 AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
1118 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
1119 AR5K_PHY_IQ_RUN);
1120 }
1121
1122 /* Wait for gain calibration to finish (we check for I/Q calibration
1123 * during ath5k_phy_calibrate) */
1100 if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, 1124 if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
1101 AR5K_PHY_AGCCTL_CAL, 0, false)) { 1125 AR5K_PHY_AGCCTL_CAL, 0, false)) {
1102 ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n", 1126 ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n",
1103 channel->center_freq); 1127 channel->center_freq);
1104 return -EAGAIN; 1128 return -EAGAIN;
1105 } 1129 }
1106 1130
1131 /*
1132 * Start noise floor calibration
1133 *
1134 * If we run NF calibration before AGC, it always times out.
1135 * Binary HAL starts NF and AGC calibration at the same time
1136 * and only waits for AGC to finish. I believe that's wrong because
1137 * during NF calibration, rx path is also routed to a detector, so if
1138 * it doesn't finish we won't have RX.
1139 *
1140 * XXX: Find an interval that's OK for all cards...
1141 */
1107 ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq); 1142 ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
1108 if (ret) 1143 if (ret)
1109 return ret; 1144 return ret;
1110 1145
1111 ah->ah_calibration = false;
1112
1113 /* A and G modes can use QAM modulation which requires enabling
1114 * I and Q calibration. Don't bother in B mode. */
1115 if (!(mode == AR5K_MODE_11B)) {
1116 ah->ah_calibration = true;
1117 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
1118 AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
1119 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
1120 AR5K_PHY_IQ_RUN);
1121 }
1122
1123 /* 1146 /*
1124 * Reset queues and start beacon timers at the end of the reset routine 1147 * Reset queues and start beacon timers at the end of the reset routine
1125 */ 1148 */
@@ -1247,7 +1270,7 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
1247 bool set_chip, u16 sleep_duration) 1270 bool set_chip, u16 sleep_duration)
1248{ 1271{
1249 unsigned int i; 1272 unsigned int i;
1250 u32 staid; 1273 u32 staid, data;
1251 1274
1252 ATH5K_TRACE(ah->ah_sc); 1275 ATH5K_TRACE(ah->ah_sc);
1253 staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1); 1276 staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
@@ -1259,7 +1282,8 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
1259 case AR5K_PM_NETWORK_SLEEP: 1282 case AR5K_PM_NETWORK_SLEEP:
1260 if (set_chip) 1283 if (set_chip)
1261 ath5k_hw_reg_write(ah, 1284 ath5k_hw_reg_write(ah,
1262 AR5K_SLEEP_CTL_SLE | sleep_duration, 1285 AR5K_SLEEP_CTL_SLE_ALLOW |
1286 sleep_duration,
1263 AR5K_SLEEP_CTL); 1287 AR5K_SLEEP_CTL);
1264 1288
1265 staid |= AR5K_STA_ID1_PWR_SV; 1289 staid |= AR5K_STA_ID1_PWR_SV;
@@ -1274,13 +1298,24 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
1274 break; 1298 break;
1275 1299
1276 case AR5K_PM_AWAKE: 1300 case AR5K_PM_AWAKE:
1301
1302 staid &= ~AR5K_STA_ID1_PWR_SV;
1303
1277 if (!set_chip) 1304 if (!set_chip)
1278 goto commit; 1305 goto commit;
1279 1306
1280 ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_WAKE, 1307 /* Preserve sleep duration */
1281 AR5K_SLEEP_CTL); 1308 data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL);
1309 if( data & 0xffc00000 ){
1310 data = 0;
1311 } else {
1312 data = data & 0xfffcffff;
1313 }
1314
1315 ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
1316 udelay(15);
1282 1317
1283 for (i = 5000; i > 0; i--) { 1318 for (i = 50; i > 0; i--) {
1284 /* Check if the chip did wake up */ 1319 /* Check if the chip did wake up */
1285 if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) & 1320 if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) &
1286 AR5K_PCICFG_SPWR_DN) == 0) 1321 AR5K_PCICFG_SPWR_DN) == 0)
@@ -1288,15 +1323,13 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
1288 1323
1289 /* Wait a bit and retry */ 1324 /* Wait a bit and retry */
1290 udelay(200); 1325 udelay(200);
1291 ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_WAKE, 1326 ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
1292 AR5K_SLEEP_CTL);
1293 } 1327 }
1294 1328
1295 /* Fail if the chip didn't wake up */ 1329 /* Fail if the chip didn't wake up */
1296 if (i <= 0) 1330 if (i <= 0)
1297 return -EIO; 1331 return -EIO;
1298 1332
1299 staid &= ~AR5K_STA_ID1_PWR_SV;
1300 break; 1333 break;
1301 1334
1302 default: 1335 default:
@@ -1325,6 +1358,7 @@ void ath5k_hw_start_rx(struct ath5k_hw *ah)
1325{ 1358{
1326 ATH5K_TRACE(ah->ah_sc); 1359 ATH5K_TRACE(ah->ah_sc);
1327 ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR); 1360 ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR);
1361 ath5k_hw_reg_read(ah, AR5K_CR);
1328} 1362}
1329 1363
1330/* 1364/*
@@ -1411,6 +1445,7 @@ int ath5k_hw_tx_start(struct ath5k_hw *ah, unsigned int queue)
1411 } 1445 }
1412 /* Start queue */ 1446 /* Start queue */
1413 ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); 1447 ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
1448 ath5k_hw_reg_read(ah, AR5K_CR);
1414 } else { 1449 } else {
1415 /* Return if queue is disabled */ 1450 /* Return if queue is disabled */
1416 if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue)) 1451 if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue))
@@ -1708,6 +1743,7 @@ enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask)
1708 * (they will be re-enabled afterwards). 1743 * (they will be re-enabled afterwards).
1709 */ 1744 */
1710 ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER); 1745 ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER);
1746 ath5k_hw_reg_read(ah, AR5K_IER);
1711 1747
1712 old_mask = ah->ah_imr; 1748 old_mask = ah->ah_imr;
1713 1749
@@ -3511,7 +3547,7 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
3511 if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE) 3547 if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
3512 AR5K_REG_ENABLE_BITS(ah, 3548 AR5K_REG_ENABLE_BITS(ah,
3513 AR5K_QUEUE_MISC(queue), 3549 AR5K_QUEUE_MISC(queue),
3514 AR5K_QCU_MISC_TXE); 3550 AR5K_QCU_MISC_RDY_VEOL_POLICY);
3515 } 3551 }
3516 3552
3517 if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE) 3553 if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)