aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43/phy_lp.c
diff options
context:
space:
mode:
authorGábor Stefanik <netrolller.3d@gmail.com>2009-08-13 16:46:30 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-20 11:35:50 -0400
commit588f8377c5470fab611c14ead768f7f9af87da94 (patch)
tree5bf7814511759cae41f4984409d8e743dc949678 /drivers/net/wireless/b43/phy_lp.c
parent6f632d57f35303118685b88c139f3da73df077e2 (diff)
b43: LP-PHY: Implement channel switching for rev2+/B2063 radio
Rev.2+/B2063 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/wireless/b43/phy_lp.c')
-rw-r--r--drivers/net/wireless/b43/phy_lp.c424
1 files changed, 402 insertions, 22 deletions
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index 996b7eccfaf8..86da8281d929 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -29,6 +29,25 @@
29#include "tables_lpphy.h" 29#include "tables_lpphy.h"
30 30
31 31
32static inline u16 channel2freq_lp(u8 channel)
33{
34 if (channel < 14)
35 return (2407 + 5 * channel);
36 else if (channel == 14)
37 return 2484;
38 else if (channel < 184)
39 return (5000 + 5 * channel);
40 else
41 return (4000 + 5 * channel);
42}
43
44static unsigned int b43_lpphy_op_get_default_chan(struct b43_wldev *dev)
45{
46 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
47 return 1;
48 return 36;
49}
50
32static int b43_lpphy_op_allocate(struct b43_wldev *dev) 51static int b43_lpphy_op_allocate(struct b43_wldev *dev)
33{ 52{
34 struct b43_phy_lp *lpphy; 53 struct b43_phy_lp *lpphy;
@@ -142,10 +161,9 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev)
142 } 161 }
143} 162}
144 163
145static void lpphy_adjust_gain_table(struct b43_wldev *dev) 164static void lpphy_adjust_gain_table(struct b43_wldev *dev, u32 freq)
146{ 165{
147 struct b43_phy_lp *lpphy = dev->phy.lp; 166 struct b43_phy_lp *lpphy = dev->phy.lp;
148 u32 freq = dev->wl->hw->conf.channel->center_freq;
149 u16 temp[3]; 167 u16 temp[3];
150 u16 isolation; 168 u16 isolation;
151 169
@@ -170,6 +188,8 @@ static void lpphy_adjust_gain_table(struct b43_wldev *dev)
170 188
171static void lpphy_table_init(struct b43_wldev *dev) 189static void lpphy_table_init(struct b43_wldev *dev)
172{ 190{
191 u32 freq = channel2freq_lp(b43_lpphy_op_get_default_chan(dev));
192
173 if (dev->phy.rev < 2) 193 if (dev->phy.rev < 2)
174 lpphy_rev0_1_table_init(dev); 194 lpphy_rev0_1_table_init(dev);
175 else 195 else
@@ -178,7 +198,7 @@ static void lpphy_table_init(struct b43_wldev *dev)
178 lpphy_init_tx_gain_table(dev); 198 lpphy_init_tx_gain_table(dev);
179 199
180 if (dev->phy.rev < 2) 200 if (dev->phy.rev < 2)
181 lpphy_adjust_gain_table(dev); 201 lpphy_adjust_gain_table(dev, freq);
182} 202}
183 203
184static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) 204static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
@@ -1363,20 +1383,6 @@ static void lpphy_tx_pctl_init(struct b43_wldev *dev)
1363 } 1383 }
1364} 1384}
1365 1385
1366static int b43_lpphy_op_init(struct b43_wldev *dev)
1367{
1368 lpphy_read_band_sprom(dev); //FIXME should this be in prepare_structs?
1369 lpphy_baseband_init(dev);
1370 lpphy_radio_init(dev);
1371 lpphy_calibrate_rc(dev);
1372 //TODO set channel
1373 lpphy_tx_pctl_init(dev);
1374 lpphy_calibration(dev);
1375 //TODO ACI init
1376
1377 return 0;
1378}
1379
1380static u16 b43_lpphy_op_read(struct b43_wldev *dev, u16 reg) 1386static u16 b43_lpphy_op_read(struct b43_wldev *dev, u16 reg)
1381{ 1387{
1382 b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); 1388 b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
@@ -1419,18 +1425,392 @@ static void b43_lpphy_op_software_rfkill(struct b43_wldev *dev,
1419 //TODO 1425 //TODO
1420} 1426}
1421 1427
1428struct b206x_channel {
1429 u8 channel;
1430 u16 freq;
1431 u8 data[12];
1432};
1433
1434static const struct b206x_channel b2063_chantbl[] = {
1435 { .channel = 1, .freq = 2412, .data[0] = 0x6F, .data[1] = 0x3C,
1436 .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
1437 .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
1438 .data[10] = 0x80, .data[11] = 0x70, },
1439 { .channel = 2, .freq = 2417, .data[0] = 0x6F, .data[1] = 0x3C,
1440 .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
1441 .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
1442 .data[10] = 0x80, .data[11] = 0x70, },
1443 { .channel = 3, .freq = 2422, .data[0] = 0x6F, .data[1] = 0x3C,
1444 .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
1445 .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
1446 .data[10] = 0x80, .data[11] = 0x70, },
1447 { .channel = 4, .freq = 2427, .data[0] = 0x6F, .data[1] = 0x2C,
1448 .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
1449 .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
1450 .data[10] = 0x80, .data[11] = 0x70, },
1451 { .channel = 5, .freq = 2432, .data[0] = 0x6F, .data[1] = 0x2C,
1452 .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
1453 .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
1454 .data[10] = 0x80, .data[11] = 0x70, },
1455 { .channel = 6, .freq = 2437, .data[0] = 0x6F, .data[1] = 0x2C,
1456 .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
1457 .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
1458 .data[10] = 0x80, .data[11] = 0x70, },
1459 { .channel = 7, .freq = 2442, .data[0] = 0x6F, .data[1] = 0x2C,
1460 .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
1461 .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
1462 .data[10] = 0x80, .data[11] = 0x70, },
1463 { .channel = 8, .freq = 2447, .data[0] = 0x6F, .data[1] = 0x2C,
1464 .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
1465 .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
1466 .data[10] = 0x80, .data[11] = 0x70, },
1467 { .channel = 9, .freq = 2452, .data[0] = 0x6F, .data[1] = 0x1C,
1468 .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
1469 .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
1470 .data[10] = 0x80, .data[11] = 0x70, },
1471 { .channel = 10, .freq = 2457, .data[0] = 0x6F, .data[1] = 0x1C,
1472 .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
1473 .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
1474 .data[10] = 0x80, .data[11] = 0x70, },
1475 { .channel = 11, .freq = 2462, .data[0] = 0x6E, .data[1] = 0x1C,
1476 .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
1477 .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
1478 .data[10] = 0x80, .data[11] = 0x70, },
1479 { .channel = 12, .freq = 2467, .data[0] = 0x6E, .data[1] = 0x1C,
1480 .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
1481 .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
1482 .data[10] = 0x80, .data[11] = 0x70, },
1483 { .channel = 13, .freq = 2472, .data[0] = 0x6E, .data[1] = 0x1C,
1484 .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
1485 .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
1486 .data[10] = 0x80, .data[11] = 0x70, },
1487 { .channel = 14, .freq = 2484, .data[0] = 0x6E, .data[1] = 0x0C,
1488 .data[2] = 0x0C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
1489 .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
1490 .data[10] = 0x80, .data[11] = 0x70, },
1491 { .channel = 34, .freq = 5170, .data[0] = 0x6A, .data[1] = 0x0C,
1492 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x02, .data[5] = 0x05,
1493 .data[6] = 0x0D, .data[7] = 0x0D, .data[8] = 0x77, .data[9] = 0x80,
1494 .data[10] = 0x20, .data[11] = 0x00, },
1495 { .channel = 36, .freq = 5180, .data[0] = 0x6A, .data[1] = 0x0C,
1496 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x05,
1497 .data[6] = 0x0D, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x80,
1498 .data[10] = 0x20, .data[11] = 0x00, },
1499 { .channel = 38, .freq = 5190, .data[0] = 0x6A, .data[1] = 0x0C,
1500 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x04,
1501 .data[6] = 0x0C, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x80,
1502 .data[10] = 0x20, .data[11] = 0x00, },
1503 { .channel = 40, .freq = 5200, .data[0] = 0x69, .data[1] = 0x0C,
1504 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x04,
1505 .data[6] = 0x0C, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x70,
1506 .data[10] = 0x20, .data[11] = 0x00, },
1507 { .channel = 42, .freq = 5210, .data[0] = 0x69, .data[1] = 0x0C,
1508 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x04,
1509 .data[6] = 0x0B, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x70,
1510 .data[10] = 0x20, .data[11] = 0x00, },
1511 { .channel = 44, .freq = 5220, .data[0] = 0x69, .data[1] = 0x0C,
1512 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x04,
1513 .data[6] = 0x0B, .data[7] = 0x0B, .data[8] = 0x77, .data[9] = 0x60,
1514 .data[10] = 0x20, .data[11] = 0x00, },
1515 { .channel = 46, .freq = 5230, .data[0] = 0x69, .data[1] = 0x0C,
1516 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x03,
1517 .data[6] = 0x0A, .data[7] = 0x0B, .data[8] = 0x77, .data[9] = 0x60,
1518 .data[10] = 0x20, .data[11] = 0x00, },
1519 { .channel = 48, .freq = 5240, .data[0] = 0x69, .data[1] = 0x0C,
1520 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x03,
1521 .data[6] = 0x0A, .data[7] = 0x0A, .data[8] = 0x77, .data[9] = 0x60,
1522 .data[10] = 0x20, .data[11] = 0x00, },
1523 { .channel = 52, .freq = 5260, .data[0] = 0x68, .data[1] = 0x0C,
1524 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x02,
1525 .data[6] = 0x09, .data[7] = 0x09, .data[8] = 0x77, .data[9] = 0x60,
1526 .data[10] = 0x20, .data[11] = 0x00, },
1527 { .channel = 56, .freq = 5280, .data[0] = 0x68, .data[1] = 0x0C,
1528 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x01,
1529 .data[6] = 0x08, .data[7] = 0x08, .data[8] = 0x77, .data[9] = 0x50,
1530 .data[10] = 0x10, .data[11] = 0x00, },
1531 { .channel = 60, .freq = 5300, .data[0] = 0x68, .data[1] = 0x0C,
1532 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x01,
1533 .data[6] = 0x08, .data[7] = 0x08, .data[8] = 0x77, .data[9] = 0x50,
1534 .data[10] = 0x10, .data[11] = 0x00, },
1535 { .channel = 64, .freq = 5320, .data[0] = 0x67, .data[1] = 0x0C,
1536 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
1537 .data[6] = 0x08, .data[7] = 0x08, .data[8] = 0x77, .data[9] = 0x50,
1538 .data[10] = 0x10, .data[11] = 0x00, },
1539 { .channel = 100, .freq = 5500, .data[0] = 0x64, .data[1] = 0x0C,
1540 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
1541 .data[6] = 0x02, .data[7] = 0x01, .data[8] = 0x77, .data[9] = 0x20,
1542 .data[10] = 0x00, .data[11] = 0x00, },
1543 { .channel = 104, .freq = 5520, .data[0] = 0x64, .data[1] = 0x0C,
1544 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
1545 .data[6] = 0x01, .data[7] = 0x01, .data[8] = 0x77, .data[9] = 0x20,
1546 .data[10] = 0x00, .data[11] = 0x00, },
1547 { .channel = 108, .freq = 5540, .data[0] = 0x63, .data[1] = 0x0C,
1548 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
1549 .data[6] = 0x01, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x10,
1550 .data[10] = 0x00, .data[11] = 0x00, },
1551 { .channel = 112, .freq = 5560, .data[0] = 0x63, .data[1] = 0x0C,
1552 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
1553 .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x10,
1554 .data[10] = 0x00, .data[11] = 0x00, },
1555 { .channel = 116, .freq = 5580, .data[0] = 0x62, .data[1] = 0x0C,
1556 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
1557 .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x10,
1558 .data[10] = 0x00, .data[11] = 0x00, },
1559 { .channel = 120, .freq = 5600, .data[0] = 0x62, .data[1] = 0x0C,
1560 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
1561 .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
1562 .data[10] = 0x00, .data[11] = 0x00, },
1563 { .channel = 124, .freq = 5620, .data[0] = 0x62, .data[1] = 0x0C,
1564 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
1565 .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
1566 .data[10] = 0x00, .data[11] = 0x00, },
1567 { .channel = 128, .freq = 5640, .data[0] = 0x61, .data[1] = 0x0C,
1568 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
1569 .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
1570 .data[10] = 0x00, .data[11] = 0x00, },
1571 { .channel = 132, .freq = 5660, .data[0] = 0x61, .data[1] = 0x0C,
1572 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
1573 .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
1574 .data[10] = 0x00, .data[11] = 0x00, },
1575 { .channel = 136, .freq = 5680, .data[0] = 0x61, .data[1] = 0x0C,
1576 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
1577 .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
1578 .data[10] = 0x00, .data[11] = 0x00, },
1579 { .channel = 140, .freq = 5700, .data[0] = 0x60, .data[1] = 0x0C,
1580 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
1581 .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
1582 .data[10] = 0x00, .data[11] = 0x00, },
1583 { .channel = 149, .freq = 5745, .data[0] = 0x60, .data[1] = 0x0C,
1584 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
1585 .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
1586 .data[10] = 0x00, .data[11] = 0x00, },
1587 { .channel = 153, .freq = 5765, .data[0] = 0x60, .data[1] = 0x0C,
1588 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
1589 .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
1590 .data[10] = 0x00, .data[11] = 0x00, },
1591 { .channel = 157, .freq = 5785, .data[0] = 0x60, .data[1] = 0x0C,
1592 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
1593 .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
1594 .data[10] = 0x00, .data[11] = 0x00, },
1595 { .channel = 161, .freq = 5805, .data[0] = 0x60, .data[1] = 0x0C,
1596 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
1597 .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
1598 .data[10] = 0x00, .data[11] = 0x00, },
1599 { .channel = 165, .freq = 5825, .data[0] = 0x60, .data[1] = 0x0C,
1600 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
1601 .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
1602 .data[10] = 0x00, .data[11] = 0x00, },
1603 { .channel = 184, .freq = 4920, .data[0] = 0x6E, .data[1] = 0x0C,
1604 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x09, .data[5] = 0x0E,
1605 .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xC0,
1606 .data[10] = 0x50, .data[11] = 0x00, },
1607 { .channel = 188, .freq = 4940, .data[0] = 0x6E, .data[1] = 0x0C,
1608 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x09, .data[5] = 0x0D,
1609 .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xB0,
1610 .data[10] = 0x50, .data[11] = 0x00, },
1611 { .channel = 192, .freq = 4960, .data[0] = 0x6E, .data[1] = 0x0C,
1612 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0C,
1613 .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xB0,
1614 .data[10] = 0x50, .data[11] = 0x00, },
1615 { .channel = 196, .freq = 4980, .data[0] = 0x6D, .data[1] = 0x0C,
1616 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0C,
1617 .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xA0,
1618 .data[10] = 0x40, .data[11] = 0x00, },
1619 { .channel = 200, .freq = 5000, .data[0] = 0x6D, .data[1] = 0x0C,
1620 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0B,
1621 .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xA0,
1622 .data[10] = 0x40, .data[11] = 0x00, },
1623 { .channel = 204, .freq = 5020, .data[0] = 0x6D, .data[1] = 0x0C,
1624 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0A,
1625 .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xA0,
1626 .data[10] = 0x40, .data[11] = 0x00, },
1627 { .channel = 208, .freq = 5040, .data[0] = 0x6C, .data[1] = 0x0C,
1628 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x07, .data[5] = 0x09,
1629 .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0x90,
1630 .data[10] = 0x40, .data[11] = 0x00, },
1631 { .channel = 212, .freq = 5060, .data[0] = 0x6C, .data[1] = 0x0C,
1632 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x06, .data[5] = 0x08,
1633 .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0x90,
1634 .data[10] = 0x40, .data[11] = 0x00, },
1635 { .channel = 216, .freq = 5080, .data[0] = 0x6C, .data[1] = 0x0C,
1636 .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x05, .data[5] = 0x08,
1637 .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0x90,
1638 .data[10] = 0x40, .data[11] = 0x00, },
1639};
1640
1641static void lpphy_b2062_tune(struct b43_wldev *dev,
1642 unsigned int channel)
1643{
1644 //TODO
1645}
1646
1647static void lpphy_b2063_vco_calib(struct b43_wldev *dev)
1648{
1649 u16 tmp;
1650
1651 b43_phy_mask(dev, B2063_PLL_SP1, ~0x40);
1652 tmp = b43_phy_read(dev, B2063_PLL_JTAG_CALNRST) & 0xF8;
1653 b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp);
1654 udelay(1);
1655 b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x4);
1656 udelay(1);
1657 b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x6);
1658 udelay(1);
1659 b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x7);
1660 udelay(300);
1661 b43_phy_set(dev, B2063_PLL_SP1, 0x40);
1662}
1663
1664static void lpphy_b2063_tune(struct b43_wldev *dev,
1665 unsigned int channel)
1666{
1667 struct ssb_bus *bus = dev->dev->bus;
1668
1669 static const struct b206x_channel *chandata = NULL;
1670 u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
1671 u32 freqref, vco_freq, val1, val2, val3, timeout, timeoutref, count;
1672 u16 old_comm15, scale;
1673 u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
1674 int i, div = (crystal_freq <= 26000000 ? 1 : 2);
1675
1676 for (i = 0; i < ARRAY_SIZE(b2063_chantbl); i++) {
1677 if (b2063_chantbl[i].channel == channel) {
1678 chandata = &b2063_chantbl[i];
1679 break;
1680 }
1681 }
1682
1683 if (B43_WARN_ON(!chandata))
1684 return;
1685
1686 b43_radio_write(dev, B2063_LOGEN_VCOBUF1, chandata->data[0]);
1687 b43_radio_write(dev, B2063_LOGEN_MIXER2, chandata->data[1]);
1688 b43_radio_write(dev, B2063_LOGEN_BUF2, chandata->data[2]);
1689 b43_radio_write(dev, B2063_LOGEN_RCCR1, chandata->data[3]);
1690 b43_radio_write(dev, B2063_A_RX_1ST3, chandata->data[4]);
1691 b43_radio_write(dev, B2063_A_RX_2ND1, chandata->data[5]);
1692 b43_radio_write(dev, B2063_A_RX_2ND4, chandata->data[6]);
1693 b43_radio_write(dev, B2063_A_RX_2ND7, chandata->data[7]);
1694 b43_radio_write(dev, B2063_A_RX_PS6, chandata->data[8]);
1695 b43_radio_write(dev, B2063_TX_RF_CTL2, chandata->data[9]);
1696 b43_radio_write(dev, B2063_TX_RF_CTL5, chandata->data[10]);
1697 b43_radio_write(dev, B2063_PA_CTL11, chandata->data[11]);
1698
1699 old_comm15 = b43_radio_read(dev, B2063_COMM15);
1700 b43_radio_set(dev, B2063_COMM15, 0x1E);
1701
1702 if (chandata->freq > 4000) /* spec says 2484, but 4000 is safer */
1703 vco_freq = chandata->freq << 1;
1704 else
1705 vco_freq = chandata->freq << 2;
1706
1707 freqref = crystal_freq * 3;
1708 val1 = lpphy_qdiv_roundup(crystal_freq, 1000000, 16);
1709 val2 = lpphy_qdiv_roundup(crystal_freq, 1000000 * div, 16);
1710 val3 = lpphy_qdiv_roundup(vco_freq, 3, 16);
1711 timeout = ((((8 * crystal_freq) / (div * 5000000)) + 1) >> 1) - 1;
1712 b43_radio_write(dev, B2063_PLL_JTAG_PLL_VCO_CALIB3, 0x2);
1713 b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_VCO_CALIB6,
1714 0xFFF8, timeout >> 2);
1715 b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_VCO_CALIB7,
1716 0xFF9F,timeout << 5);
1717
1718 timeoutref = ((((8 * crystal_freq) / (div * (timeout + 1))) +
1719 999999) / 1000000) + 1;
1720 b43_radio_write(dev, B2063_PLL_JTAG_PLL_VCO_CALIB5, timeoutref);
1721
1722 count = lpphy_qdiv_roundup(val3, val2 + 16, 16);
1723 count *= (timeout + 1) * (timeoutref + 1);
1724 count--;
1725 b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_VCO_CALIB7,
1726 0xF0, count >> 8);
1727 b43_radio_write(dev, B2063_PLL_JTAG_PLL_VCO_CALIB8, count & 0xFF);
1728
1729 tmp1 = ((val3 * 62500) / freqref) << 4;
1730 tmp2 = ((val3 * 62500) % freqref) << 4;
1731 while (tmp2 >= freqref) {
1732 tmp1++;
1733 tmp2 -= freqref;
1734 }
1735 b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_SG1, 0xFFE0, tmp1 >> 4);
1736 b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_SG2, 0xFE0F, tmp1 << 4);
1737 b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_SG2, 0xFFF0, tmp1 >> 16);
1738 b43_radio_write(dev, B2063_PLL_JTAG_PLL_SG3, (tmp2 >> 8) & 0xFF);
1739 b43_radio_write(dev, B2063_PLL_JTAG_PLL_SG4, tmp2 & 0xFF);
1740
1741 b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF1, 0xB9);
1742 b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF2, 0x88);
1743 b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF3, 0x28);
1744 b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF4, 0x63);
1745
1746 tmp3 = ((41 * (val3 - 3000)) /1200) + 27;
1747 tmp4 = lpphy_qdiv_roundup(132000 * tmp1, 8451, 16);
1748
1749 if ((tmp4 + tmp3 - 1) / tmp3 > 60) {
1750 scale = 1;
1751 tmp5 = ((tmp4 + tmp3) / (tmp3 << 1)) - 8;
1752 } else {
1753 scale = 0;
1754 tmp5 = ((tmp4 + (tmp3 >> 1)) / tmp3) - 8;
1755 }
1756 b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFC0, tmp5);
1757 b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFBF, scale << 6);
1758
1759 tmp6 = lpphy_qdiv_roundup(100 * val1, val3, 16);
1760 tmp6 *= (tmp5 * 8) * (scale + 1);
1761 if (tmp6 > 150)
1762 tmp6 = 0;
1763
1764 b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFE0, tmp6);
1765 b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFDF, scale << 5);
1766
1767 b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFFFB, 0x4);
1768 if (crystal_freq > 26000000)
1769 b43_phy_set(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0x2);
1770 else
1771 b43_phy_mask(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFD);
1772
1773 if (val1 == 45)
1774 b43_phy_set(dev, B2063_PLL_JTAG_PLL_VCO1, 0x2);
1775 else
1776 b43_phy_mask(dev, B2063_PLL_JTAG_PLL_VCO1, 0xFD);
1777
1778 b43_phy_set(dev, B2063_PLL_SP2, 0x3);
1779 udelay(1);
1780 b43_phy_mask(dev, B2063_PLL_SP2, 0xFFFC);
1781 lpphy_b2063_vco_calib(dev);
1782 b43_radio_write(dev, B2063_COMM15, old_comm15);
1783}
1784
1422static int b43_lpphy_op_switch_channel(struct b43_wldev *dev, 1785static int b43_lpphy_op_switch_channel(struct b43_wldev *dev,
1423 unsigned int new_channel) 1786 unsigned int new_channel)
1424{ 1787{
1425 //TODO 1788 b43_write16(dev, B43_MMIO_CHANNEL, new_channel);
1789
1790 if (dev->phy.radio_ver == 0x2063) {
1791 lpphy_b2063_tune(dev, new_channel);
1792 } else {
1793 lpphy_b2062_tune(dev, new_channel);
1794 //TODO Japan filter
1795 }
1796
1797 lpphy_adjust_gain_table(dev, channel2freq_lp(new_channel));
1798
1426 return 0; 1799 return 0;
1427} 1800}
1428 1801
1429static unsigned int b43_lpphy_op_get_default_chan(struct b43_wldev *dev) 1802static int b43_lpphy_op_init(struct b43_wldev *dev)
1430{ 1803{
1431 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) 1804 lpphy_read_band_sprom(dev); //FIXME should this be in prepare_structs?
1432 return 1; 1805 lpphy_baseband_init(dev);
1433 return 36; 1806 lpphy_radio_init(dev);
1807 lpphy_calibrate_rc(dev);
1808 b43_lpphy_op_switch_channel(dev, b43_lpphy_op_get_default_chan(dev));
1809 lpphy_tx_pctl_init(dev);
1810 lpphy_calibration(dev);
1811 //TODO ACI init
1812
1813 return 0;
1434} 1814}
1435 1815
1436static void b43_lpphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna) 1816static void b43_lpphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)