0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #include <linux/slab.h>
0034
0035 #include "b43.h"
0036 #include "phy_lcn.h"
0037 #include "tables_phy_lcn.h"
0038 #include "main.h"
0039
0040 struct lcn_tx_gains {
0041 u16 gm_gain;
0042 u16 pga_gain;
0043 u16 pad_gain;
0044 u16 dac_gain;
0045 };
0046
0047 struct lcn_tx_iir_filter {
0048 u8 type;
0049 u16 values[16];
0050 };
0051
0052 enum lcn_sense_type {
0053 B43_SENSE_TEMP,
0054 B43_SENSE_VBAT,
0055 };
0056
0057
0058
0059
0060
0061
0062 static void b43_radio_2064_channel_setup(struct b43_wldev *dev)
0063 {
0064 u16 save[2];
0065
0066 b43_radio_set(dev, 0x09d, 0x4);
0067 b43_radio_write(dev, 0x09e, 0xf);
0068
0069
0070 b43_radio_write(dev, 0x02a, 0xb);
0071 b43_radio_maskset(dev, 0x030, ~0x3, 0xa);
0072 b43_radio_maskset(dev, 0x091, ~0x3, 0);
0073 b43_radio_maskset(dev, 0x038, ~0xf, 0x7);
0074 b43_radio_maskset(dev, 0x030, ~0xc, 0x8);
0075 b43_radio_maskset(dev, 0x05e, ~0xf, 0x8);
0076 b43_radio_maskset(dev, 0x05e, ~0xf0, 0x80);
0077 b43_radio_write(dev, 0x06c, 0x80);
0078
0079 save[0] = b43_radio_read(dev, 0x044);
0080 save[1] = b43_radio_read(dev, 0x12b);
0081
0082 b43_radio_set(dev, 0x044, 0x7);
0083 b43_radio_set(dev, 0x12b, 0xe);
0084
0085
0086
0087 b43_radio_write(dev, 0x040, 0xfb);
0088
0089 b43_radio_write(dev, 0x041, 0x9a);
0090 b43_radio_write(dev, 0x042, 0xa3);
0091 b43_radio_write(dev, 0x043, 0x0c);
0092
0093
0094
0095 b43_radio_set(dev, 0x044, 0x0c);
0096 udelay(1);
0097
0098 b43_radio_write(dev, 0x044, save[0]);
0099 b43_radio_write(dev, 0x12b, save[1]);
0100
0101 if (dev->phy.rev == 1) {
0102
0103 b43_radio_write(dev, 0x038, 0x0);
0104 b43_radio_write(dev, 0x091, 0x7);
0105 }
0106 }
0107
0108
0109 static void b43_radio_2064_init(struct b43_wldev *dev)
0110 {
0111 if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
0112 b43_radio_write(dev, 0x09c, 0x0020);
0113 b43_radio_write(dev, 0x105, 0x0008);
0114 } else {
0115
0116 }
0117 b43_radio_write(dev, 0x032, 0x0062);
0118 b43_radio_write(dev, 0x033, 0x0019);
0119 b43_radio_write(dev, 0x090, 0x0010);
0120 b43_radio_write(dev, 0x010, 0x0000);
0121 if (dev->phy.rev == 1) {
0122 b43_radio_write(dev, 0x060, 0x007f);
0123 b43_radio_write(dev, 0x061, 0x0072);
0124 b43_radio_write(dev, 0x062, 0x007f);
0125 }
0126 b43_radio_write(dev, 0x01d, 0x0002);
0127 b43_radio_write(dev, 0x01e, 0x0006);
0128
0129 b43_phy_write(dev, 0x4ea, 0x4688);
0130 b43_phy_maskset(dev, 0x4eb, ~0x7, 0x2);
0131 b43_phy_mask(dev, 0x4eb, ~0x01c0);
0132 b43_phy_maskset(dev, 0x46a, 0xff00, 0x19);
0133
0134 b43_lcntab_write(dev, B43_LCNTAB16(0x00, 0x55), 0);
0135
0136 b43_radio_mask(dev, 0x05b, (u16) ~0xff02);
0137 b43_radio_set(dev, 0x004, 0x40);
0138 b43_radio_set(dev, 0x120, 0x10);
0139 b43_radio_set(dev, 0x078, 0x80);
0140 b43_radio_set(dev, 0x129, 0x2);
0141 b43_radio_set(dev, 0x057, 0x1);
0142 b43_radio_set(dev, 0x05b, 0x2);
0143
0144
0145 b43_radio_read(dev, 0x05c);
0146
0147 b43_radio_mask(dev, 0x05b, (u16) ~0xff02);
0148 b43_radio_mask(dev, 0x057, (u16) ~0xff01);
0149
0150 b43_phy_write(dev, 0x933, 0x2d6b);
0151 b43_phy_write(dev, 0x934, 0x2d6b);
0152 b43_phy_write(dev, 0x935, 0x2d6b);
0153 b43_phy_write(dev, 0x936, 0x2d6b);
0154 b43_phy_write(dev, 0x937, 0x016b);
0155
0156 b43_radio_mask(dev, 0x057, (u16) ~0xff02);
0157 b43_radio_write(dev, 0x0c2, 0x006f);
0158 }
0159
0160
0161
0162
0163
0164
0165 static void b43_phy_lcn_afe_set_unset(struct b43_wldev *dev)
0166 {
0167 u16 afe_ctl2 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL2);
0168 u16 afe_ctl1 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL1);
0169
0170 b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2 | 0x1);
0171 b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1 | 0x1);
0172
0173 b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2 & ~0x1);
0174 b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1 & ~0x1);
0175
0176 b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2);
0177 b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1);
0178 }
0179
0180
0181 static u16 b43_phy_lcn_get_pa_gain(struct b43_wldev *dev)
0182 {
0183 return (b43_phy_read(dev, 0x4fb) & 0x7f00) >> 8;
0184 }
0185
0186
0187 static void b43_phy_lcn_set_dac_gain(struct b43_wldev *dev, u16 dac_gain)
0188 {
0189 u16 dac_ctrl;
0190
0191 dac_ctrl = b43_phy_read(dev, 0x439);
0192 dac_ctrl = dac_ctrl & 0xc7f;
0193 dac_ctrl = dac_ctrl | (dac_gain << 7);
0194 b43_phy_maskset(dev, 0x439, ~0xfff, dac_ctrl);
0195 }
0196
0197
0198 static void b43_phy_lcn_set_bbmult(struct b43_wldev *dev, u8 m0)
0199 {
0200 b43_lcntab_write(dev, B43_LCNTAB16(0x00, 0x57), m0 << 8);
0201 }
0202
0203
0204 static void b43_phy_lcn_clear_tx_power_offsets(struct b43_wldev *dev)
0205 {
0206 u8 i;
0207
0208 if (1) {
0209 b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x340);
0210 for (i = 0; i < 30; i++) {
0211 b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0);
0212 b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0);
0213 }
0214 }
0215
0216 b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x80);
0217 for (i = 0; i < 64; i++) {
0218 b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0);
0219 b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0);
0220 }
0221 }
0222
0223
0224 static void b43_phy_lcn_rev0_baseband_init(struct b43_wldev *dev)
0225 {
0226 b43_radio_write(dev, 0x11c, 0);
0227
0228 b43_phy_write(dev, 0x43b, 0);
0229 b43_phy_write(dev, 0x43c, 0);
0230 b43_phy_write(dev, 0x44c, 0);
0231 b43_phy_write(dev, 0x4e6, 0);
0232 b43_phy_write(dev, 0x4f9, 0);
0233 b43_phy_write(dev, 0x4b0, 0);
0234 b43_phy_write(dev, 0x938, 0);
0235 b43_phy_write(dev, 0x4b0, 0);
0236 b43_phy_write(dev, 0x44e, 0);
0237
0238 b43_phy_set(dev, 0x567, 0x03);
0239
0240 b43_phy_set(dev, 0x44a, 0x44);
0241 b43_phy_write(dev, 0x44a, 0x80);
0242
0243 if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM))
0244 ;
0245 b43_phy_maskset(dev, 0x634, ~0xff, 0xc);
0246 if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM) {
0247 b43_phy_maskset(dev, 0x634, ~0xff, 0xa);
0248 b43_phy_write(dev, 0x910, 0x1);
0249 }
0250
0251 b43_phy_write(dev, 0x910, 0x1);
0252
0253 b43_phy_maskset(dev, 0x448, ~0x300, 0x100);
0254 b43_phy_maskset(dev, 0x608, ~0xff, 0x17);
0255 b43_phy_maskset(dev, 0x604, ~0x7ff, 0x3ea);
0256 }
0257
0258
0259 static void b43_phy_lcn_bu_tweaks(struct b43_wldev *dev)
0260 {
0261 b43_phy_set(dev, 0x805, 0x1);
0262
0263 b43_phy_maskset(dev, 0x42f, ~0x7, 0x3);
0264 b43_phy_maskset(dev, 0x030, ~0x7, 0x3);
0265
0266 b43_phy_write(dev, 0x414, 0x1e10);
0267 b43_phy_write(dev, 0x415, 0x0640);
0268
0269 b43_phy_maskset(dev, 0x4df, (u16) ~0xff00, 0xf700);
0270
0271 b43_phy_set(dev, 0x44a, 0x44);
0272 b43_phy_write(dev, 0x44a, 0x80);
0273
0274 b43_phy_maskset(dev, 0x434, ~0xff, 0xfd);
0275 b43_phy_maskset(dev, 0x420, ~0xff, 0x10);
0276
0277 if (dev->dev->bus_sprom->board_rev >= 0x1204)
0278 b43_radio_set(dev, 0x09b, 0xf0);
0279
0280 b43_phy_write(dev, 0x7d6, 0x0902);
0281
0282 b43_phy_maskset(dev, 0x429, ~0xf, 0x9);
0283 b43_phy_maskset(dev, 0x429, ~(0x3f << 4), 0xe << 4);
0284
0285 if (dev->phy.rev == 1) {
0286 b43_phy_maskset(dev, 0x423, ~0xff, 0x46);
0287 b43_phy_maskset(dev, 0x411, ~0xff, 1);
0288 b43_phy_set(dev, 0x434, 0xff);
0289
0290
0291
0292 b43_phy_maskset(dev, 0x656, ~0xf, 2);
0293 b43_phy_set(dev, 0x44d, 4);
0294
0295 b43_radio_set(dev, 0x0f7, 0x4);
0296 b43_radio_mask(dev, 0x0f1, ~0x3);
0297 b43_radio_maskset(dev, 0x0f2, ~0xf8, 0x90);
0298 b43_radio_maskset(dev, 0x0f3, ~0x3, 0x2);
0299 b43_radio_maskset(dev, 0x0f3, ~0xf0, 0xa0);
0300
0301 b43_radio_set(dev, 0x11f, 0x2);
0302
0303 b43_phy_lcn_clear_tx_power_offsets(dev);
0304
0305
0306 }
0307 }
0308
0309
0310 static void b43_phy_lcn_sense_setup(struct b43_wldev *dev,
0311 enum lcn_sense_type sense_type)
0312 {
0313 u8 auxpga_vmidcourse, auxpga_vmidfine, auxpga_gain;
0314 u16 auxpga_vmid;
0315 u8 tx_pwr_idx;
0316 u8 i;
0317
0318 u16 save_radio_regs[6][2] = {
0319 { 0x007, 0 }, { 0x0ff, 0 }, { 0x11f, 0 }, { 0x005, 0 },
0320 { 0x025, 0 }, { 0x112, 0 },
0321 };
0322 u16 save_phy_regs[14][2] = {
0323 { 0x503, 0 }, { 0x4a4, 0 }, { 0x4d0, 0 }, { 0x4d9, 0 },
0324 { 0x4da, 0 }, { 0x4a6, 0 }, { 0x938, 0 }, { 0x939, 0 },
0325 { 0x4d8, 0 }, { 0x4d0, 0 }, { 0x4d7, 0 }, { 0x4a5, 0 },
0326 { 0x40d, 0 }, { 0x4a2, 0 },
0327 };
0328 u16 save_radio_4a4;
0329
0330 msleep(1);
0331
0332
0333 for (i = 0; i < 6; i++)
0334 save_radio_regs[i][1] = b43_radio_read(dev,
0335 save_radio_regs[i][0]);
0336 for (i = 0; i < 14; i++)
0337 save_phy_regs[i][1] = b43_phy_read(dev, save_phy_regs[i][0]);
0338 b43_mac_suspend(dev);
0339 save_radio_4a4 = b43_radio_read(dev, 0x4a4);
0340
0341 tx_pwr_idx = dev->phy.lcn->tx_pwr_curr_idx;
0342
0343
0344
0345 b43_radio_set(dev, 0x007, 0x1);
0346 b43_radio_set(dev, 0x0ff, 0x10);
0347 b43_radio_set(dev, 0x11f, 0x4);
0348
0349 b43_phy_mask(dev, 0x503, ~0x1);
0350 b43_phy_mask(dev, 0x503, ~0x4);
0351 b43_phy_mask(dev, 0x4a4, ~0x4000);
0352 b43_phy_mask(dev, 0x4a4, (u16) ~0x8000);
0353 b43_phy_mask(dev, 0x4d0, ~0x20);
0354 b43_phy_set(dev, 0x4a5, 0xff);
0355 b43_phy_maskset(dev, 0x4a5, ~0x7000, 0x5000);
0356 b43_phy_mask(dev, 0x4a5, ~0x700);
0357 b43_phy_maskset(dev, 0x40d, ~0xff, 64);
0358 b43_phy_maskset(dev, 0x40d, ~0x700, 0x600);
0359 b43_phy_maskset(dev, 0x4a2, ~0xff, 64);
0360 b43_phy_maskset(dev, 0x4a2, ~0x700, 0x600);
0361 b43_phy_maskset(dev, 0x4d9, ~0x70, 0x20);
0362 b43_phy_maskset(dev, 0x4d9, ~0x700, 0x300);
0363 b43_phy_maskset(dev, 0x4d9, ~0x7000, 0x1000);
0364 b43_phy_mask(dev, 0x4da, ~0x1000);
0365 b43_phy_set(dev, 0x4da, 0x2000);
0366 b43_phy_set(dev, 0x4a6, 0x8000);
0367
0368 b43_radio_write(dev, 0x025, 0xc);
0369 b43_radio_set(dev, 0x005, 0x8);
0370 b43_phy_set(dev, 0x938, 0x4);
0371 b43_phy_set(dev, 0x939, 0x4);
0372 b43_phy_set(dev, 0x4a4, 0x1000);
0373
0374
0375 b43_lcntab_write(dev, B43_LCNTAB16(0x8, 0x6), 0x640);
0376
0377 switch (sense_type) {
0378 case B43_SENSE_TEMP:
0379 b43_phy_set(dev, 0x4d7, 0x8);
0380 b43_phy_maskset(dev, 0x4d7, ~0x7000, 0x1000);
0381 auxpga_vmidcourse = 8;
0382 auxpga_vmidfine = 0x4;
0383 auxpga_gain = 2;
0384 b43_radio_set(dev, 0x082, 0x20);
0385 break;
0386 case B43_SENSE_VBAT:
0387 b43_phy_set(dev, 0x4d7, 0x8);
0388 b43_phy_maskset(dev, 0x4d7, ~0x7000, 0x3000);
0389 auxpga_vmidcourse = 7;
0390 auxpga_vmidfine = 0xa;
0391 auxpga_gain = 2;
0392 break;
0393 }
0394 auxpga_vmid = (0x200 | (auxpga_vmidcourse << 4) | auxpga_vmidfine);
0395
0396 b43_phy_set(dev, 0x4d8, 0x1);
0397 b43_phy_maskset(dev, 0x4d8, ~(0x3ff << 2), auxpga_vmid << 2);
0398 b43_phy_set(dev, 0x4d8, 0x2);
0399 b43_phy_maskset(dev, 0x4d8, ~(0x7 << 12), auxpga_gain << 12);
0400 b43_phy_set(dev, 0x4d0, 0x20);
0401 b43_radio_write(dev, 0x112, 0x6);
0402
0403 b43_dummy_transmission(dev, true, false);
0404
0405 if (!(b43_phy_read(dev, 0x476) & 0x8000))
0406 udelay(10);
0407
0408
0409 for (i = 0; i < 6; i++)
0410 b43_radio_write(dev, save_radio_regs[i][0],
0411 save_radio_regs[i][1]);
0412 for (i = 0; i < 14; i++)
0413 b43_phy_write(dev, save_phy_regs[i][0], save_phy_regs[i][1]);
0414
0415 b43_radio_write(dev, 0x4a4, save_radio_4a4);
0416
0417 b43_mac_enable(dev);
0418
0419 msleep(1);
0420 }
0421
0422 static bool b43_phy_lcn_load_tx_iir_cck_filter(struct b43_wldev *dev,
0423 u8 filter_type)
0424 {
0425 int i, j;
0426 u16 phy_regs[] = { 0x910, 0x91e, 0x91f, 0x924, 0x925, 0x926, 0x920,
0427 0x921, 0x927, 0x928, 0x929, 0x922, 0x923, 0x930,
0428 0x931, 0x932 };
0429
0430
0431 struct lcn_tx_iir_filter tx_iir_filters_cck[] = {
0432 { 0, { 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778,
0433 1582, 64, 128, 64 } },
0434 { 1, { 1, 402, 1847, 259, 59, 259, 671, 1794, 68, 54, 68, 608,
0435 1863, 93, 167, 93 } },
0436 { 2, { 1, 415, 1874, 64, 128, 64, 792, 1656, 192, 384, 192,
0437 778, 1582, 64, 128, 64 } },
0438 { 3, { 1, 302, 1841, 129, 258, 129, 658, 1720, 205, 410, 205,
0439 754, 1760, 170, 340, 170 } },
0440 { 20, { 1, 360, 1884, 242, 1734, 242, 752, 1720, 205, 1845, 205,
0441 767, 1760, 256, 185, 256 } },
0442 { 21, { 1, 360, 1884, 149, 1874, 149, 752, 1720, 205, 1883, 205,
0443 767, 1760, 256, 273, 256 } },
0444 { 22, { 1, 360, 1884, 98, 1948, 98, 752, 1720, 205, 1924, 205,
0445 767, 1760, 256, 352, 256 } },
0446 { 23, { 1, 350, 1884, 116, 1966, 116, 752, 1720, 205, 2008, 205,
0447 767, 1760, 128, 233, 128 } },
0448 { 24, { 1, 325, 1884, 32, 40, 32, 756, 1720, 256, 471, 256, 766,
0449 1760, 256, 1881, 256 } },
0450 { 25, { 1, 299, 1884, 51, 64, 51, 736, 1720, 256, 471, 256, 765,
0451 1760, 262, 1878, 262 } },
0452
0453
0454 { 26, { 1, 277, 1943, 39, 117, 88, 637, 1838, 64, 192, 144, 614,
0455 1864, 128, 384, 288 } },
0456 { 27, { 1, 245, 1943, 49, 147, 110, 626, 1838, 256, 768, 576,
0457 613, 1864, 128, 384, 288 } },
0458 { 30, { 1, 302, 1841, 61, 122, 61, 658, 1720, 205, 410, 205,
0459 754, 1760, 170, 340, 170 } },
0460 };
0461
0462 for (i = 0; i < ARRAY_SIZE(tx_iir_filters_cck); i++) {
0463 if (tx_iir_filters_cck[i].type == filter_type) {
0464 for (j = 0; j < 16; j++)
0465 b43_phy_write(dev, phy_regs[j],
0466 tx_iir_filters_cck[i].values[j]);
0467 return true;
0468 }
0469 }
0470
0471 return false;
0472 }
0473
0474 static bool b43_phy_lcn_load_tx_iir_ofdm_filter(struct b43_wldev *dev,
0475 u8 filter_type)
0476 {
0477 int i, j;
0478 u16 phy_regs[] = { 0x90f, 0x900, 0x901, 0x906, 0x907, 0x908, 0x902,
0479 0x903, 0x909, 0x90a, 0x90b, 0x904, 0x905, 0x90c,
0480 0x90d, 0x90e };
0481 struct lcn_tx_iir_filter tx_iir_filters_ofdm[] = {
0482 { 0, { 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0,
0483 0x0, 0x278, 0xfea0, 0x80, 0x100, 0x80 } },
0484 { 1, { 0, 374, 0xFF79, 16, 32, 16, 799, 0xFE74, 50, 32, 50, 750,
0485 0xFE2B, 212, 0xFFCE, 212 } },
0486 { 2, { 0, 375, 0xFF16, 37, 76, 37, 799, 0xFE74, 32, 20, 32, 748,
0487 0xFEF2, 128, 0xFFE2, 128 } },
0488 };
0489
0490 for (i = 0; i < ARRAY_SIZE(tx_iir_filters_ofdm); i++) {
0491 if (tx_iir_filters_ofdm[i].type == filter_type) {
0492 for (j = 0; j < 16; j++)
0493 b43_phy_write(dev, phy_regs[j],
0494 tx_iir_filters_ofdm[i].values[j]);
0495 return true;
0496 }
0497 }
0498
0499 return false;
0500 }
0501
0502
0503 static void b43_phy_lcn_set_tx_gain_override(struct b43_wldev *dev, bool enable)
0504 {
0505 b43_phy_maskset(dev, 0x4b0, ~(0x1 << 7), enable << 7);
0506 b43_phy_maskset(dev, 0x4b0, ~(0x1 << 14), enable << 14);
0507 b43_phy_maskset(dev, 0x43b, ~(0x1 << 6), enable << 6);
0508 }
0509
0510
0511 static void b43_phy_lcn_set_tx_gain(struct b43_wldev *dev,
0512 struct lcn_tx_gains *target_gains)
0513 {
0514 u16 pa_gain = b43_phy_lcn_get_pa_gain(dev);
0515
0516 b43_phy_write(dev, 0x4b5,
0517 (target_gains->gm_gain | (target_gains->pga_gain << 8)));
0518 b43_phy_maskset(dev, 0x4fb, ~0x7fff,
0519 (target_gains->pad_gain | (pa_gain << 8)));
0520 b43_phy_write(dev, 0x4fc,
0521 (target_gains->gm_gain | (target_gains->pga_gain << 8)));
0522 b43_phy_maskset(dev, 0x4fd, ~0x7fff,
0523 (target_gains->pad_gain | (pa_gain << 8)));
0524
0525 b43_phy_lcn_set_dac_gain(dev, target_gains->dac_gain);
0526 b43_phy_lcn_set_tx_gain_override(dev, true);
0527 }
0528
0529
0530 static void b43_phy_lcn_tx_pwr_ctl_init(struct b43_wldev *dev)
0531 {
0532 struct lcn_tx_gains tx_gains;
0533 u8 bbmult;
0534
0535 b43_mac_suspend(dev);
0536
0537 if (!dev->phy.lcn->hw_pwr_ctl_capable) {
0538 if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
0539 tx_gains.gm_gain = 4;
0540 tx_gains.pga_gain = 12;
0541 tx_gains.pad_gain = 12;
0542 tx_gains.dac_gain = 0;
0543 bbmult = 150;
0544 } else {
0545 tx_gains.gm_gain = 7;
0546 tx_gains.pga_gain = 15;
0547 tx_gains.pad_gain = 14;
0548 tx_gains.dac_gain = 0;
0549 bbmult = 150;
0550 }
0551 b43_phy_lcn_set_tx_gain(dev, &tx_gains);
0552 b43_phy_lcn_set_bbmult(dev, bbmult);
0553 b43_phy_lcn_sense_setup(dev, B43_SENSE_TEMP);
0554 } else {
0555 b43err(dev->wl, "TX power control not supported for this HW\n");
0556 }
0557
0558 b43_mac_enable(dev);
0559 }
0560
0561
0562 static void b43_phy_lcn_txrx_spur_avoidance_mode(struct b43_wldev *dev,
0563 bool enable)
0564 {
0565 if (enable) {
0566 b43_phy_write(dev, 0x942, 0x7);
0567 b43_phy_write(dev, 0x93b, ((1 << 13) + 23));
0568 b43_phy_write(dev, 0x93c, ((1 << 13) + 1989));
0569
0570 b43_phy_write(dev, 0x44a, 0x084);
0571 b43_phy_write(dev, 0x44a, 0x080);
0572 b43_phy_write(dev, 0x6d3, 0x2222);
0573 b43_phy_write(dev, 0x6d3, 0x2220);
0574 } else {
0575 b43_phy_write(dev, 0x942, 0x0);
0576 b43_phy_write(dev, 0x93b, ((0 << 13) + 23));
0577 b43_phy_write(dev, 0x93c, ((0 << 13) + 1989));
0578 }
0579 b43_mac_switch_freq(dev, enable);
0580 }
0581
0582
0583
0584
0585
0586
0587 static void b43_phy_lcn_set_channel_tweaks(struct b43_wldev *dev, int channel)
0588 {
0589 struct bcma_drv_cc *cc = &dev->dev->bdev->bus->drv_cc;
0590
0591 b43_phy_maskset(dev, 0x448, ~0x300, (channel == 14) ? 0x200 : 0x100);
0592
0593 if (channel == 1 || channel == 2 || channel == 3 || channel == 4 ||
0594 channel == 9 || channel == 10 || channel == 11 || channel == 12) {
0595 bcma_chipco_pll_write(cc, 0x2, 0x03000c04);
0596 bcma_chipco_pll_maskset(cc, 0x3, 0x00ffffff, 0x0);
0597 bcma_chipco_pll_write(cc, 0x4, 0x200005c0);
0598
0599 bcma_cc_set32(cc, BCMA_CC_PMU_CTL, 0x400);
0600
0601 b43_phy_write(dev, 0x942, 0);
0602
0603 b43_phy_lcn_txrx_spur_avoidance_mode(dev, false);
0604 b43_phy_maskset(dev, 0x424, (u16) ~0xff00, 0x1b00);
0605 b43_phy_write(dev, 0x425, 0x5907);
0606 } else {
0607 bcma_chipco_pll_write(cc, 0x2, 0x03140c04);
0608 bcma_chipco_pll_maskset(cc, 0x3, 0x00ffffff, 0x333333);
0609 bcma_chipco_pll_write(cc, 0x4, 0x202c2820);
0610
0611 bcma_cc_set32(cc, BCMA_CC_PMU_CTL, 0x400);
0612
0613 b43_phy_write(dev, 0x942, 0);
0614
0615 b43_phy_lcn_txrx_spur_avoidance_mode(dev, true);
0616 b43_phy_maskset(dev, 0x424, (u16) ~0xff00, 0x1f00);
0617 b43_phy_write(dev, 0x425, 0x590a);
0618 }
0619
0620 b43_phy_set(dev, 0x44a, 0x44);
0621 b43_phy_write(dev, 0x44a, 0x80);
0622 }
0623
0624
0625 static int b43_phy_lcn_set_channel(struct b43_wldev *dev,
0626 struct ieee80211_channel *channel,
0627 enum nl80211_channel_type channel_type)
0628 {
0629 static const u16 sfo_cfg[14][2] = {
0630 {965, 1087}, {967, 1085}, {969, 1082}, {971, 1080}, {973, 1078},
0631 {975, 1076}, {977, 1073}, {979, 1071}, {981, 1069}, {983, 1067},
0632 {985, 1065}, {987, 1063}, {989, 1060}, {994, 1055},
0633 };
0634
0635 b43_phy_lcn_set_channel_tweaks(dev, channel->hw_value);
0636
0637 b43_phy_set(dev, 0x44a, 0x44);
0638 b43_phy_write(dev, 0x44a, 0x80);
0639
0640 b43_radio_2064_channel_setup(dev);
0641 mdelay(1);
0642
0643 b43_phy_lcn_afe_set_unset(dev);
0644
0645 b43_phy_write(dev, 0x657, sfo_cfg[channel->hw_value - 1][0]);
0646 b43_phy_write(dev, 0x658, sfo_cfg[channel->hw_value - 1][1]);
0647
0648 if (channel->hw_value == 14) {
0649 b43_phy_maskset(dev, 0x448, ~(0x3 << 8), (2) << 8);
0650 b43_phy_lcn_load_tx_iir_cck_filter(dev, 3);
0651 } else {
0652 b43_phy_maskset(dev, 0x448, ~(0x3 << 8), (1) << 8);
0653
0654 b43_phy_lcn_load_tx_iir_cck_filter(dev, 25);
0655 }
0656
0657 b43_phy_lcn_load_tx_iir_ofdm_filter(dev, 0);
0658
0659 b43_phy_maskset(dev, 0x4eb, ~(0x7 << 3), 0x1 << 3);
0660
0661 return 0;
0662 }
0663
0664
0665
0666
0667
0668 static int b43_phy_lcn_op_allocate(struct b43_wldev *dev)
0669 {
0670 struct b43_phy_lcn *phy_lcn;
0671
0672 phy_lcn = kzalloc(sizeof(*phy_lcn), GFP_KERNEL);
0673 if (!phy_lcn)
0674 return -ENOMEM;
0675 dev->phy.lcn = phy_lcn;
0676
0677 return 0;
0678 }
0679
0680 static void b43_phy_lcn_op_free(struct b43_wldev *dev)
0681 {
0682 struct b43_phy *phy = &dev->phy;
0683 struct b43_phy_lcn *phy_lcn = phy->lcn;
0684
0685 kfree(phy_lcn);
0686 phy->lcn = NULL;
0687 }
0688
0689 static void b43_phy_lcn_op_prepare_structs(struct b43_wldev *dev)
0690 {
0691 struct b43_phy *phy = &dev->phy;
0692 struct b43_phy_lcn *phy_lcn = phy->lcn;
0693
0694 memset(phy_lcn, 0, sizeof(*phy_lcn));
0695 }
0696
0697
0698 static int b43_phy_lcn_op_init(struct b43_wldev *dev)
0699 {
0700 struct bcma_drv_cc *cc = &dev->dev->bdev->bus->drv_cc;
0701
0702 b43_phy_set(dev, 0x44a, 0x80);
0703 b43_phy_mask(dev, 0x44a, 0x7f);
0704 b43_phy_set(dev, 0x6d1, 0x80);
0705 b43_phy_write(dev, 0x6d0, 0x7);
0706
0707 b43_phy_lcn_afe_set_unset(dev);
0708
0709 b43_phy_write(dev, 0x60a, 0xa0);
0710 b43_phy_write(dev, 0x46a, 0x19);
0711 b43_phy_maskset(dev, 0x663, 0xFF00, 0x64);
0712
0713 b43_phy_lcn_tables_init(dev);
0714
0715 b43_phy_lcn_rev0_baseband_init(dev);
0716 b43_phy_lcn_bu_tweaks(dev);
0717
0718 if (dev->phy.radio_ver == 0x2064)
0719 b43_radio_2064_init(dev);
0720 else
0721 B43_WARN_ON(1);
0722
0723 if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
0724 b43_phy_lcn_tx_pwr_ctl_init(dev);
0725
0726 b43_switch_channel(dev, dev->phy.channel);
0727
0728 bcma_chipco_regctl_maskset(cc, 0, 0xf, 0x9);
0729 bcma_chipco_chipctl_maskset(cc, 0, 0, 0x03cddddd);
0730
0731
0732
0733 b43_phy_set(dev, 0x448, 0x4000);
0734 udelay(100);
0735 b43_phy_mask(dev, 0x448, ~0x4000);
0736
0737
0738
0739 return 0;
0740 }
0741
0742 static void b43_phy_lcn_op_software_rfkill(struct b43_wldev *dev,
0743 bool blocked)
0744 {
0745 if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
0746 b43err(dev->wl, "MAC not suspended\n");
0747
0748 if (blocked) {
0749 b43_phy_mask(dev, B43_PHY_LCN_RF_CTL2, ~0x7c00);
0750 b43_phy_set(dev, B43_PHY_LCN_RF_CTL1, 0x1f00);
0751
0752 b43_phy_mask(dev, B43_PHY_LCN_RF_CTL5, ~0x7f00);
0753 b43_phy_mask(dev, B43_PHY_LCN_RF_CTL4, ~0x2);
0754 b43_phy_set(dev, B43_PHY_LCN_RF_CTL3, 0x808);
0755
0756 b43_phy_mask(dev, B43_PHY_LCN_RF_CTL7, ~0x8);
0757 b43_phy_set(dev, B43_PHY_LCN_RF_CTL6, 0x8);
0758 } else {
0759 b43_phy_mask(dev, B43_PHY_LCN_RF_CTL1, ~0x1f00);
0760 b43_phy_mask(dev, B43_PHY_LCN_RF_CTL3, ~0x808);
0761 b43_phy_mask(dev, B43_PHY_LCN_RF_CTL6, ~0x8);
0762 }
0763 }
0764
0765 static void b43_phy_lcn_op_switch_analog(struct b43_wldev *dev, bool on)
0766 {
0767 if (on) {
0768 b43_phy_mask(dev, B43_PHY_LCN_AFE_CTL1, ~0x7);
0769 } else {
0770 b43_phy_set(dev, B43_PHY_LCN_AFE_CTL2, 0x7);
0771 b43_phy_set(dev, B43_PHY_LCN_AFE_CTL1, 0x7);
0772 }
0773 }
0774
0775 static int b43_phy_lcn_op_switch_channel(struct b43_wldev *dev,
0776 unsigned int new_channel)
0777 {
0778 struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;
0779 enum nl80211_channel_type channel_type =
0780 cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef);
0781
0782 if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
0783 if ((new_channel < 1) || (new_channel > 14))
0784 return -EINVAL;
0785 } else {
0786 return -EINVAL;
0787 }
0788
0789 return b43_phy_lcn_set_channel(dev, channel, channel_type);
0790 }
0791
0792 static unsigned int b43_phy_lcn_op_get_default_chan(struct b43_wldev *dev)
0793 {
0794 if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
0795 return 1;
0796 return 36;
0797 }
0798
0799 static enum b43_txpwr_result
0800 b43_phy_lcn_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi)
0801 {
0802 return B43_TXPWR_RES_DONE;
0803 }
0804
0805 static void b43_phy_lcn_op_adjust_txpower(struct b43_wldev *dev)
0806 {
0807 }
0808
0809
0810
0811
0812
0813 static void b43_phy_lcn_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
0814 u16 set)
0815 {
0816 b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
0817 b43_write16(dev, B43_MMIO_PHY_DATA,
0818 (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
0819 }
0820
0821 static u16 b43_phy_lcn_op_radio_read(struct b43_wldev *dev, u16 reg)
0822 {
0823
0824 reg |= 0x200;
0825
0826 b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg);
0827 return b43_read16(dev, B43_MMIO_RADIO24_DATA);
0828 }
0829
0830 static void b43_phy_lcn_op_radio_write(struct b43_wldev *dev, u16 reg,
0831 u16 value)
0832 {
0833 b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg);
0834 b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
0835 }
0836
0837
0838
0839
0840
0841 const struct b43_phy_operations b43_phyops_lcn = {
0842 .allocate = b43_phy_lcn_op_allocate,
0843 .free = b43_phy_lcn_op_free,
0844 .prepare_structs = b43_phy_lcn_op_prepare_structs,
0845 .init = b43_phy_lcn_op_init,
0846 .phy_maskset = b43_phy_lcn_op_maskset,
0847 .radio_read = b43_phy_lcn_op_radio_read,
0848 .radio_write = b43_phy_lcn_op_radio_write,
0849 .software_rfkill = b43_phy_lcn_op_software_rfkill,
0850 .switch_analog = b43_phy_lcn_op_switch_analog,
0851 .switch_channel = b43_phy_lcn_op_switch_channel,
0852 .get_default_chan = b43_phy_lcn_op_get_default_chan,
0853 .recalc_txpower = b43_phy_lcn_op_recalc_txpower,
0854 .adjust_txpower = b43_phy_lcn_op_adjust_txpower,
0855 };