diff options
author | Gábor Stefanik <netrolller.3d@gmail.com> | 2009-08-13 18:15:17 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-08-20 11:35:51 -0400 |
commit | 1e711bee566e26f03e51d5a754e7c8a57e489f9f (patch) | |
tree | 963d8d7665d39426b0e2c1f6b6e6d5ca912520c7 /drivers/net | |
parent | 588f8377c5470fab611c14ead768f7f9af87da94 (diff) |
b43: LP-PHY: Implement channel switching for rev0/1/B2062 radio
-Move pdiv from lpphy_2062_init to struct b43_phy_lp.
-Add channel table for the B2062 radio.
-Add code for tuning the B2062 radio to channel.
-Add error handling to op_switch_channel, and use it for both radios.
Rev0/1/B2062 will now hopefully show some signs of life, though
it won't work at full performance, as calibration is still missing.
Signed-off-by: Gábor Stefanik <netrolller.3d@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/b43/phy_lp.c | 297 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_lp.h | 2 |
2 files changed, 284 insertions, 15 deletions
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 86da8281d929..e010268b9879 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c | |||
@@ -455,8 +455,9 @@ struct b2062_freqdata { | |||
455 | /* Initialize the 2062 radio. */ | 455 | /* Initialize the 2062 radio. */ |
456 | static void lpphy_2062_init(struct b43_wldev *dev) | 456 | static void lpphy_2062_init(struct b43_wldev *dev) |
457 | { | 457 | { |
458 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
458 | struct ssb_bus *bus = dev->dev->bus; | 459 | struct ssb_bus *bus = dev->dev->bus; |
459 | u32 crystalfreq, pdiv, tmp, ref; | 460 | u32 crystalfreq, tmp, ref; |
460 | unsigned int i; | 461 | unsigned int i; |
461 | const struct b2062_freqdata *fd = NULL; | 462 | const struct b2062_freqdata *fd = NULL; |
462 | 463 | ||
@@ -496,22 +497,24 @@ static void lpphy_2062_init(struct b43_wldev *dev) | |||
496 | B43_WARN_ON(crystalfreq == 0); | 497 | B43_WARN_ON(crystalfreq == 0); |
497 | 498 | ||
498 | if (crystalfreq >= 30000000) { | 499 | if (crystalfreq >= 30000000) { |
499 | pdiv = 1; | 500 | lpphy->pdiv = 1; |
500 | b43_radio_mask(dev, B2062_S_RFPLL_CTL1, 0xFFFB); | 501 | b43_radio_mask(dev, B2062_S_RFPLL_CTL1, 0xFFFB); |
501 | } else { | 502 | } else { |
502 | pdiv = 2; | 503 | lpphy->pdiv = 2; |
503 | b43_radio_set(dev, B2062_S_RFPLL_CTL1, 0x4); | 504 | b43_radio_set(dev, B2062_S_RFPLL_CTL1, 0x4); |
504 | } | 505 | } |
505 | 506 | ||
506 | tmp = (800000000 * pdiv + crystalfreq) / (32000000 * pdiv); | 507 | tmp = (800000000 * lpphy->pdiv + crystalfreq) / |
508 | (32000000 * lpphy->pdiv); | ||
507 | tmp = (tmp - 1) & 0xFF; | 509 | tmp = (tmp - 1) & 0xFF; |
508 | b43_radio_write(dev, B2062_S_RFPLL_CTL18, tmp); | 510 | b43_radio_write(dev, B2062_S_RFPLL_CTL18, tmp); |
509 | 511 | ||
510 | tmp = (2 * crystalfreq + 1000000 * pdiv) / (2000000 * pdiv); | 512 | tmp = (2 * crystalfreq + 1000000 * lpphy->pdiv) / |
513 | (2000000 * lpphy->pdiv); | ||
511 | tmp = ((tmp & 0xFF) - 1) & 0xFFFF; | 514 | tmp = ((tmp & 0xFF) - 1) & 0xFFFF; |
512 | b43_radio_write(dev, B2062_S_RFPLL_CTL19, tmp); | 515 | b43_radio_write(dev, B2062_S_RFPLL_CTL19, tmp); |
513 | 516 | ||
514 | ref = (1000 * pdiv + 2 * crystalfreq) / (2000 * pdiv); | 517 | ref = (1000 * lpphy->pdiv + 2 * crystalfreq) / (2000 * lpphy->pdiv); |
515 | ref &= 0xFFFF; | 518 | ref &= 0xFFFF; |
516 | for (i = 0; i < ARRAY_SIZE(freqdata_tab); i++) { | 519 | for (i = 0; i < ARRAY_SIZE(freqdata_tab); i++) { |
517 | if (ref < freqdata_tab[i].freq) { | 520 | if (ref < freqdata_tab[i].freq) { |
@@ -1431,6 +1434,162 @@ struct b206x_channel { | |||
1431 | u8 data[12]; | 1434 | u8 data[12]; |
1432 | }; | 1435 | }; |
1433 | 1436 | ||
1437 | static const struct b206x_channel b2062_chantbl[] = { | ||
1438 | { .channel = 1, .freq = 2412, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1439 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1440 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1441 | { .channel = 2, .freq = 2417, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1442 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1443 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1444 | { .channel = 3, .freq = 2422, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1445 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1446 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1447 | { .channel = 4, .freq = 2427, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1448 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1449 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1450 | { .channel = 5, .freq = 2432, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1451 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1452 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1453 | { .channel = 6, .freq = 2437, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1454 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1455 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1456 | { .channel = 7, .freq = 2442, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1457 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1458 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1459 | { .channel = 8, .freq = 2447, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1460 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1461 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1462 | { .channel = 9, .freq = 2452, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1463 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1464 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1465 | { .channel = 10, .freq = 2457, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1466 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1467 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1468 | { .channel = 11, .freq = 2462, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1469 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1470 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1471 | { .channel = 12, .freq = 2467, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1472 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1473 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1474 | { .channel = 13, .freq = 2472, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1475 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1476 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1477 | { .channel = 14, .freq = 2484, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1478 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1479 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1480 | { .channel = 34, .freq = 5170, .data[0] = 0x00, .data[1] = 0x22, | ||
1481 | .data[2] = 0x20, .data[3] = 0x84, .data[4] = 0x3C, .data[5] = 0x77, | ||
1482 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1483 | { .channel = 38, .freq = 5190, .data[0] = 0x00, .data[1] = 0x11, | ||
1484 | .data[2] = 0x10, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, | ||
1485 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1486 | { .channel = 42, .freq = 5210, .data[0] = 0x00, .data[1] = 0x11, | ||
1487 | .data[2] = 0x10, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, | ||
1488 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1489 | { .channel = 46, .freq = 5230, .data[0] = 0x00, .data[1] = 0x00, | ||
1490 | .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, | ||
1491 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1492 | { .channel = 36, .freq = 5180, .data[0] = 0x00, .data[1] = 0x11, | ||
1493 | .data[2] = 0x20, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, | ||
1494 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1495 | { .channel = 40, .freq = 5200, .data[0] = 0x00, .data[1] = 0x11, | ||
1496 | .data[2] = 0x10, .data[3] = 0x84, .data[4] = 0x3C, .data[5] = 0x77, | ||
1497 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1498 | { .channel = 44, .freq = 5220, .data[0] = 0x00, .data[1] = 0x11, | ||
1499 | .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, | ||
1500 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1501 | { .channel = 48, .freq = 5240, .data[0] = 0x00, .data[1] = 0x00, | ||
1502 | .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, | ||
1503 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1504 | { .channel = 52, .freq = 5260, .data[0] = 0x00, .data[1] = 0x00, | ||
1505 | .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, | ||
1506 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1507 | { .channel = 56, .freq = 5280, .data[0] = 0x00, .data[1] = 0x00, | ||
1508 | .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, | ||
1509 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1510 | { .channel = 60, .freq = 5300, .data[0] = 0x00, .data[1] = 0x00, | ||
1511 | .data[2] = 0x00, .data[3] = 0x63, .data[4] = 0x3C, .data[5] = 0x77, | ||
1512 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1513 | { .channel = 64, .freq = 5320, .data[0] = 0x00, .data[1] = 0x00, | ||
1514 | .data[2] = 0x00, .data[3] = 0x62, .data[4] = 0x3C, .data[5] = 0x77, | ||
1515 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1516 | { .channel = 100, .freq = 5500, .data[0] = 0x00, .data[1] = 0x00, | ||
1517 | .data[2] = 0x00, .data[3] = 0x30, .data[4] = 0x3C, .data[5] = 0x77, | ||
1518 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1519 | { .channel = 104, .freq = 5520, .data[0] = 0x00, .data[1] = 0x00, | ||
1520 | .data[2] = 0x00, .data[3] = 0x20, .data[4] = 0x3C, .data[5] = 0x77, | ||
1521 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1522 | { .channel = 108, .freq = 5540, .data[0] = 0x00, .data[1] = 0x00, | ||
1523 | .data[2] = 0x00, .data[3] = 0x20, .data[4] = 0x3C, .data[5] = 0x77, | ||
1524 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1525 | { .channel = 112, .freq = 5560, .data[0] = 0x00, .data[1] = 0x00, | ||
1526 | .data[2] = 0x00, .data[3] = 0x20, .data[4] = 0x3C, .data[5] = 0x77, | ||
1527 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1528 | { .channel = 116, .freq = 5580, .data[0] = 0x00, .data[1] = 0x00, | ||
1529 | .data[2] = 0x00, .data[3] = 0x10, .data[4] = 0x3C, .data[5] = 0x77, | ||
1530 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1531 | { .channel = 120, .freq = 5600, .data[0] = 0x00, .data[1] = 0x00, | ||
1532 | .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, | ||
1533 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1534 | { .channel = 124, .freq = 5620, .data[0] = 0x00, .data[1] = 0x00, | ||
1535 | .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, | ||
1536 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1537 | { .channel = 128, .freq = 5640, .data[0] = 0x00, .data[1] = 0x00, | ||
1538 | .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, | ||
1539 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1540 | { .channel = 132, .freq = 5660, .data[0] = 0x00, .data[1] = 0x00, | ||
1541 | .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, | ||
1542 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1543 | { .channel = 136, .freq = 5680, .data[0] = 0x00, .data[1] = 0x00, | ||
1544 | .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, | ||
1545 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1546 | { .channel = 140, .freq = 5700, .data[0] = 0x00, .data[1] = 0x00, | ||
1547 | .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, | ||
1548 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1549 | { .channel = 149, .freq = 5745, .data[0] = 0x00, .data[1] = 0x00, | ||
1550 | .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, | ||
1551 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1552 | { .channel = 153, .freq = 5765, .data[0] = 0x00, .data[1] = 0x00, | ||
1553 | .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, | ||
1554 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1555 | { .channel = 157, .freq = 5785, .data[0] = 0x00, .data[1] = 0x00, | ||
1556 | .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, | ||
1557 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1558 | { .channel = 161, .freq = 5805, .data[0] = 0x00, .data[1] = 0x00, | ||
1559 | .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, | ||
1560 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1561 | { .channel = 165, .freq = 5825, .data[0] = 0x00, .data[1] = 0x00, | ||
1562 | .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, | ||
1563 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1564 | { .channel = 184, .freq = 4920, .data[0] = 0x55, .data[1] = 0x77, | ||
1565 | .data[2] = 0x90, .data[3] = 0xF7, .data[4] = 0x3C, .data[5] = 0x77, | ||
1566 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, | ||
1567 | { .channel = 188, .freq = 4940, .data[0] = 0x44, .data[1] = 0x77, | ||
1568 | .data[2] = 0x80, .data[3] = 0xE7, .data[4] = 0x3C, .data[5] = 0x77, | ||
1569 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, | ||
1570 | { .channel = 192, .freq = 4960, .data[0] = 0x44, .data[1] = 0x66, | ||
1571 | .data[2] = 0x80, .data[3] = 0xE7, .data[4] = 0x3C, .data[5] = 0x77, | ||
1572 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, | ||
1573 | { .channel = 196, .freq = 4980, .data[0] = 0x33, .data[1] = 0x66, | ||
1574 | .data[2] = 0x70, .data[3] = 0xC7, .data[4] = 0x3C, .data[5] = 0x77, | ||
1575 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, | ||
1576 | { .channel = 200, .freq = 5000, .data[0] = 0x22, .data[1] = 0x55, | ||
1577 | .data[2] = 0x60, .data[3] = 0xD7, .data[4] = 0x3C, .data[5] = 0x77, | ||
1578 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, | ||
1579 | { .channel = 204, .freq = 5020, .data[0] = 0x22, .data[1] = 0x55, | ||
1580 | .data[2] = 0x60, .data[3] = 0xC7, .data[4] = 0x3C, .data[5] = 0x77, | ||
1581 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, | ||
1582 | { .channel = 208, .freq = 5040, .data[0] = 0x22, .data[1] = 0x44, | ||
1583 | .data[2] = 0x50, .data[3] = 0xC7, .data[4] = 0x3C, .data[5] = 0x77, | ||
1584 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, | ||
1585 | { .channel = 212, .freq = 5060, .data[0] = 0x11, .data[1] = 0x44, | ||
1586 | .data[2] = 0x50, .data[3] = 0xA5, .data[4] = 0x3C, .data[5] = 0x77, | ||
1587 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1588 | { .channel = 216, .freq = 5080, .data[0] = 0x00, .data[1] = 0x44, | ||
1589 | .data[2] = 0x40, .data[3] = 0xB6, .data[4] = 0x3C, .data[5] = 0x77, | ||
1590 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1591 | }; | ||
1592 | |||
1434 | static const struct b206x_channel b2063_chantbl[] = { | 1593 | static const struct b206x_channel b2063_chantbl[] = { |
1435 | { .channel = 1, .freq = 2412, .data[0] = 0x6F, .data[1] = 0x3C, | 1594 | { .channel = 1, .freq = 2412, .data[0] = 0x6F, .data[1] = 0x3C, |
1436 | .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, | 1595 | .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, |
@@ -1638,10 +1797,110 @@ static const struct b206x_channel b2063_chantbl[] = { | |||
1638 | .data[10] = 0x40, .data[11] = 0x00, }, | 1797 | .data[10] = 0x40, .data[11] = 0x00, }, |
1639 | }; | 1798 | }; |
1640 | 1799 | ||
1641 | static void lpphy_b2062_tune(struct b43_wldev *dev, | 1800 | static void lpphy_b2062_reset_pll_bias(struct b43_wldev *dev) |
1642 | unsigned int channel) | ||
1643 | { | 1801 | { |
1644 | //TODO | 1802 | struct ssb_bus *bus = dev->dev->bus; |
1803 | |||
1804 | b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0xFF); | ||
1805 | udelay(20); | ||
1806 | if (bus->chip_id == 0x5354) { | ||
1807 | b43_radio_write(dev, B2062_N_COMM1, 4); | ||
1808 | b43_radio_write(dev, B2062_S_RFPLL_CTL2, 4); | ||
1809 | } else { | ||
1810 | b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0); | ||
1811 | } | ||
1812 | udelay(5); | ||
1813 | } | ||
1814 | |||
1815 | static void lpphy_b2062_vco_calib(struct b43_wldev *dev) | ||
1816 | { | ||
1817 | b43_phy_write(dev, B2062_S_RFPLL_CTL21, 0x42); | ||
1818 | b43_phy_write(dev, B2062_S_RFPLL_CTL21, 0x62); | ||
1819 | udelay(200); | ||
1820 | } | ||
1821 | |||
1822 | static int lpphy_b2062_tune(struct b43_wldev *dev, | ||
1823 | unsigned int channel) | ||
1824 | { | ||
1825 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
1826 | struct ssb_bus *bus = dev->dev->bus; | ||
1827 | static const struct b206x_channel *chandata = NULL; | ||
1828 | u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000; | ||
1829 | u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9; | ||
1830 | int i, err = 0; | ||
1831 | |||
1832 | for (i = 0; i < ARRAY_SIZE(b2063_chantbl); i++) { | ||
1833 | if (b2063_chantbl[i].channel == channel) { | ||
1834 | chandata = &b2063_chantbl[i]; | ||
1835 | break; | ||
1836 | } | ||
1837 | } | ||
1838 | |||
1839 | if (B43_WARN_ON(!chandata)) | ||
1840 | return -EINVAL; | ||
1841 | |||
1842 | b43_radio_set(dev, B2062_S_RFPLL_CTL14, 0x04); | ||
1843 | b43_radio_write(dev, B2062_N_LGENA_TUNE0, chandata->data[0]); | ||
1844 | b43_radio_write(dev, B2062_N_LGENA_TUNE2, chandata->data[1]); | ||
1845 | b43_radio_write(dev, B2062_N_LGENA_TUNE3, chandata->data[2]); | ||
1846 | b43_radio_write(dev, B2062_N_TX_TUNE, chandata->data[3]); | ||
1847 | b43_radio_write(dev, B2062_S_LGENG_CTL1, chandata->data[4]); | ||
1848 | b43_radio_write(dev, B2062_N_LGENA_CTL5, chandata->data[5]); | ||
1849 | b43_radio_write(dev, B2062_N_LGENA_CTL6, chandata->data[6]); | ||
1850 | b43_radio_write(dev, B2062_N_TX_PGA, chandata->data[7]); | ||
1851 | b43_radio_write(dev, B2062_N_TX_PAD, chandata->data[8]); | ||
1852 | |||
1853 | tmp1 = crystal_freq / 1000; | ||
1854 | tmp2 = lpphy->pdiv * 1000; | ||
1855 | b43_radio_write(dev, B2062_S_RFPLL_CTL33, 0xCC); | ||
1856 | b43_radio_write(dev, B2062_S_RFPLL_CTL34, 0x07); | ||
1857 | lpphy_b2062_reset_pll_bias(dev); | ||
1858 | tmp3 = tmp2 * channel2freq_lp(channel); | ||
1859 | if (channel2freq_lp(channel) < 4000) | ||
1860 | tmp3 *= 2; | ||
1861 | tmp4 = 48 * tmp1; | ||
1862 | tmp6 = tmp3 / tmp4; | ||
1863 | tmp7 = tmp3 % tmp4; | ||
1864 | b43_radio_write(dev, B2062_S_RFPLL_CTL26, tmp6); | ||
1865 | tmp5 = tmp7 * 0x100; | ||
1866 | tmp6 = tmp5 / tmp4; | ||
1867 | tmp7 = tmp5 % tmp4; | ||
1868 | b43_radio_write(dev, B2062_S_RFPLL_CTL28, tmp6); | ||
1869 | tmp5 = tmp7 * 0x100; | ||
1870 | tmp6 = tmp5 / tmp4; | ||
1871 | tmp7 = tmp5 % tmp4; | ||
1872 | b43_radio_write(dev, B2062_S_RFPLL_CTL29, tmp6 + ((2 * tmp7) / tmp4)); | ||
1873 | tmp8 = b43_phy_read(dev, B2062_S_RFPLL_CTL19); | ||
1874 | tmp9 = ((2 * tmp3 * (tmp8 + 1)) + (3 * tmp1)) / (6 * tmp1); | ||
1875 | b43_radio_write(dev, B2062_S_RFPLL_CTL23, tmp9 >> 8); | ||
1876 | b43_radio_write(dev, B2062_S_RFPLL_CTL24, tmp9 & 0xFF); | ||
1877 | |||
1878 | lpphy_b2062_vco_calib(dev); | ||
1879 | if (b43_radio_read(dev, B2062_S_RFPLL_CTL3) & 0x10) { | ||
1880 | b43_radio_write(dev, B2062_S_RFPLL_CTL33, 0xFC); | ||
1881 | b43_radio_write(dev, B2062_S_RFPLL_CTL34, 0); | ||
1882 | lpphy_b2062_reset_pll_bias(dev); | ||
1883 | lpphy_b2062_vco_calib(dev); | ||
1884 | if (b43_radio_read(dev, B2062_S_RFPLL_CTL3) & 0x10) | ||
1885 | err = -EINVAL; | ||
1886 | } | ||
1887 | |||
1888 | b43_radio_mask(dev, B2062_S_RFPLL_CTL14, ~0x04); | ||
1889 | return err; | ||
1890 | } | ||
1891 | |||
1892 | static void lpphy_japan_filter(struct b43_wldev *dev, int channel) | ||
1893 | { | ||
1894 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
1895 | u16 tmp = (channel == 14); //SPEC FIXME check japanwidefilter! | ||
1896 | |||
1897 | if (dev->phy.rev < 2) { //SPEC FIXME Isn't this rev0/1-specific? | ||
1898 | b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFCFF, tmp << 9); | ||
1899 | if ((dev->phy.rev == 1) && (lpphy->rc_cap)) | ||
1900 | lpphy_set_rc_cap(dev); | ||
1901 | } else { | ||
1902 | b43_radio_write(dev, B2063_TX_BB_SP3, 0x3F); | ||
1903 | } | ||
1645 | } | 1904 | } |
1646 | 1905 | ||
1647 | static void lpphy_b2063_vco_calib(struct b43_wldev *dev) | 1906 | static void lpphy_b2063_vco_calib(struct b43_wldev *dev) |
@@ -1661,8 +1920,8 @@ static void lpphy_b2063_vco_calib(struct b43_wldev *dev) | |||
1661 | b43_phy_set(dev, B2063_PLL_SP1, 0x40); | 1920 | b43_phy_set(dev, B2063_PLL_SP1, 0x40); |
1662 | } | 1921 | } |
1663 | 1922 | ||
1664 | static void lpphy_b2063_tune(struct b43_wldev *dev, | 1923 | static int lpphy_b2063_tune(struct b43_wldev *dev, |
1665 | unsigned int channel) | 1924 | unsigned int channel) |
1666 | { | 1925 | { |
1667 | struct ssb_bus *bus = dev->dev->bus; | 1926 | struct ssb_bus *bus = dev->dev->bus; |
1668 | 1927 | ||
@@ -1681,7 +1940,7 @@ static void lpphy_b2063_tune(struct b43_wldev *dev, | |||
1681 | } | 1940 | } |
1682 | 1941 | ||
1683 | if (B43_WARN_ON(!chandata)) | 1942 | if (B43_WARN_ON(!chandata)) |
1684 | return; | 1943 | return -EINVAL; |
1685 | 1944 | ||
1686 | b43_radio_write(dev, B2063_LOGEN_VCOBUF1, chandata->data[0]); | 1945 | b43_radio_write(dev, B2063_LOGEN_VCOBUF1, chandata->data[0]); |
1687 | b43_radio_write(dev, B2063_LOGEN_MIXER2, chandata->data[1]); | 1946 | b43_radio_write(dev, B2063_LOGEN_MIXER2, chandata->data[1]); |
@@ -1780,18 +2039,26 @@ static void lpphy_b2063_tune(struct b43_wldev *dev, | |||
1780 | b43_phy_mask(dev, B2063_PLL_SP2, 0xFFFC); | 2039 | b43_phy_mask(dev, B2063_PLL_SP2, 0xFFFC); |
1781 | lpphy_b2063_vco_calib(dev); | 2040 | lpphy_b2063_vco_calib(dev); |
1782 | b43_radio_write(dev, B2063_COMM15, old_comm15); | 2041 | b43_radio_write(dev, B2063_COMM15, old_comm15); |
2042 | |||
2043 | return 0; | ||
1783 | } | 2044 | } |
1784 | 2045 | ||
1785 | static int b43_lpphy_op_switch_channel(struct b43_wldev *dev, | 2046 | static int b43_lpphy_op_switch_channel(struct b43_wldev *dev, |
1786 | unsigned int new_channel) | 2047 | unsigned int new_channel) |
1787 | { | 2048 | { |
2049 | int err; | ||
2050 | |||
1788 | b43_write16(dev, B43_MMIO_CHANNEL, new_channel); | 2051 | b43_write16(dev, B43_MMIO_CHANNEL, new_channel); |
1789 | 2052 | ||
1790 | if (dev->phy.radio_ver == 0x2063) { | 2053 | if (dev->phy.radio_ver == 0x2063) { |
1791 | lpphy_b2063_tune(dev, new_channel); | 2054 | err = lpphy_b2063_tune(dev, new_channel); |
2055 | if (err) | ||
2056 | return err; | ||
1792 | } else { | 2057 | } else { |
1793 | lpphy_b2062_tune(dev, new_channel); | 2058 | err = lpphy_b2062_tune(dev, new_channel); |
1794 | //TODO Japan filter | 2059 | if (err) |
2060 | return err; | ||
2061 | lpphy_japan_filter(dev, new_channel); | ||
1795 | } | 2062 | } |
1796 | 2063 | ||
1797 | lpphy_adjust_gain_table(dev, channel2freq_lp(new_channel)); | 2064 | lpphy_adjust_gain_table(dev, channel2freq_lp(new_channel)); |
diff --git a/drivers/net/wireless/b43/phy_lp.h b/drivers/net/wireless/b43/phy_lp.h index 4eab760ac619..99cb0386e345 100644 --- a/drivers/net/wireless/b43/phy_lp.h +++ b/drivers/net/wireless/b43/phy_lp.h | |||
@@ -884,6 +884,8 @@ struct b43_phy_lp { | |||
884 | 884 | ||
885 | /* Used for "Save/Restore Dig Filt State" */ | 885 | /* Used for "Save/Restore Dig Filt State" */ |
886 | u16 dig_flt_state[9]; | 886 | u16 dig_flt_state[9]; |
887 | |||
888 | unsigned int pdiv; | ||
887 | }; | 889 | }; |
888 | 890 | ||
889 | enum tssi_mux_mode { | 891 | enum tssi_mux_mode { |