diff options
author | Rafał Miłecki <zajec5@gmail.com> | 2012-01-04 19:05:30 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-01-24 14:06:06 -0500 |
commit | e0c9a0219a8f542e3946fe972a68aacf8c3f906c (patch) | |
tree | 37382a9122e5ed5b48029e2ced3a34dfd78df23b /drivers/net/wireless/b43 | |
parent | 3eb1fa7e0021bc03be1bf7f68b1913d959e29512 (diff) |
b43: N-PHY: implement RSSI calibration for rev3+
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/b43')
-rw-r--r-- | drivers/net/wireless/b43/phy_n.c | 193 |
1 files changed, 187 insertions, 6 deletions
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index f6ac18139b10..945aa5267d09 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c | |||
@@ -85,6 +85,13 @@ static inline bool b43_nphy_ipa(struct b43_wldev *dev) | |||
85 | (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ)); | 85 | (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ)); |
86 | } | 86 | } |
87 | 87 | ||
88 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreGetState */ | ||
89 | static u8 b43_nphy_get_rx_core_state(struct b43_wldev *dev) | ||
90 | { | ||
91 | return (b43_phy_read(dev, B43_NPHY_RFSEQCA) & B43_NPHY_RFSEQCA_RXEN) >> | ||
92 | B43_NPHY_RFSEQCA_RXEN_SHIFT; | ||
93 | } | ||
94 | |||
88 | /************************************************** | 95 | /************************************************** |
89 | * RF (just without b43_nphy_rf_control_intc_override) | 96 | * RF (just without b43_nphy_rf_control_intc_override) |
90 | **************************************************/ | 97 | **************************************************/ |
@@ -1290,6 +1297,186 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, | |||
1290 | return out; | 1297 | return out; |
1291 | } | 1298 | } |
1292 | 1299 | ||
1300 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */ | ||
1301 | static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) | ||
1302 | { | ||
1303 | struct b43_phy_n *nphy = dev->phy.n; | ||
1304 | |||
1305 | u16 saved_regs_phy_rfctl[2]; | ||
1306 | u16 saved_regs_phy[13]; | ||
1307 | u16 regs_to_store[] = { | ||
1308 | B43_NPHY_AFECTL_OVER1, B43_NPHY_AFECTL_OVER, | ||
1309 | B43_NPHY_AFECTL_C1, B43_NPHY_AFECTL_C2, | ||
1310 | B43_NPHY_TXF_40CO_B1S1, B43_NPHY_RFCTL_OVER, | ||
1311 | B43_NPHY_TXF_40CO_B1S0, B43_NPHY_TXF_40CO_B32S1, | ||
1312 | B43_NPHY_RFCTL_CMD, | ||
1313 | B43_NPHY_RFCTL_LUT_TRSW_UP1, B43_NPHY_RFCTL_LUT_TRSW_UP2, | ||
1314 | B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2 | ||
1315 | }; | ||
1316 | |||
1317 | u16 class; | ||
1318 | |||
1319 | u16 clip_state[2]; | ||
1320 | u16 clip_off[2] = { 0xFFFF, 0xFFFF }; | ||
1321 | |||
1322 | u8 vcm_final = 0; | ||
1323 | s8 offset[4]; | ||
1324 | s32 results[8][4] = { }; | ||
1325 | s32 results_min[4] = { }; | ||
1326 | s32 poll_results[4] = { }; | ||
1327 | |||
1328 | u16 *rssical_radio_regs = NULL; | ||
1329 | u16 *rssical_phy_regs = NULL; | ||
1330 | |||
1331 | u16 r; /* routing */ | ||
1332 | u8 rx_core_state; | ||
1333 | u8 core, i, j; | ||
1334 | |||
1335 | class = b43_nphy_classifier(dev, 0, 0); | ||
1336 | b43_nphy_classifier(dev, 7, 4); | ||
1337 | b43_nphy_read_clip_detection(dev, clip_state); | ||
1338 | b43_nphy_write_clip_detection(dev, clip_off); | ||
1339 | |||
1340 | saved_regs_phy_rfctl[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); | ||
1341 | saved_regs_phy_rfctl[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); | ||
1342 | for (i = 0; i < ARRAY_SIZE(regs_to_store); i++) | ||
1343 | saved_regs_phy[i] = b43_phy_read(dev, regs_to_store[i]); | ||
1344 | |||
1345 | b43_nphy_rf_control_intc_override(dev, 0, 0, 7); | ||
1346 | b43_nphy_rf_control_intc_override(dev, 1, 1, 7); | ||
1347 | b43_nphy_rf_control_override(dev, 0x1, 0, 0, false); | ||
1348 | b43_nphy_rf_control_override(dev, 0x2, 1, 0, false); | ||
1349 | b43_nphy_rf_control_override(dev, 0x80, 1, 0, false); | ||
1350 | b43_nphy_rf_control_override(dev, 0x40, 1, 0, false); | ||
1351 | |||
1352 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { | ||
1353 | b43_nphy_rf_control_override(dev, 0x20, 0, 0, false); | ||
1354 | b43_nphy_rf_control_override(dev, 0x10, 1, 0, false); | ||
1355 | } else { | ||
1356 | b43_nphy_rf_control_override(dev, 0x10, 0, 0, false); | ||
1357 | b43_nphy_rf_control_override(dev, 0x20, 1, 0, false); | ||
1358 | } | ||
1359 | |||
1360 | rx_core_state = b43_nphy_get_rx_core_state(dev); | ||
1361 | for (core = 0; core < 2; core++) { | ||
1362 | if (!(rx_core_state & (1 << core))) | ||
1363 | continue; | ||
1364 | r = core ? B2056_RX1 : B2056_RX0; | ||
1365 | b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 0, 2); | ||
1366 | b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 1, 2); | ||
1367 | for (i = 0; i < 8; i++) { | ||
1368 | b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC, 0xE3, | ||
1369 | i << 2); | ||
1370 | b43_nphy_poll_rssi(dev, 2, results[i], 8); | ||
1371 | } | ||
1372 | for (i = 0; i < 4; i++) { | ||
1373 | s32 curr; | ||
1374 | s32 mind = 40; | ||
1375 | s32 minpoll = 249; | ||
1376 | u8 minvcm = 0; | ||
1377 | if (2 * core != i) | ||
1378 | continue; | ||
1379 | for (j = 0; j < 8; j++) { | ||
1380 | curr = results[j][i] * results[j][i] + | ||
1381 | results[j][i + 1] * results[j][i]; | ||
1382 | if (curr < mind) { | ||
1383 | mind = curr; | ||
1384 | minvcm = j; | ||
1385 | } | ||
1386 | if (results[j][i] < minpoll) | ||
1387 | minpoll = results[j][i]; | ||
1388 | } | ||
1389 | vcm_final = minvcm; | ||
1390 | results_min[i] = minpoll; | ||
1391 | } | ||
1392 | b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC, 0xE3, | ||
1393 | vcm_final << 2); | ||
1394 | for (i = 0; i < 4; i++) { | ||
1395 | if (core != i / 2) | ||
1396 | continue; | ||
1397 | offset[i] = -results[vcm_final][i]; | ||
1398 | if (offset[i] < 0) | ||
1399 | offset[i] = -((abs(offset[i]) + 4) / 8); | ||
1400 | else | ||
1401 | offset[i] = (offset[i] + 4) / 8; | ||
1402 | if (results_min[i] == 248) | ||
1403 | offset[i] = -32; | ||
1404 | b43_nphy_scale_offset_rssi(dev, 0, offset[i], | ||
1405 | (i / 2 == 0) ? 1 : 2, | ||
1406 | (i % 2 == 0) ? 0 : 1, | ||
1407 | 2); | ||
1408 | } | ||
1409 | } | ||
1410 | for (core = 0; core < 2; core++) { | ||
1411 | if (!(rx_core_state & (1 << core))) | ||
1412 | continue; | ||
1413 | for (i = 0; i < 2; i++) { | ||
1414 | b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 0, i); | ||
1415 | b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 1, i); | ||
1416 | b43_nphy_poll_rssi(dev, i, poll_results, 8); | ||
1417 | for (j = 0; j < 4; j++) { | ||
1418 | if (j / 2 == core) | ||
1419 | offset[j] = 232 - poll_results[j]; | ||
1420 | if (offset[j] < 0) | ||
1421 | offset[j] = -(abs(offset[j] + 4) / 8); | ||
1422 | else | ||
1423 | offset[j] = (offset[j] + 4) / 8; | ||
1424 | b43_nphy_scale_offset_rssi(dev, 0, | ||
1425 | offset[2 * core], core + 1, j % 2, i); | ||
1426 | } | ||
1427 | } | ||
1428 | } | ||
1429 | |||
1430 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, saved_regs_phy_rfctl[0]); | ||
1431 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, saved_regs_phy_rfctl[1]); | ||
1432 | |||
1433 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); | ||
1434 | |||
1435 | b43_phy_set(dev, B43_NPHY_TXF_40CO_B1S1, 0x1); | ||
1436 | b43_phy_set(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_START); | ||
1437 | b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S1, ~0x1); | ||
1438 | |||
1439 | b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1); | ||
1440 | b43_phy_set(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_RXTX); | ||
1441 | b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S1, ~0x1); | ||
1442 | |||
1443 | for (i = 0; i < ARRAY_SIZE(regs_to_store); i++) | ||
1444 | b43_phy_write(dev, regs_to_store[i], saved_regs_phy[i]); | ||
1445 | |||
1446 | /* Store for future configuration */ | ||
1447 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||
1448 | rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; | ||
1449 | rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G; | ||
1450 | } else { | ||
1451 | rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G; | ||
1452 | rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; | ||
1453 | } | ||
1454 | rssical_radio_regs[0] = b43_radio_read(dev, 0x602B); | ||
1455 | rssical_radio_regs[0] = b43_radio_read(dev, 0x702B); | ||
1456 | rssical_phy_regs[0] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_Z); | ||
1457 | rssical_phy_regs[1] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z); | ||
1458 | rssical_phy_regs[2] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_Z); | ||
1459 | rssical_phy_regs[3] = b43_phy_read(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z); | ||
1460 | rssical_phy_regs[4] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_X); | ||
1461 | rssical_phy_regs[5] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_X); | ||
1462 | rssical_phy_regs[6] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_X); | ||
1463 | rssical_phy_regs[7] = b43_phy_read(dev, B43_NPHY_RSSIMC_1Q_RSSI_X); | ||
1464 | rssical_phy_regs[8] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_Y); | ||
1465 | rssical_phy_regs[9] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y); | ||
1466 | rssical_phy_regs[10] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_Y); | ||
1467 | rssical_phy_regs[11] = b43_phy_read(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y); | ||
1468 | |||
1469 | /* Remember for which channel we store configuration */ | ||
1470 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | ||
1471 | nphy->rssical_chanspec_2G.center_freq = dev->phy.channel_freq; | ||
1472 | else | ||
1473 | nphy->rssical_chanspec_5G.center_freq = dev->phy.channel_freq; | ||
1474 | |||
1475 | /* End of calibration, restore configuration */ | ||
1476 | b43_nphy_classifier(dev, 7, class); | ||
1477 | b43_nphy_write_clip_detection(dev, clip_state); | ||
1478 | } | ||
1479 | |||
1293 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */ | 1480 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */ |
1294 | static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) | 1481 | static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) |
1295 | { | 1482 | { |
@@ -1454,12 +1641,6 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) | |||
1454 | b43_nphy_reset_cca(dev); | 1641 | b43_nphy_reset_cca(dev); |
1455 | } | 1642 | } |
1456 | 1643 | ||
1457 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */ | ||
1458 | static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) | ||
1459 | { | ||
1460 | /* TODO */ | ||
1461 | } | ||
1462 | |||
1463 | /* | 1644 | /* |
1464 | * RSSI Calibration | 1645 | * RSSI Calibration |
1465 | * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal | 1646 | * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal |