aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath5k/phy.c
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/net/wireless/ath/ath5k/phy.c
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/net/wireless/ath/ath5k/phy.c')
-rw-r--r--drivers/net/wireless/ath/ath5k/phy.c255
1 files changed, 251 insertions, 4 deletions
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 */