diff options
Diffstat (limited to 'drivers/net/wireless/b43/phy_n.c')
-rw-r--r-- | drivers/net/wireless/b43/phy_n.c | 532 |
1 files changed, 427 insertions, 105 deletions
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index bf5a43855358..108118820b36 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c | |||
@@ -85,22 +85,11 @@ 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/GetIpaGainTbl */ | 88 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreGetState */ |
89 | static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev) | 89 | static u8 b43_nphy_get_rx_core_state(struct b43_wldev *dev) |
90 | { | 90 | { |
91 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | 91 | return (b43_phy_read(dev, B43_NPHY_RFSEQCA) & B43_NPHY_RFSEQCA_RXEN) >> |
92 | if (dev->phy.rev >= 6) { | 92 | B43_NPHY_RFSEQCA_RXEN_SHIFT; |
93 | if (dev->dev->chip_id == 47162) | ||
94 | return txpwrctrl_tx_gain_ipa_rev5; | ||
95 | return txpwrctrl_tx_gain_ipa_rev6; | ||
96 | } else if (dev->phy.rev >= 5) { | ||
97 | return txpwrctrl_tx_gain_ipa_rev5; | ||
98 | } else { | ||
99 | return txpwrctrl_tx_gain_ipa; | ||
100 | } | ||
101 | } else { | ||
102 | return txpwrctrl_tx_gain_ipa_5g; | ||
103 | } | ||
104 | } | 93 | } |
105 | 94 | ||
106 | /************************************************** | 95 | /************************************************** |
@@ -229,7 +218,7 @@ static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, | |||
229 | 218 | ||
230 | reg = (i == 0) ? | 219 | reg = (i == 0) ? |
231 | B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2; | 220 | B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2; |
232 | b43_phy_mask(dev, reg, 0xFBFF); | 221 | b43_phy_set(dev, reg, 0x400); |
233 | 222 | ||
234 | switch (field) { | 223 | switch (field) { |
235 | case 0: | 224 | case 0: |
@@ -245,7 +234,7 @@ static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, | |||
245 | b43_phy_set(dev, B43_NPHY_RFCTL_CMD, | 234 | b43_phy_set(dev, B43_NPHY_RFCTL_CMD, |
246 | B43_NPHY_RFCTL_CMD_START); | 235 | B43_NPHY_RFCTL_CMD_START); |
247 | for (j = 0; j < 100; j++) { | 236 | for (j = 0; j < 100; j++) { |
248 | if (b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_START) { | 237 | if (!(b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_START)) { |
249 | j = 0; | 238 | j = 0; |
250 | break; | 239 | break; |
251 | } | 240 | } |
@@ -264,7 +253,7 @@ static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, | |||
264 | b43_phy_set(dev, B43_NPHY_RFCTL_CMD, | 253 | b43_phy_set(dev, B43_NPHY_RFCTL_CMD, |
265 | B43_NPHY_RFCTL_CMD_RXTX); | 254 | B43_NPHY_RFCTL_CMD_RXTX); |
266 | for (j = 0; j < 100; j++) { | 255 | for (j = 0; j < 100; j++) { |
267 | if (b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_RXTX) { | 256 | if (!(b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_RXTX)) { |
268 | j = 0; | 257 | j = 0; |
269 | break; | 258 | break; |
270 | } | 259 | } |
@@ -1231,12 +1220,12 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, | |||
1231 | u16 s[2]; | 1220 | u16 s[2]; |
1232 | 1221 | ||
1233 | if (dev->phy.rev >= 3) { | 1222 | if (dev->phy.rev >= 3) { |
1234 | save_regs_phy[0] = b43_phy_read(dev, | 1223 | save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); |
1224 | save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); | ||
1225 | save_regs_phy[2] = b43_phy_read(dev, | ||
1235 | B43_NPHY_RFCTL_LUT_TRSW_UP1); | 1226 | B43_NPHY_RFCTL_LUT_TRSW_UP1); |
1236 | save_regs_phy[1] = b43_phy_read(dev, | 1227 | save_regs_phy[3] = b43_phy_read(dev, |
1237 | B43_NPHY_RFCTL_LUT_TRSW_UP2); | 1228 | 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); | 1229 | 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); | 1230 | 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); | 1231 | save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0); |
@@ -1285,12 +1274,12 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, | |||
1285 | b43_phy_write(dev, B43_NPHY_GPIO_SEL, save_regs_phy[8]); | 1274 | b43_phy_write(dev, B43_NPHY_GPIO_SEL, save_regs_phy[8]); |
1286 | 1275 | ||
1287 | if (dev->phy.rev >= 3) { | 1276 | if (dev->phy.rev >= 3) { |
1277 | b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]); | ||
1278 | b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]); | ||
1288 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, | 1279 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, |
1289 | save_regs_phy[0]); | 1280 | save_regs_phy[2]); |
1290 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, | 1281 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, |
1291 | save_regs_phy[1]); | 1282 | save_regs_phy[3]); |
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]); | 1283 | 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]); | 1284 | 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]); | 1285 | b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]); |
@@ -1308,6 +1297,186 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, | |||
1308 | return out; | 1297 | return out; |
1309 | } | 1298 | } |
1310 | 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 | |||
1311 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */ | 1480 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */ |
1312 | 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) |
1313 | { | 1482 | { |
@@ -1472,12 +1641,6 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) | |||
1472 | b43_nphy_reset_cca(dev); | 1641 | b43_nphy_reset_cca(dev); |
1473 | } | 1642 | } |
1474 | 1643 | ||
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 | /* | 1644 | /* |
1482 | * RSSI Calibration | 1645 | * RSSI Calibration |
1483 | * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal | 1646 | * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal |
@@ -2229,27 +2392,12 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev) | |||
2229 | */ | 2392 | */ |
2230 | 2393 | ||
2231 | for (i = 0; i < 2; i++) { | 2394 | for (i = 0; i < 2; i++) { |
2232 | if (dev->phy.rev >= 3) { | 2395 | txgain = *(b43_nphy_get_tx_gain_table(dev) + txpi[i]); |
2233 | if (b43_nphy_ipa(dev)) { | 2396 | |
2234 | txgain = *(b43_nphy_get_ipa_gain_table(dev) + | 2397 | if (dev->phy.rev >= 3) |
2235 | txpi[i]); | ||
2236 | } else if (b43_current_band(dev->wl) == | ||
2237 | IEEE80211_BAND_5GHZ) { | ||
2238 | /* FIXME: use 5GHz tables */ | ||
2239 | txgain = | ||
2240 | b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]]; | ||
2241 | } else { | ||
2242 | if (dev->phy.rev >= 5 && | ||
2243 | sprom->fem.ghz5.extpa_gain == 3) | ||
2244 | ; /* FIXME: 5GHz_txgain_HiPwrEPA */ | ||
2245 | txgain = | ||
2246 | b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]]; | ||
2247 | } | ||
2248 | radio_gain = (txgain >> 16) & 0x1FFFF; | 2398 | radio_gain = (txgain >> 16) & 0x1FFFF; |
2249 | } else { | 2399 | else |
2250 | txgain = b43_ntab_tx_gain_rev0_1_2[txpi[i]]; | ||
2251 | radio_gain = (txgain >> 16) & 0x1FFF; | 2400 | radio_gain = (txgain >> 16) & 0x1FFF; |
2252 | } | ||
2253 | 2401 | ||
2254 | if (dev->phy.rev >= 7) | 2402 | if (dev->phy.rev >= 7) |
2255 | dac_gain = (txgain >> 8) & 0x7; | 2403 | dac_gain = (txgain >> 8) & 0x7; |
@@ -2420,55 +2568,252 @@ static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev) | |||
2420 | nphy->pwr_ctl_info[1].idle_tssi_2g = (tmp >> 8) & 0xFF; | 2568 | nphy->pwr_ctl_info[1].idle_tssi_2g = (tmp >> 8) & 0xFF; |
2421 | } | 2569 | } |
2422 | 2570 | ||
2423 | static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev) | 2571 | /* http://bcm-v4.sipsolutions.net/PHY/N/TxPwrLimitToTbl */ |
2572 | static void b43_nphy_tx_prepare_adjusted_power_table(struct b43_wldev *dev) | ||
2424 | { | 2573 | { |
2425 | struct b43_phy *phy = &dev->phy; | 2574 | struct b43_phy_n *nphy = dev->phy.n; |
2426 | 2575 | ||
2427 | const u32 *table = NULL; | 2576 | u8 idx, delta; |
2428 | #if 0 | 2577 | u8 i, stf_mode; |
2429 | TODO: b43_ntab_papd_pga_gain_delta_ipa_2* | ||
2430 | u32 rfpwr_offset; | ||
2431 | u8 pga_gain; | ||
2432 | int i; | ||
2433 | #endif | ||
2434 | 2578 | ||
2435 | if (phy->rev >= 3) { | 2579 | for (i = 0; i < 4; i++) |
2436 | if (b43_nphy_ipa(dev)) { | 2580 | nphy->adj_pwr_tbl[i] = nphy->tx_power_offset[i]; |
2437 | table = b43_nphy_get_ipa_gain_table(dev); | 2581 | |
2582 | for (stf_mode = 0; stf_mode < 4; stf_mode++) { | ||
2583 | delta = 0; | ||
2584 | switch (stf_mode) { | ||
2585 | case 0: | ||
2586 | if (dev->phy.is_40mhz && dev->phy.rev >= 5) { | ||
2587 | idx = 68; | ||
2588 | } else { | ||
2589 | delta = 1; | ||
2590 | idx = dev->phy.is_40mhz ? 52 : 4; | ||
2591 | } | ||
2592 | break; | ||
2593 | case 1: | ||
2594 | idx = dev->phy.is_40mhz ? 76 : 28; | ||
2595 | break; | ||
2596 | case 2: | ||
2597 | idx = dev->phy.is_40mhz ? 84 : 36; | ||
2598 | break; | ||
2599 | case 3: | ||
2600 | idx = dev->phy.is_40mhz ? 92 : 44; | ||
2601 | break; | ||
2602 | } | ||
2603 | |||
2604 | for (i = 0; i < 20; i++) { | ||
2605 | nphy->adj_pwr_tbl[4 + 4 * i + stf_mode] = | ||
2606 | nphy->tx_power_offset[idx]; | ||
2607 | if (i == 0) | ||
2608 | idx += delta; | ||
2609 | if (i == 14) | ||
2610 | idx += 1 - delta; | ||
2611 | if (i == 3 || i == 4 || i == 7 || i == 8 || i == 11 || | ||
2612 | i == 13) | ||
2613 | idx += 1; | ||
2614 | } | ||
2615 | } | ||
2616 | } | ||
2617 | |||
2618 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlSetup */ | ||
2619 | static void b43_nphy_tx_power_ctl_setup(struct b43_wldev *dev) | ||
2620 | { | ||
2621 | struct b43_phy_n *nphy = dev->phy.n; | ||
2622 | struct ssb_sprom *sprom = dev->dev->bus_sprom; | ||
2623 | |||
2624 | s16 a1[2], b0[2], b1[2]; | ||
2625 | u8 idle[2]; | ||
2626 | s8 target[2]; | ||
2627 | s32 num, den, pwr; | ||
2628 | u32 regval[64]; | ||
2629 | |||
2630 | u16 freq = dev->phy.channel_freq; | ||
2631 | u16 tmp; | ||
2632 | u16 r; /* routing */ | ||
2633 | u8 i, c; | ||
2634 | |||
2635 | if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) { | ||
2636 | b43_maskset32(dev, B43_MMIO_MACCTL, ~0, 0x200000); | ||
2637 | b43_read32(dev, B43_MMIO_MACCTL); | ||
2638 | udelay(1); | ||
2639 | } | ||
2640 | |||
2641 | if (nphy->hang_avoid) | ||
2642 | b43_nphy_stay_in_carrier_search(dev, true); | ||
2643 | |||
2644 | b43_phy_set(dev, B43_NPHY_TSSIMODE, B43_NPHY_TSSIMODE_EN); | ||
2645 | if (dev->phy.rev >= 3) | ||
2646 | b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD, | ||
2647 | ~B43_NPHY_TXPCTL_CMD_PCTLEN & 0xFFFF); | ||
2648 | else | ||
2649 | b43_phy_set(dev, B43_NPHY_TXPCTL_CMD, | ||
2650 | B43_NPHY_TXPCTL_CMD_PCTLEN); | ||
2651 | |||
2652 | if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) | ||
2653 | b43_maskset32(dev, B43_MMIO_MACCTL, ~0x200000, 0); | ||
2654 | |||
2655 | if (sprom->revision < 4) { | ||
2656 | idle[0] = nphy->pwr_ctl_info[0].idle_tssi_2g; | ||
2657 | idle[1] = nphy->pwr_ctl_info[1].idle_tssi_2g; | ||
2658 | target[0] = target[1] = 52; | ||
2659 | a1[0] = a1[1] = -424; | ||
2660 | b0[0] = b0[1] = 5612; | ||
2661 | b1[0] = b1[1] = -1393; | ||
2662 | } else { | ||
2663 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||
2664 | for (c = 0; c < 2; c++) { | ||
2665 | idle[c] = nphy->pwr_ctl_info[c].idle_tssi_2g; | ||
2666 | target[c] = sprom->core_pwr_info[c].maxpwr_2g; | ||
2667 | a1[c] = sprom->core_pwr_info[c].pa_2g[0]; | ||
2668 | b0[c] = sprom->core_pwr_info[c].pa_2g[1]; | ||
2669 | b1[c] = sprom->core_pwr_info[c].pa_2g[2]; | ||
2670 | } | ||
2671 | } else if (freq >= 4900 && freq < 5100) { | ||
2672 | for (c = 0; c < 2; c++) { | ||
2673 | idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g; | ||
2674 | target[c] = sprom->core_pwr_info[c].maxpwr_5gl; | ||
2675 | a1[c] = sprom->core_pwr_info[c].pa_5gl[0]; | ||
2676 | b0[c] = sprom->core_pwr_info[c].pa_5gl[1]; | ||
2677 | b1[c] = sprom->core_pwr_info[c].pa_5gl[2]; | ||
2678 | } | ||
2679 | } else if (freq >= 5100 && freq < 5500) { | ||
2680 | for (c = 0; c < 2; c++) { | ||
2681 | idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g; | ||
2682 | target[c] = sprom->core_pwr_info[c].maxpwr_5g; | ||
2683 | a1[c] = sprom->core_pwr_info[c].pa_5g[0]; | ||
2684 | b0[c] = sprom->core_pwr_info[c].pa_5g[1]; | ||
2685 | b1[c] = sprom->core_pwr_info[c].pa_5g[2]; | ||
2686 | } | ||
2687 | } else if (freq >= 5500) { | ||
2688 | for (c = 0; c < 2; c++) { | ||
2689 | idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g; | ||
2690 | target[c] = sprom->core_pwr_info[c].maxpwr_5gh; | ||
2691 | a1[c] = sprom->core_pwr_info[c].pa_5gh[0]; | ||
2692 | b0[c] = sprom->core_pwr_info[c].pa_5gh[1]; | ||
2693 | b1[c] = sprom->core_pwr_info[c].pa_5gh[2]; | ||
2694 | } | ||
2438 | } else { | 2695 | } else { |
2439 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { | 2696 | idle[0] = nphy->pwr_ctl_info[0].idle_tssi_5g; |
2440 | if (phy->rev == 3) | 2697 | idle[1] = nphy->pwr_ctl_info[1].idle_tssi_5g; |
2441 | table = b43_ntab_tx_gain_rev3_5ghz; | 2698 | target[0] = target[1] = 52; |
2442 | if (phy->rev == 4) | 2699 | a1[0] = a1[1] = -424; |
2443 | table = b43_ntab_tx_gain_rev4_5ghz; | 2700 | b0[0] = b0[1] = 5612; |
2444 | else | 2701 | b1[0] = b1[1] = -1393; |
2445 | table = b43_ntab_tx_gain_rev5plus_5ghz; | 2702 | } |
2703 | } | ||
2704 | /* target[0] = target[1] = nphy->tx_power_max; */ | ||
2705 | |||
2706 | if (dev->phy.rev >= 3) { | ||
2707 | if (sprom->fem.ghz2.tssipos) | ||
2708 | b43_phy_set(dev, B43_NPHY_TXPCTL_ITSSI, 0x4000); | ||
2709 | if (dev->phy.rev >= 7) { | ||
2710 | for (c = 0; c < 2; c++) { | ||
2711 | r = c ? 0x190 : 0x170; | ||
2712 | if (b43_nphy_ipa(dev)) | ||
2713 | b43_radio_write(dev, r + 0x9, (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ? 0xE : 0xC); | ||
2714 | } | ||
2715 | } else { | ||
2716 | if (b43_nphy_ipa(dev)) { | ||
2717 | tmp = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? 0xC : 0xE; | ||
2718 | b43_radio_write(dev, | ||
2719 | B2056_TX0 | B2056_TX_TX_SSI_MUX, tmp); | ||
2720 | b43_radio_write(dev, | ||
2721 | B2056_TX1 | B2056_TX_TX_SSI_MUX, tmp); | ||
2446 | } else { | 2722 | } else { |
2447 | table = b43_ntab_tx_gain_rev3plus_2ghz; | 2723 | b43_radio_write(dev, |
2724 | B2056_TX0 | B2056_TX_TX_SSI_MUX, 0x11); | ||
2725 | b43_radio_write(dev, | ||
2726 | B2056_TX1 | B2056_TX_TX_SSI_MUX, 0x11); | ||
2448 | } | 2727 | } |
2449 | } | 2728 | } |
2729 | } | ||
2730 | |||
2731 | if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) { | ||
2732 | b43_maskset32(dev, B43_MMIO_MACCTL, ~0, 0x200000); | ||
2733 | b43_read32(dev, B43_MMIO_MACCTL); | ||
2734 | udelay(1); | ||
2735 | } | ||
2736 | |||
2737 | if (dev->phy.rev >= 7) { | ||
2738 | b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, | ||
2739 | ~B43_NPHY_TXPCTL_CMD_INIT, 0x19); | ||
2740 | b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT, | ||
2741 | ~B43_NPHY_TXPCTL_INIT_PIDXI1, 0x19); | ||
2450 | } else { | 2742 | } else { |
2451 | table = b43_ntab_tx_gain_rev0_1_2; | 2743 | b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, |
2744 | ~B43_NPHY_TXPCTL_CMD_INIT, 0x40); | ||
2745 | if (dev->phy.rev > 1) | ||
2746 | b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT, | ||
2747 | ~B43_NPHY_TXPCTL_INIT_PIDXI1, 0x40); | ||
2748 | } | ||
2749 | |||
2750 | if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) | ||
2751 | b43_maskset32(dev, B43_MMIO_MACCTL, ~0x200000, 0); | ||
2752 | |||
2753 | b43_phy_write(dev, B43_NPHY_TXPCTL_N, | ||
2754 | 0xF0 << B43_NPHY_TXPCTL_N_TSSID_SHIFT | | ||
2755 | 3 << B43_NPHY_TXPCTL_N_NPTIL2_SHIFT); | ||
2756 | b43_phy_write(dev, B43_NPHY_TXPCTL_ITSSI, | ||
2757 | idle[0] << B43_NPHY_TXPCTL_ITSSI_0_SHIFT | | ||
2758 | idle[1] << B43_NPHY_TXPCTL_ITSSI_1_SHIFT | | ||
2759 | B43_NPHY_TXPCTL_ITSSI_BINF); | ||
2760 | b43_phy_write(dev, B43_NPHY_TXPCTL_TPWR, | ||
2761 | target[0] << B43_NPHY_TXPCTL_TPWR_0_SHIFT | | ||
2762 | target[1] << B43_NPHY_TXPCTL_TPWR_1_SHIFT); | ||
2763 | |||
2764 | for (c = 0; c < 2; c++) { | ||
2765 | for (i = 0; i < 64; i++) { | ||
2766 | num = 8 * (16 * b0[c] + b1[c] * i); | ||
2767 | den = 32768 + a1[c] * i; | ||
2768 | pwr = max((4 * num + den / 2) / den, -8); | ||
2769 | if (dev->phy.rev < 3 && (i <= (31 - idle[c] + 1))) | ||
2770 | pwr = max(pwr, target[c] + 1); | ||
2771 | regval[i] = pwr; | ||
2772 | } | ||
2773 | b43_ntab_write_bulk(dev, B43_NTAB32(26 + c, 0), 64, regval); | ||
2452 | } | 2774 | } |
2775 | |||
2776 | b43_nphy_tx_prepare_adjusted_power_table(dev); | ||
2777 | /* | ||
2778 | b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84, nphy->adj_pwr_tbl); | ||
2779 | b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84, nphy->adj_pwr_tbl); | ||
2780 | */ | ||
2781 | |||
2782 | if (nphy->hang_avoid) | ||
2783 | b43_nphy_stay_in_carrier_search(dev, false); | ||
2784 | } | ||
2785 | |||
2786 | static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev) | ||
2787 | { | ||
2788 | struct b43_phy *phy = &dev->phy; | ||
2789 | |||
2790 | const u32 *table = NULL; | ||
2791 | u32 rfpwr_offset; | ||
2792 | u8 pga_gain; | ||
2793 | int i; | ||
2794 | |||
2795 | table = b43_nphy_get_tx_gain_table(dev); | ||
2453 | b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table); | 2796 | b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table); |
2454 | b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table); | 2797 | b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table); |
2455 | 2798 | ||
2456 | if (phy->rev >= 3) { | 2799 | if (phy->rev >= 3) { |
2457 | #if 0 | 2800 | #if 0 |
2458 | nphy->gmval = (table[0] >> 16) & 0x7000; | 2801 | nphy->gmval = (table[0] >> 16) & 0x7000; |
2802 | #endif | ||
2459 | 2803 | ||
2460 | for (i = 0; i < 128; i++) { | 2804 | for (i = 0; i < 128; i++) { |
2461 | pga_gain = (table[i] >> 24) & 0xF; | 2805 | pga_gain = (table[i] >> 24) & 0xF; |
2462 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | 2806 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) |
2463 | rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain]; | 2807 | rfpwr_offset = |
2808 | b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain]; | ||
2464 | else | 2809 | else |
2465 | rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_5g[pga_gain]; | 2810 | rfpwr_offset = |
2811 | 0; /* FIXME */ | ||
2466 | b43_ntab_write(dev, B43_NTAB32(26, 576 + i), | 2812 | b43_ntab_write(dev, B43_NTAB32(26, 576 + i), |
2467 | rfpwr_offset); | 2813 | rfpwr_offset); |
2468 | b43_ntab_write(dev, B43_NTAB32(27, 576 + i), | 2814 | b43_ntab_write(dev, B43_NTAB32(27, 576 + i), |
2469 | rfpwr_offset); | 2815 | rfpwr_offset); |
2470 | } | 2816 | } |
2471 | #endif | ||
2472 | } | 2817 | } |
2473 | } | 2818 | } |
2474 | 2819 | ||
@@ -3139,32 +3484,13 @@ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev) | |||
3139 | B43_NPHY_TXPCTL_STAT_BIDX_SHIFT; | 3484 | B43_NPHY_TXPCTL_STAT_BIDX_SHIFT; |
3140 | 3485 | ||
3141 | for (i = 0; i < 2; ++i) { | 3486 | for (i = 0; i < 2; ++i) { |
3487 | table = b43_nphy_get_tx_gain_table(dev); | ||
3142 | if (dev->phy.rev >= 3) { | 3488 | if (dev->phy.rev >= 3) { |
3143 | enum ieee80211_band band = | ||
3144 | b43_current_band(dev->wl); | ||
3145 | |||
3146 | if (b43_nphy_ipa(dev)) { | ||
3147 | table = b43_nphy_get_ipa_gain_table(dev); | ||
3148 | } else { | ||
3149 | if (band == IEEE80211_BAND_5GHZ) { | ||
3150 | if (dev->phy.rev == 3) | ||
3151 | table = b43_ntab_tx_gain_rev3_5ghz; | ||
3152 | else if (dev->phy.rev == 4) | ||
3153 | table = b43_ntab_tx_gain_rev4_5ghz; | ||
3154 | else | ||
3155 | table = b43_ntab_tx_gain_rev5plus_5ghz; | ||
3156 | } else { | ||
3157 | table = b43_ntab_tx_gain_rev3plus_2ghz; | ||
3158 | } | ||
3159 | } | ||
3160 | |||
3161 | target.ipa[i] = (table[index[i]] >> 16) & 0xF; | 3489 | target.ipa[i] = (table[index[i]] >> 16) & 0xF; |
3162 | target.pad[i] = (table[index[i]] >> 20) & 0xF; | 3490 | target.pad[i] = (table[index[i]] >> 20) & 0xF; |
3163 | target.pga[i] = (table[index[i]] >> 24) & 0xF; | 3491 | target.pga[i] = (table[index[i]] >> 24) & 0xF; |
3164 | target.txgm[i] = (table[index[i]] >> 28) & 0xF; | 3492 | target.txgm[i] = (table[index[i]] >> 28) & 0xF; |
3165 | } else { | 3493 | } else { |
3166 | table = b43_ntab_tx_gain_rev0_1_2; | ||
3167 | |||
3168 | target.ipa[i] = (table[index[i]] >> 16) & 0x3; | 3494 | target.ipa[i] = (table[index[i]] >> 16) & 0x3; |
3169 | target.pad[i] = (table[index[i]] >> 18) & 0x3; | 3495 | target.pad[i] = (table[index[i]] >> 18) & 0x3; |
3170 | target.pga[i] = (table[index[i]] >> 20) & 0x7; | 3496 | target.pga[i] = (table[index[i]] >> 20) & 0x7; |
@@ -3968,13 +4294,10 @@ static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init) | |||
3968 | #endif | 4294 | #endif |
3969 | } | 4295 | } |
3970 | 4296 | ||
3971 | b43_write32(dev, B43_MMIO_MACCTL, | 4297 | b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0); |
3972 | b43_read32(dev, B43_MMIO_MACCTL) & | 4298 | b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, 0xFC00); |
3973 | ~B43_MACCTL_GPOUTSMSK); | 4299 | b43_maskset16(dev, B43_MMIO_GPIO_CONTROL, (~0xFC00 & 0xFFFF), |
3974 | b43_write16(dev, B43_MMIO_GPIO_MASK, | 4300 | 0); |
3975 | b43_read16(dev, B43_MMIO_GPIO_MASK) | 0xFC00); | ||
3976 | b43_write16(dev, B43_MMIO_GPIO_CONTROL, | ||
3977 | b43_read16(dev, B43_MMIO_GPIO_CONTROL) & ~0xFC00); | ||
3978 | 4301 | ||
3979 | if (init) { | 4302 | if (init) { |
3980 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); | 4303 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); |
@@ -4110,7 +4433,7 @@ int b43_phy_initn(struct b43_wldev *dev) | |||
4110 | b43_nphy_tx_power_ctrl(dev, false); | 4433 | b43_nphy_tx_power_ctrl(dev, false); |
4111 | b43_nphy_tx_power_fix(dev); | 4434 | b43_nphy_tx_power_fix(dev); |
4112 | b43_nphy_tx_power_ctl_idle_tssi(dev); | 4435 | b43_nphy_tx_power_ctl_idle_tssi(dev); |
4113 | /* TODO N PHY TX Power Control Setup */ | 4436 | b43_nphy_tx_power_ctl_setup(dev); |
4114 | b43_nphy_tx_gain_table_upload(dev); | 4437 | b43_nphy_tx_gain_table_upload(dev); |
4115 | 4438 | ||
4116 | if (nphy->phyrxchain != 3) | 4439 | if (nphy->phyrxchain != 3) |
@@ -4530,8 +4853,7 @@ static void b43_nphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask, | |||
4530 | { | 4853 | { |
4531 | check_phyreg(dev, reg); | 4854 | check_phyreg(dev, reg); |
4532 | b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); | 4855 | b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); |
4533 | b43_write16(dev, B43_MMIO_PHY_DATA, | 4856 | b43_maskset16(dev, B43_MMIO_PHY_DATA, mask, set); |
4534 | (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set); | ||
4535 | } | 4857 | } |
4536 | 4858 | ||
4537 | static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg) | 4859 | static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg) |