diff options
author | Rafał Miłecki <zajec5@gmail.com> | 2011-12-17 07:57:25 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-12-19 14:40:49 -0500 |
commit | 5ecab603c75efafaa2604725efe0afc3da4bd55b (patch) | |
tree | aef8288287bf3cf1ca8a203cff9feae57396ee51 /drivers/net/wireless/b43 | |
parent | 647120956e4e9a2151c42f4d3eead20c7f7be869 (diff) |
b43: N-PHY: reorder functions: move RSSI calibration
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
Acked-by: Larry Finger <Larry.Finger@lwfinger.net>
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 | 600 |
1 files changed, 300 insertions, 300 deletions
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 620d278c59c2..f027909a4b34 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c | |||
@@ -1193,6 +1193,306 @@ static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type) | |||
1193 | b43_nphy_rev2_rssi_select(dev, code, type); | 1193 | b43_nphy_rev2_rssi_select(dev, code, type); |
1194 | } | 1194 | } |
1195 | 1195 | ||
1196 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */ | ||
1197 | static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf) | ||
1198 | { | ||
1199 | int i; | ||
1200 | for (i = 0; i < 2; i++) { | ||
1201 | if (type == 2) { | ||
1202 | if (i == 0) { | ||
1203 | b43_radio_maskset(dev, B2055_C1_B0NB_RSSIVCM, | ||
1204 | 0xFC, buf[0]); | ||
1205 | b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5, | ||
1206 | 0xFC, buf[1]); | ||
1207 | } else { | ||
1208 | b43_radio_maskset(dev, B2055_C2_B0NB_RSSIVCM, | ||
1209 | 0xFC, buf[2 * i]); | ||
1210 | b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5, | ||
1211 | 0xFC, buf[2 * i + 1]); | ||
1212 | } | ||
1213 | } else { | ||
1214 | if (i == 0) | ||
1215 | b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5, | ||
1216 | 0xF3, buf[0] << 2); | ||
1217 | else | ||
1218 | b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5, | ||
1219 | 0xF3, buf[2 * i + 1] << 2); | ||
1220 | } | ||
1221 | } | ||
1222 | } | ||
1223 | |||
1224 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */ | ||
1225 | static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, | ||
1226 | u8 nsamp) | ||
1227 | { | ||
1228 | int i; | ||
1229 | int out; | ||
1230 | u16 save_regs_phy[9]; | ||
1231 | u16 s[2]; | ||
1232 | |||
1233 | if (dev->phy.rev >= 3) { | ||
1234 | save_regs_phy[0] = b43_phy_read(dev, | ||
1235 | B43_NPHY_RFCTL_LUT_TRSW_UP1); | ||
1236 | save_regs_phy[1] = b43_phy_read(dev, | ||
1237 | B43_NPHY_RFCTL_LUT_TRSW_UP2); | ||
1238 | save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); | ||
1239 | save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); | ||
1240 | save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1); | ||
1241 | save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); | ||
1242 | save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0); | ||
1243 | save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1); | ||
1244 | save_regs_phy[8] = 0; | ||
1245 | } else { | ||
1246 | save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); | ||
1247 | save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); | ||
1248 | save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); | ||
1249 | save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_RFCTL_CMD); | ||
1250 | save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER); | ||
1251 | save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1); | ||
1252 | save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2); | ||
1253 | save_regs_phy[7] = 0; | ||
1254 | save_regs_phy[8] = 0; | ||
1255 | } | ||
1256 | |||
1257 | b43_nphy_rssi_select(dev, 5, type); | ||
1258 | |||
1259 | if (dev->phy.rev < 2) { | ||
1260 | save_regs_phy[8] = b43_phy_read(dev, B43_NPHY_GPIO_SEL); | ||
1261 | b43_phy_write(dev, B43_NPHY_GPIO_SEL, 5); | ||
1262 | } | ||
1263 | |||
1264 | for (i = 0; i < 4; i++) | ||
1265 | buf[i] = 0; | ||
1266 | |||
1267 | for (i = 0; i < nsamp; i++) { | ||
1268 | if (dev->phy.rev < 2) { | ||
1269 | s[0] = b43_phy_read(dev, B43_NPHY_GPIO_LOOUT); | ||
1270 | s[1] = b43_phy_read(dev, B43_NPHY_GPIO_HIOUT); | ||
1271 | } else { | ||
1272 | s[0] = b43_phy_read(dev, B43_NPHY_RSSI1); | ||
1273 | s[1] = b43_phy_read(dev, B43_NPHY_RSSI2); | ||
1274 | } | ||
1275 | |||
1276 | buf[0] += ((s8)((s[0] & 0x3F) << 2)) >> 2; | ||
1277 | buf[1] += ((s8)(((s[0] >> 8) & 0x3F) << 2)) >> 2; | ||
1278 | buf[2] += ((s8)((s[1] & 0x3F) << 2)) >> 2; | ||
1279 | buf[3] += ((s8)(((s[1] >> 8) & 0x3F) << 2)) >> 2; | ||
1280 | } | ||
1281 | out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 | | ||
1282 | (buf[2] & 0xFF) << 8 | (buf[3] & 0xFF); | ||
1283 | |||
1284 | if (dev->phy.rev < 2) | ||
1285 | b43_phy_write(dev, B43_NPHY_GPIO_SEL, save_regs_phy[8]); | ||
1286 | |||
1287 | if (dev->phy.rev >= 3) { | ||
1288 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, | ||
1289 | save_regs_phy[0]); | ||
1290 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, | ||
1291 | save_regs_phy[1]); | ||
1292 | b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[2]); | ||
1293 | b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[3]); | ||
1294 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, save_regs_phy[4]); | ||
1295 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]); | ||
1296 | b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]); | ||
1297 | b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]); | ||
1298 | } else { | ||
1299 | b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]); | ||
1300 | b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]); | ||
1301 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[2]); | ||
1302 | b43_phy_write(dev, B43_NPHY_RFCTL_CMD, save_regs_phy[3]); | ||
1303 | b43_phy_write(dev, B43_NPHY_RFCTL_OVER, save_regs_phy[4]); | ||
1304 | b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, save_regs_phy[5]); | ||
1305 | b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, save_regs_phy[6]); | ||
1306 | } | ||
1307 | |||
1308 | return out; | ||
1309 | } | ||
1310 | |||
1311 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */ | ||
1312 | static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) | ||
1313 | { | ||
1314 | int i, j; | ||
1315 | u8 state[4]; | ||
1316 | u8 code, val; | ||
1317 | u16 class, override; | ||
1318 | u8 regs_save_radio[2]; | ||
1319 | u16 regs_save_phy[2]; | ||
1320 | |||
1321 | s8 offset[4]; | ||
1322 | u8 core; | ||
1323 | u8 rail; | ||
1324 | |||
1325 | u16 clip_state[2]; | ||
1326 | u16 clip_off[2] = { 0xFFFF, 0xFFFF }; | ||
1327 | s32 results_min[4] = { }; | ||
1328 | u8 vcm_final[4] = { }; | ||
1329 | s32 results[4][4] = { }; | ||
1330 | s32 miniq[4][2] = { }; | ||
1331 | |||
1332 | if (type == 2) { | ||
1333 | code = 0; | ||
1334 | val = 6; | ||
1335 | } else if (type < 2) { | ||
1336 | code = 25; | ||
1337 | val = 4; | ||
1338 | } else { | ||
1339 | B43_WARN_ON(1); | ||
1340 | return; | ||
1341 | } | ||
1342 | |||
1343 | class = b43_nphy_classifier(dev, 0, 0); | ||
1344 | b43_nphy_classifier(dev, 7, 4); | ||
1345 | b43_nphy_read_clip_detection(dev, clip_state); | ||
1346 | b43_nphy_write_clip_detection(dev, clip_off); | ||
1347 | |||
1348 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) | ||
1349 | override = 0x140; | ||
1350 | else | ||
1351 | override = 0x110; | ||
1352 | |||
1353 | regs_save_phy[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); | ||
1354 | regs_save_radio[0] = b43_radio_read16(dev, B2055_C1_PD_RXTX); | ||
1355 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, override); | ||
1356 | b43_radio_write16(dev, B2055_C1_PD_RXTX, val); | ||
1357 | |||
1358 | regs_save_phy[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); | ||
1359 | regs_save_radio[1] = b43_radio_read16(dev, B2055_C2_PD_RXTX); | ||
1360 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, override); | ||
1361 | b43_radio_write16(dev, B2055_C2_PD_RXTX, val); | ||
1362 | |||
1363 | state[0] = b43_radio_read16(dev, B2055_C1_PD_RSSIMISC) & 0x07; | ||
1364 | state[1] = b43_radio_read16(dev, B2055_C2_PD_RSSIMISC) & 0x07; | ||
1365 | b43_radio_mask(dev, B2055_C1_PD_RSSIMISC, 0xF8); | ||
1366 | b43_radio_mask(dev, B2055_C2_PD_RSSIMISC, 0xF8); | ||
1367 | state[2] = b43_radio_read16(dev, B2055_C1_SP_RSSI) & 0x07; | ||
1368 | state[3] = b43_radio_read16(dev, B2055_C2_SP_RSSI) & 0x07; | ||
1369 | |||
1370 | b43_nphy_rssi_select(dev, 5, type); | ||
1371 | b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 0, type); | ||
1372 | b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 1, type); | ||
1373 | |||
1374 | for (i = 0; i < 4; i++) { | ||
1375 | u8 tmp[4]; | ||
1376 | for (j = 0; j < 4; j++) | ||
1377 | tmp[j] = i; | ||
1378 | if (type != 1) | ||
1379 | b43_nphy_set_rssi_2055_vcm(dev, type, tmp); | ||
1380 | b43_nphy_poll_rssi(dev, type, results[i], 8); | ||
1381 | if (type < 2) | ||
1382 | for (j = 0; j < 2; j++) | ||
1383 | miniq[i][j] = min(results[i][2 * j], | ||
1384 | results[i][2 * j + 1]); | ||
1385 | } | ||
1386 | |||
1387 | for (i = 0; i < 4; i++) { | ||
1388 | s32 mind = 40; | ||
1389 | u8 minvcm = 0; | ||
1390 | s32 minpoll = 249; | ||
1391 | s32 curr; | ||
1392 | for (j = 0; j < 4; j++) { | ||
1393 | if (type == 2) | ||
1394 | curr = abs(results[j][i]); | ||
1395 | else | ||
1396 | curr = abs(miniq[j][i / 2] - code * 8); | ||
1397 | |||
1398 | if (curr < mind) { | ||
1399 | mind = curr; | ||
1400 | minvcm = j; | ||
1401 | } | ||
1402 | |||
1403 | if (results[j][i] < minpoll) | ||
1404 | minpoll = results[j][i]; | ||
1405 | } | ||
1406 | results_min[i] = minpoll; | ||
1407 | vcm_final[i] = minvcm; | ||
1408 | } | ||
1409 | |||
1410 | if (type != 1) | ||
1411 | b43_nphy_set_rssi_2055_vcm(dev, type, vcm_final); | ||
1412 | |||
1413 | for (i = 0; i < 4; i++) { | ||
1414 | offset[i] = (code * 8) - results[vcm_final[i]][i]; | ||
1415 | |||
1416 | if (offset[i] < 0) | ||
1417 | offset[i] = -((abs(offset[i]) + 4) / 8); | ||
1418 | else | ||
1419 | offset[i] = (offset[i] + 4) / 8; | ||
1420 | |||
1421 | if (results_min[i] == 248) | ||
1422 | offset[i] = code - 32; | ||
1423 | |||
1424 | core = (i / 2) ? 2 : 1; | ||
1425 | rail = (i % 2) ? 1 : 0; | ||
1426 | |||
1427 | b43_nphy_scale_offset_rssi(dev, 0, offset[i], core, rail, | ||
1428 | type); | ||
1429 | } | ||
1430 | |||
1431 | b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[0]); | ||
1432 | b43_radio_maskset(dev, B2055_C2_PD_RSSIMISC, 0xF8, state[1]); | ||
1433 | |||
1434 | switch (state[2]) { | ||
1435 | case 1: | ||
1436 | b43_nphy_rssi_select(dev, 1, 2); | ||
1437 | break; | ||
1438 | case 4: | ||
1439 | b43_nphy_rssi_select(dev, 1, 0); | ||
1440 | break; | ||
1441 | case 2: | ||
1442 | b43_nphy_rssi_select(dev, 1, 1); | ||
1443 | break; | ||
1444 | default: | ||
1445 | b43_nphy_rssi_select(dev, 1, 1); | ||
1446 | break; | ||
1447 | } | ||
1448 | |||
1449 | switch (state[3]) { | ||
1450 | case 1: | ||
1451 | b43_nphy_rssi_select(dev, 2, 2); | ||
1452 | break; | ||
1453 | case 4: | ||
1454 | b43_nphy_rssi_select(dev, 2, 0); | ||
1455 | break; | ||
1456 | default: | ||
1457 | b43_nphy_rssi_select(dev, 2, 1); | ||
1458 | break; | ||
1459 | } | ||
1460 | |||
1461 | b43_nphy_rssi_select(dev, 0, type); | ||
1462 | |||
1463 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs_save_phy[0]); | ||
1464 | b43_radio_write16(dev, B2055_C1_PD_RXTX, regs_save_radio[0]); | ||
1465 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs_save_phy[1]); | ||
1466 | b43_radio_write16(dev, B2055_C2_PD_RXTX, regs_save_radio[1]); | ||
1467 | |||
1468 | b43_nphy_classifier(dev, 7, class); | ||
1469 | b43_nphy_write_clip_detection(dev, clip_state); | ||
1470 | /* Specs don't say about reset here, but it makes wl and b43 dumps | ||
1471 | identical, it really seems wl performs this */ | ||
1472 | b43_nphy_reset_cca(dev); | ||
1473 | } | ||
1474 | |||
1475 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */ | ||
1476 | static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) | ||
1477 | { | ||
1478 | /* TODO */ | ||
1479 | } | ||
1480 | |||
1481 | /* | ||
1482 | * RSSI Calibration | ||
1483 | * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal | ||
1484 | */ | ||
1485 | static void b43_nphy_rssi_cal(struct b43_wldev *dev) | ||
1486 | { | ||
1487 | if (dev->phy.rev >= 3) { | ||
1488 | b43_nphy_rev3_rssi_cal(dev); | ||
1489 | } else { | ||
1490 | b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Z); | ||
1491 | b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_X); | ||
1492 | b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Y); | ||
1493 | } | ||
1494 | } | ||
1495 | |||
1196 | /************************************************** | 1496 | /************************************************** |
1197 | * Workarounds | 1497 | * Workarounds |
1198 | **************************************************/ | 1498 | **************************************************/ |
@@ -2539,306 +2839,6 @@ static void b43_nphy_bphy_init(struct b43_wldev *dev) | |||
2539 | b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668); | 2839 | b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668); |
2540 | } | 2840 | } |
2541 | 2841 | ||
2542 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */ | ||
2543 | static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf) | ||
2544 | { | ||
2545 | int i; | ||
2546 | for (i = 0; i < 2; i++) { | ||
2547 | if (type == 2) { | ||
2548 | if (i == 0) { | ||
2549 | b43_radio_maskset(dev, B2055_C1_B0NB_RSSIVCM, | ||
2550 | 0xFC, buf[0]); | ||
2551 | b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5, | ||
2552 | 0xFC, buf[1]); | ||
2553 | } else { | ||
2554 | b43_radio_maskset(dev, B2055_C2_B0NB_RSSIVCM, | ||
2555 | 0xFC, buf[2 * i]); | ||
2556 | b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5, | ||
2557 | 0xFC, buf[2 * i + 1]); | ||
2558 | } | ||
2559 | } else { | ||
2560 | if (i == 0) | ||
2561 | b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5, | ||
2562 | 0xF3, buf[0] << 2); | ||
2563 | else | ||
2564 | b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5, | ||
2565 | 0xF3, buf[2 * i + 1] << 2); | ||
2566 | } | ||
2567 | } | ||
2568 | } | ||
2569 | |||
2570 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */ | ||
2571 | static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, | ||
2572 | u8 nsamp) | ||
2573 | { | ||
2574 | int i; | ||
2575 | int out; | ||
2576 | u16 save_regs_phy[9]; | ||
2577 | u16 s[2]; | ||
2578 | |||
2579 | if (dev->phy.rev >= 3) { | ||
2580 | save_regs_phy[0] = b43_phy_read(dev, | ||
2581 | B43_NPHY_RFCTL_LUT_TRSW_UP1); | ||
2582 | save_regs_phy[1] = b43_phy_read(dev, | ||
2583 | B43_NPHY_RFCTL_LUT_TRSW_UP2); | ||
2584 | save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); | ||
2585 | save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); | ||
2586 | save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1); | ||
2587 | save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); | ||
2588 | save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0); | ||
2589 | save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1); | ||
2590 | save_regs_phy[8] = 0; | ||
2591 | } else { | ||
2592 | save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); | ||
2593 | save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); | ||
2594 | save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); | ||
2595 | save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_RFCTL_CMD); | ||
2596 | save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER); | ||
2597 | save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1); | ||
2598 | save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2); | ||
2599 | save_regs_phy[7] = 0; | ||
2600 | save_regs_phy[8] = 0; | ||
2601 | } | ||
2602 | |||
2603 | b43_nphy_rssi_select(dev, 5, type); | ||
2604 | |||
2605 | if (dev->phy.rev < 2) { | ||
2606 | save_regs_phy[8] = b43_phy_read(dev, B43_NPHY_GPIO_SEL); | ||
2607 | b43_phy_write(dev, B43_NPHY_GPIO_SEL, 5); | ||
2608 | } | ||
2609 | |||
2610 | for (i = 0; i < 4; i++) | ||
2611 | buf[i] = 0; | ||
2612 | |||
2613 | for (i = 0; i < nsamp; i++) { | ||
2614 | if (dev->phy.rev < 2) { | ||
2615 | s[0] = b43_phy_read(dev, B43_NPHY_GPIO_LOOUT); | ||
2616 | s[1] = b43_phy_read(dev, B43_NPHY_GPIO_HIOUT); | ||
2617 | } else { | ||
2618 | s[0] = b43_phy_read(dev, B43_NPHY_RSSI1); | ||
2619 | s[1] = b43_phy_read(dev, B43_NPHY_RSSI2); | ||
2620 | } | ||
2621 | |||
2622 | buf[0] += ((s8)((s[0] & 0x3F) << 2)) >> 2; | ||
2623 | buf[1] += ((s8)(((s[0] >> 8) & 0x3F) << 2)) >> 2; | ||
2624 | buf[2] += ((s8)((s[1] & 0x3F) << 2)) >> 2; | ||
2625 | buf[3] += ((s8)(((s[1] >> 8) & 0x3F) << 2)) >> 2; | ||
2626 | } | ||
2627 | out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 | | ||
2628 | (buf[2] & 0xFF) << 8 | (buf[3] & 0xFF); | ||
2629 | |||
2630 | if (dev->phy.rev < 2) | ||
2631 | b43_phy_write(dev, B43_NPHY_GPIO_SEL, save_regs_phy[8]); | ||
2632 | |||
2633 | if (dev->phy.rev >= 3) { | ||
2634 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, | ||
2635 | save_regs_phy[0]); | ||
2636 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, | ||
2637 | save_regs_phy[1]); | ||
2638 | b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[2]); | ||
2639 | b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[3]); | ||
2640 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, save_regs_phy[4]); | ||
2641 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]); | ||
2642 | b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]); | ||
2643 | b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]); | ||
2644 | } else { | ||
2645 | b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]); | ||
2646 | b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]); | ||
2647 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[2]); | ||
2648 | b43_phy_write(dev, B43_NPHY_RFCTL_CMD, save_regs_phy[3]); | ||
2649 | b43_phy_write(dev, B43_NPHY_RFCTL_OVER, save_regs_phy[4]); | ||
2650 | b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, save_regs_phy[5]); | ||
2651 | b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, save_regs_phy[6]); | ||
2652 | } | ||
2653 | |||
2654 | return out; | ||
2655 | } | ||
2656 | |||
2657 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */ | ||
2658 | static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) | ||
2659 | { | ||
2660 | int i, j; | ||
2661 | u8 state[4]; | ||
2662 | u8 code, val; | ||
2663 | u16 class, override; | ||
2664 | u8 regs_save_radio[2]; | ||
2665 | u16 regs_save_phy[2]; | ||
2666 | |||
2667 | s8 offset[4]; | ||
2668 | u8 core; | ||
2669 | u8 rail; | ||
2670 | |||
2671 | u16 clip_state[2]; | ||
2672 | u16 clip_off[2] = { 0xFFFF, 0xFFFF }; | ||
2673 | s32 results_min[4] = { }; | ||
2674 | u8 vcm_final[4] = { }; | ||
2675 | s32 results[4][4] = { }; | ||
2676 | s32 miniq[4][2] = { }; | ||
2677 | |||
2678 | if (type == 2) { | ||
2679 | code = 0; | ||
2680 | val = 6; | ||
2681 | } else if (type < 2) { | ||
2682 | code = 25; | ||
2683 | val = 4; | ||
2684 | } else { | ||
2685 | B43_WARN_ON(1); | ||
2686 | return; | ||
2687 | } | ||
2688 | |||
2689 | class = b43_nphy_classifier(dev, 0, 0); | ||
2690 | b43_nphy_classifier(dev, 7, 4); | ||
2691 | b43_nphy_read_clip_detection(dev, clip_state); | ||
2692 | b43_nphy_write_clip_detection(dev, clip_off); | ||
2693 | |||
2694 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) | ||
2695 | override = 0x140; | ||
2696 | else | ||
2697 | override = 0x110; | ||
2698 | |||
2699 | regs_save_phy[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); | ||
2700 | regs_save_radio[0] = b43_radio_read16(dev, B2055_C1_PD_RXTX); | ||
2701 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, override); | ||
2702 | b43_radio_write16(dev, B2055_C1_PD_RXTX, val); | ||
2703 | |||
2704 | regs_save_phy[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); | ||
2705 | regs_save_radio[1] = b43_radio_read16(dev, B2055_C2_PD_RXTX); | ||
2706 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, override); | ||
2707 | b43_radio_write16(dev, B2055_C2_PD_RXTX, val); | ||
2708 | |||
2709 | state[0] = b43_radio_read16(dev, B2055_C1_PD_RSSIMISC) & 0x07; | ||
2710 | state[1] = b43_radio_read16(dev, B2055_C2_PD_RSSIMISC) & 0x07; | ||
2711 | b43_radio_mask(dev, B2055_C1_PD_RSSIMISC, 0xF8); | ||
2712 | b43_radio_mask(dev, B2055_C2_PD_RSSIMISC, 0xF8); | ||
2713 | state[2] = b43_radio_read16(dev, B2055_C1_SP_RSSI) & 0x07; | ||
2714 | state[3] = b43_radio_read16(dev, B2055_C2_SP_RSSI) & 0x07; | ||
2715 | |||
2716 | b43_nphy_rssi_select(dev, 5, type); | ||
2717 | b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 0, type); | ||
2718 | b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 1, type); | ||
2719 | |||
2720 | for (i = 0; i < 4; i++) { | ||
2721 | u8 tmp[4]; | ||
2722 | for (j = 0; j < 4; j++) | ||
2723 | tmp[j] = i; | ||
2724 | if (type != 1) | ||
2725 | b43_nphy_set_rssi_2055_vcm(dev, type, tmp); | ||
2726 | b43_nphy_poll_rssi(dev, type, results[i], 8); | ||
2727 | if (type < 2) | ||
2728 | for (j = 0; j < 2; j++) | ||
2729 | miniq[i][j] = min(results[i][2 * j], | ||
2730 | results[i][2 * j + 1]); | ||
2731 | } | ||
2732 | |||
2733 | for (i = 0; i < 4; i++) { | ||
2734 | s32 mind = 40; | ||
2735 | u8 minvcm = 0; | ||
2736 | s32 minpoll = 249; | ||
2737 | s32 curr; | ||
2738 | for (j = 0; j < 4; j++) { | ||
2739 | if (type == 2) | ||
2740 | curr = abs(results[j][i]); | ||
2741 | else | ||
2742 | curr = abs(miniq[j][i / 2] - code * 8); | ||
2743 | |||
2744 | if (curr < mind) { | ||
2745 | mind = curr; | ||
2746 | minvcm = j; | ||
2747 | } | ||
2748 | |||
2749 | if (results[j][i] < minpoll) | ||
2750 | minpoll = results[j][i]; | ||
2751 | } | ||
2752 | results_min[i] = minpoll; | ||
2753 | vcm_final[i] = minvcm; | ||
2754 | } | ||
2755 | |||
2756 | if (type != 1) | ||
2757 | b43_nphy_set_rssi_2055_vcm(dev, type, vcm_final); | ||
2758 | |||
2759 | for (i = 0; i < 4; i++) { | ||
2760 | offset[i] = (code * 8) - results[vcm_final[i]][i]; | ||
2761 | |||
2762 | if (offset[i] < 0) | ||
2763 | offset[i] = -((abs(offset[i]) + 4) / 8); | ||
2764 | else | ||
2765 | offset[i] = (offset[i] + 4) / 8; | ||
2766 | |||
2767 | if (results_min[i] == 248) | ||
2768 | offset[i] = code - 32; | ||
2769 | |||
2770 | core = (i / 2) ? 2 : 1; | ||
2771 | rail = (i % 2) ? 1 : 0; | ||
2772 | |||
2773 | b43_nphy_scale_offset_rssi(dev, 0, offset[i], core, rail, | ||
2774 | type); | ||
2775 | } | ||
2776 | |||
2777 | b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[0]); | ||
2778 | b43_radio_maskset(dev, B2055_C2_PD_RSSIMISC, 0xF8, state[1]); | ||
2779 | |||
2780 | switch (state[2]) { | ||
2781 | case 1: | ||
2782 | b43_nphy_rssi_select(dev, 1, 2); | ||
2783 | break; | ||
2784 | case 4: | ||
2785 | b43_nphy_rssi_select(dev, 1, 0); | ||
2786 | break; | ||
2787 | case 2: | ||
2788 | b43_nphy_rssi_select(dev, 1, 1); | ||
2789 | break; | ||
2790 | default: | ||
2791 | b43_nphy_rssi_select(dev, 1, 1); | ||
2792 | break; | ||
2793 | } | ||
2794 | |||
2795 | switch (state[3]) { | ||
2796 | case 1: | ||
2797 | b43_nphy_rssi_select(dev, 2, 2); | ||
2798 | break; | ||
2799 | case 4: | ||
2800 | b43_nphy_rssi_select(dev, 2, 0); | ||
2801 | break; | ||
2802 | default: | ||
2803 | b43_nphy_rssi_select(dev, 2, 1); | ||
2804 | break; | ||
2805 | } | ||
2806 | |||
2807 | b43_nphy_rssi_select(dev, 0, type); | ||
2808 | |||
2809 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs_save_phy[0]); | ||
2810 | b43_radio_write16(dev, B2055_C1_PD_RXTX, regs_save_radio[0]); | ||
2811 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs_save_phy[1]); | ||
2812 | b43_radio_write16(dev, B2055_C2_PD_RXTX, regs_save_radio[1]); | ||
2813 | |||
2814 | b43_nphy_classifier(dev, 7, class); | ||
2815 | b43_nphy_write_clip_detection(dev, clip_state); | ||
2816 | /* Specs don't say about reset here, but it makes wl and b43 dumps | ||
2817 | identical, it really seems wl performs this */ | ||
2818 | b43_nphy_reset_cca(dev); | ||
2819 | } | ||
2820 | |||
2821 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */ | ||
2822 | static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) | ||
2823 | { | ||
2824 | /* TODO */ | ||
2825 | } | ||
2826 | |||
2827 | /* | ||
2828 | * RSSI Calibration | ||
2829 | * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal | ||
2830 | */ | ||
2831 | static void b43_nphy_rssi_cal(struct b43_wldev *dev) | ||
2832 | { | ||
2833 | if (dev->phy.rev >= 3) { | ||
2834 | b43_nphy_rev3_rssi_cal(dev); | ||
2835 | } else { | ||
2836 | b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Z); | ||
2837 | b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_X); | ||
2838 | b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Y); | ||
2839 | } | ||
2840 | } | ||
2841 | |||
2842 | /* | 2842 | /* |
2843 | * Restore RSSI Calibration | 2843 | * Restore RSSI Calibration |
2844 | * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal | 2844 | * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal |