aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorNick Kossifidis <mick@madwifi-project.org>2009-04-30 15:55:50 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-05-06 15:14:56 -0400
commit57e6c56dbb52d680f61dd629759fe2974840ed93 (patch)
tree66a9671168f7eb67aa42fa1ce8def3ded45e21ae /drivers
parent2bed03ebf62f9d013a455209bf30d7e086120443 (diff)
ath5k: Add Spur filter support on newer chips
* Add spur filter support for RF5413 and later chips Signed-off-by: Nick Kossifidis <mickflemm@gmail.com> Signed-off-by: Bob Copeland <me@bobcopeland.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ath5k/ath5k.h5
-rw-r--r--drivers/net/wireless/ath/ath5k/phy.c255
-rw-r--r--drivers/net/wireless/ath/ath5k/reset.c35
3 files changed, 270 insertions, 25 deletions
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 33da290e4bb5..813718210338 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1278,6 +1278,11 @@ extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *chann
1278/* PHY calibration */ 1278/* PHY calibration */
1279extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel); 1279extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel);
1280extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq); 1280extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq);
1281/* Spur mitigation */
1282bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
1283 struct ieee80211_channel *channel);
1284void ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
1285 struct ieee80211_channel *channel);
1281/* Misc PHY functions */ 1286/* Misc PHY functions */
1282extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); 1287extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan);
1283extern int ath5k_hw_phy_disable(struct ath5k_hw *ah); 1288extern int ath5k_hw_phy_disable(struct ath5k_hw *ah);
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index fd93c4e20214..6737ba0a4de3 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -1353,6 +1353,257 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
1353 return ret; 1353 return ret;
1354} 1354}
1355 1355
1356/***************************\
1357* Spur mitigation functions *
1358\***************************/
1359
1360bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
1361 struct ieee80211_channel *channel)
1362{
1363 u8 refclk_freq;
1364
1365 if ((ah->ah_radio == AR5K_RF5112) ||
1366 (ah->ah_radio == AR5K_RF5413) ||
1367 (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
1368 refclk_freq = 40;
1369 else
1370 refclk_freq = 32;
1371
1372 if ((channel->center_freq % refclk_freq != 0) &&
1373 ((channel->center_freq % refclk_freq < 10) ||
1374 (channel->center_freq % refclk_freq > 22)))
1375 return true;
1376 else
1377 return false;
1378}
1379
1380void
1381ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
1382 struct ieee80211_channel *channel)
1383{
1384 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
1385 u32 mag_mask[4] = {0, 0, 0, 0};
1386 u32 pilot_mask[2] = {0, 0};
1387 /* Note: fbin values are scaled up by 2 */
1388 u16 spur_chan_fbin, chan_fbin, symbol_width, spur_detection_window;
1389 s32 spur_delta_phase, spur_freq_sigma_delta;
1390 s32 spur_offset, num_symbols_x16;
1391 u8 num_symbol_offsets, i, freq_band;
1392
1393 /* Convert current frequency to fbin value (the same way channels
1394 * are stored on EEPROM, check out ath5k_eeprom_bin2freq) and scale
1395 * up by 2 so we can compare it later */
1396 if (channel->hw_value & CHANNEL_2GHZ) {
1397 chan_fbin = (channel->center_freq - 2300) * 10;
1398 freq_band = AR5K_EEPROM_BAND_2GHZ;
1399 } else {
1400 chan_fbin = (channel->center_freq - 4900) * 10;
1401 freq_band = AR5K_EEPROM_BAND_5GHZ;
1402 }
1403
1404 /* Check if any spur_chan_fbin from EEPROM is
1405 * within our current channel's spur detection range */
1406 spur_chan_fbin = AR5K_EEPROM_NO_SPUR;
1407 spur_detection_window = AR5K_SPUR_CHAN_WIDTH;
1408 /* XXX: Half/Quarter channels ?*/
1409 if (channel->hw_value & CHANNEL_TURBO)
1410 spur_detection_window *= 2;
1411
1412 for (i = 0; i < AR5K_EEPROM_N_SPUR_CHANS; i++) {
1413 spur_chan_fbin = ee->ee_spur_chans[i][freq_band];
1414
1415 /* Note: mask cleans AR5K_EEPROM_NO_SPUR flag
1416 * so it's zero if we got nothing from EEPROM */
1417 if (spur_chan_fbin == AR5K_EEPROM_NO_SPUR) {
1418 spur_chan_fbin &= AR5K_EEPROM_SPUR_CHAN_MASK;
1419 break;
1420 }
1421
1422 if ((chan_fbin - spur_detection_window <=
1423 (spur_chan_fbin & AR5K_EEPROM_SPUR_CHAN_MASK)) &&
1424 (chan_fbin + spur_detection_window >=
1425 (spur_chan_fbin & AR5K_EEPROM_SPUR_CHAN_MASK))) {
1426 spur_chan_fbin &= AR5K_EEPROM_SPUR_CHAN_MASK;
1427 break;
1428 }
1429 }
1430
1431 /* We need to enable spur filter for this channel */
1432 if (spur_chan_fbin) {
1433 spur_offset = spur_chan_fbin - chan_fbin;
1434 /*
1435 * Calculate deltas:
1436 * spur_freq_sigma_delta -> spur_offset / sample_freq << 21
1437 * spur_delta_phase -> spur_offset / chip_freq << 11
1438 * Note: Both values have 100KHz resolution
1439 */
1440 /* XXX: Half/Quarter rate channels ? */
1441 switch (channel->hw_value) {
1442 case CHANNEL_A:
1443 /* Both sample_freq and chip_freq are 40MHz */
1444 spur_delta_phase = (spur_offset << 17) / 25;
1445 spur_freq_sigma_delta = (spur_delta_phase >> 10);
1446 symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz;
1447 break;
1448 case CHANNEL_G:
1449 /* sample_freq -> 40MHz chip_freq -> 44MHz
1450 * (for b compatibility) */
1451 spur_freq_sigma_delta = (spur_offset << 8) / 55;
1452 spur_delta_phase = (spur_offset << 17) / 25;
1453 symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz;
1454 break;
1455 case CHANNEL_T:
1456 case CHANNEL_TG:
1457 /* Both sample_freq and chip_freq are 80MHz */
1458 spur_delta_phase = (spur_offset << 16) / 25;
1459 spur_freq_sigma_delta = (spur_delta_phase >> 10);
1460 symbol_width = AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz;
1461 break;
1462 default:
1463 return;
1464 }
1465
1466 /* Calculate pilot and magnitude masks */
1467
1468 /* Scale up spur_offset by 1000 to switch to 100HZ resolution
1469 * and divide by symbol_width to find how many symbols we have
1470 * Note: number of symbols is scaled up by 16 */
1471 num_symbols_x16 = ((spur_offset * 1000) << 4) / symbol_width;
1472
1473 /* Spur is on a symbol if num_symbols_x16 % 16 is zero */
1474 if (!(num_symbols_x16 & 0xF))
1475 /* _X_ */
1476 num_symbol_offsets = 3;
1477 else
1478 /* _xx_ */
1479 num_symbol_offsets = 4;
1480
1481 for (i = 0; i < num_symbol_offsets; i++) {
1482
1483 /* Calculate pilot mask */
1484 s32 curr_sym_off =
1485 (num_symbols_x16 / 16) + i + 25;
1486
1487 /* Pilot magnitude mask seems to be a way to
1488 * declare the boundaries for our detection
1489 * window or something, it's 2 for the middle
1490 * value(s) where the symbol is expected to be
1491 * and 1 on the boundary values */
1492 u8 plt_mag_map =
1493 (i == 0 || i == (num_symbol_offsets - 1))
1494 ? 1 : 2;
1495
1496 if (curr_sym_off >= 0 && curr_sym_off <= 32) {
1497 if (curr_sym_off <= 25)
1498 pilot_mask[0] |= 1 << curr_sym_off;
1499 else if (curr_sym_off >= 27)
1500 pilot_mask[0] |= 1 << (curr_sym_off - 1);
1501 } else if (curr_sym_off >= 33 && curr_sym_off <= 52)
1502 pilot_mask[1] |= 1 << (curr_sym_off - 33);
1503
1504 /* Calculate magnitude mask (for viterbi decoder) */
1505 if (curr_sym_off >= -1 && curr_sym_off <= 14)
1506 mag_mask[0] |=
1507 plt_mag_map << (curr_sym_off + 1) * 2;
1508 else if (curr_sym_off >= 15 && curr_sym_off <= 30)
1509 mag_mask[1] |=
1510 plt_mag_map << (curr_sym_off - 15) * 2;
1511 else if (curr_sym_off >= 31 && curr_sym_off <= 46)
1512 mag_mask[2] |=
1513 plt_mag_map << (curr_sym_off - 31) * 2;
1514 else if (curr_sym_off >= 46 && curr_sym_off <= 53)
1515 mag_mask[3] |=
1516 plt_mag_map << (curr_sym_off - 47) * 2;
1517
1518 }
1519
1520 /* Write settings on hw to enable spur filter */
1521 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL,
1522 AR5K_PHY_BIN_MASK_CTL_RATE, 0xff);
1523 /* XXX: Self correlator also ? */
1524 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
1525 AR5K_PHY_IQ_PILOT_MASK_EN |
1526 AR5K_PHY_IQ_CHAN_MASK_EN |
1527 AR5K_PHY_IQ_SPUR_FILT_EN);
1528
1529 /* Set delta phase and freq sigma delta */
1530 ath5k_hw_reg_write(ah,
1531 AR5K_REG_SM(spur_delta_phase,
1532 AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE) |
1533 AR5K_REG_SM(spur_freq_sigma_delta,
1534 AR5K_PHY_TIMING_11_SPUR_FREQ_SD) |
1535 AR5K_PHY_TIMING_11_USE_SPUR_IN_AGC,
1536 AR5K_PHY_TIMING_11);
1537
1538 /* Write pilot masks */
1539 ath5k_hw_reg_write(ah, pilot_mask[0], AR5K_PHY_TIMING_7);
1540 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_8,
1541 AR5K_PHY_TIMING_8_PILOT_MASK_2,
1542 pilot_mask[1]);
1543
1544 ath5k_hw_reg_write(ah, pilot_mask[0], AR5K_PHY_TIMING_9);
1545 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_10,
1546 AR5K_PHY_TIMING_10_PILOT_MASK_2,
1547 pilot_mask[1]);
1548
1549 /* Write magnitude masks */
1550 ath5k_hw_reg_write(ah, mag_mask[0], AR5K_PHY_BIN_MASK_1);
1551 ath5k_hw_reg_write(ah, mag_mask[1], AR5K_PHY_BIN_MASK_2);
1552 ath5k_hw_reg_write(ah, mag_mask[2], AR5K_PHY_BIN_MASK_3);
1553 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL,
1554 AR5K_PHY_BIN_MASK_CTL_MASK_4,
1555 mag_mask[3]);
1556
1557 ath5k_hw_reg_write(ah, mag_mask[0], AR5K_PHY_BIN_MASK2_1);
1558 ath5k_hw_reg_write(ah, mag_mask[1], AR5K_PHY_BIN_MASK2_2);
1559 ath5k_hw_reg_write(ah, mag_mask[2], AR5K_PHY_BIN_MASK2_3);
1560 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK2_4,
1561 AR5K_PHY_BIN_MASK2_4_MASK_4,
1562 mag_mask[3]);
1563
1564 } else if (ath5k_hw_reg_read(ah, AR5K_PHY_IQ) &
1565 AR5K_PHY_IQ_SPUR_FILT_EN) {
1566 /* Clean up spur mitigation settings and disable fliter */
1567 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL,
1568 AR5K_PHY_BIN_MASK_CTL_RATE, 0);
1569 AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_IQ,
1570 AR5K_PHY_IQ_PILOT_MASK_EN |
1571 AR5K_PHY_IQ_CHAN_MASK_EN |
1572 AR5K_PHY_IQ_SPUR_FILT_EN);
1573 ath5k_hw_reg_write(ah, 0, AR5K_PHY_TIMING_11);
1574
1575 /* Clear pilot masks */
1576 ath5k_hw_reg_write(ah, 0, AR5K_PHY_TIMING_7);
1577 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_8,
1578 AR5K_PHY_TIMING_8_PILOT_MASK_2,
1579 0);
1580
1581 ath5k_hw_reg_write(ah, 0, AR5K_PHY_TIMING_9);
1582 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_10,
1583 AR5K_PHY_TIMING_10_PILOT_MASK_2,
1584 0);
1585
1586 /* Clear magnitude masks */
1587 ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK_1);
1588 ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK_2);
1589 ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK_3);
1590 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL,
1591 AR5K_PHY_BIN_MASK_CTL_MASK_4,
1592 0);
1593
1594 ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK2_1);
1595 ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK2_2);
1596 ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK2_3);
1597 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK2_4,
1598 AR5K_PHY_BIN_MASK2_4_MASK_4,
1599 0);
1600 }
1601}
1602
1603/********************\
1604 Misc PHY functions
1605\********************/
1606
1356int ath5k_hw_phy_disable(struct ath5k_hw *ah) 1607int ath5k_hw_phy_disable(struct ath5k_hw *ah)
1357{ 1608{
1358 ATH5K_TRACE(ah->ah_sc); 1609 ATH5K_TRACE(ah->ah_sc);
@@ -1362,10 +1613,6 @@ int ath5k_hw_phy_disable(struct ath5k_hw *ah)
1362 return 0; 1613 return 0;
1363} 1614}
1364 1615
1365/********************\
1366 Misc PHY functions
1367\********************/
1368
1369/* 1616/*
1370 * Get the PHY Chip revision 1617 * Get the PHY Chip revision
1371 */ 1618 */
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index 0e075bca384f..c1862f8a2e7b 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -536,26 +536,6 @@ static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
536 return; 536 return;
537} 537}
538 538
539static bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
540 struct ieee80211_channel *channel)
541{
542 u8 refclk_freq;
543
544 if ((ah->ah_radio == AR5K_RF5112) ||
545 (ah->ah_radio == AR5K_RF5413) ||
546 (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
547 refclk_freq = 40;
548 else
549 refclk_freq = 32;
550
551 if ((channel->center_freq % refclk_freq != 0) &&
552 ((channel->center_freq % refclk_freq < 10) ||
553 (channel->center_freq % refclk_freq > 22)))
554 return true;
555 else
556 return false;
557}
558
559/* TODO: Half/Quarter rate */ 539/* TODO: Half/Quarter rate */
560static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, 540static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah,
561 struct ieee80211_channel *channel) 541 struct ieee80211_channel *channel)
@@ -998,7 +978,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
998 ath5k_hw_tweak_initval_settings(ah, channel); 978 ath5k_hw_tweak_initval_settings(ah, channel);
999 979
1000 /* 980 /*
1001 * Set TX power (FIXME) 981 * Set TX power
1002 */ 982 */
1003 ret = ath5k_hw_txpower(ah, channel, ee_mode, 983 ret = ath5k_hw_txpower(ah, channel, ee_mode,
1004 ah->ah_txpower.txp_max_pwr / 2); 984 ah->ah_txpower.txp_max_pwr / 2);
@@ -1024,9 +1004,22 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
1024 /* Write OFDM timings on 5212*/ 1004 /* Write OFDM timings on 5212*/
1025 if (ah->ah_version == AR5K_AR5212 && 1005 if (ah->ah_version == AR5K_AR5212 &&
1026 channel->hw_value & CHANNEL_OFDM) { 1006 channel->hw_value & CHANNEL_OFDM) {
1007 struct ath5k_eeprom_info *ee =
1008 &ah->ah_capabilities.cap_eeprom;
1009
1027 ret = ath5k_hw_write_ofdm_timings(ah, channel); 1010 ret = ath5k_hw_write_ofdm_timings(ah, channel);
1028 if (ret) 1011 if (ret)
1029 return ret; 1012 return ret;
1013
1014 /* Note: According to docs we can have a newer
1015 * EEPROM on old hardware, so we need to verify
1016 * that our hardware is new enough to have spur
1017 * mitigation registers (delta phase etc) */
1018 if (ah->ah_mac_srev >= AR5K_SREV_AR5424 ||
1019 (ah->ah_mac_srev >= AR5K_SREV_AR5424 &&
1020 ee->ee_version >= AR5K_EEPROM_VERSION_5_3))
1021 ath5k_hw_set_spur_mitigation_filter(ah,
1022 channel);
1030 } 1023 }
1031 1024
1032 /*Enable/disable 802.11b mode on 5111 1025 /*Enable/disable 802.11b mode on 5111