3 Broadcom BCM43xx wireless driver
5 G PHY LO (LocalOscillator) Measuring and Control routines
7 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
8 Copyright (c) 2005, 2006 Stefano Brivio <st3@riseup.net>
9 Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
10 Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
11 Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; see the file COPYING. If not, write to
25 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
26 Boston, MA 02110-1301, USA.
31 #include "bcm43xx_lo.h"
32 #include "bcm43xx_phy.h"
33 #include "bcm43xx_main.h"
35 #include <linux/delay.h>
36 #include <linux/sched.h>
39 /* Write the LocalOscillator Control (adjust) value-pair. */
40 static void bcm43xx_lo_write(struct bcm43xx_wldev *dev,
41 struct bcm43xx_loctl *control)
43 struct bcm43xx_phy *phy = &dev->phy;
48 if (unlikely(abs(control->i) > 16 ||
49 abs(control->q) > 16)) {
50 printk(KERN_ERR PFX "ERROR: Invalid LO control pair "
52 control->i, control->q);
58 value = (u8)(control->q);
59 value |= ((u8)(control->i)) << 8;
61 reg = (phy->type == BCM43xx_PHYTYPE_B) ? 0x002F : BCM43xx_PHY_LO_CTL;
62 bcm43xx_phy_write(dev, reg, value);
66 int assert_rfatt_and_bbatt(const struct bcm43xx_rfatt *rfatt,
67 const struct bcm43xx_bbatt *bbatt)
71 /* Check the attenuation values against the LO control array sizes. */
73 if (rfatt->att >= BCM43xx_NR_RF) {
75 "ERROR: rfatt(%u) >= size of LO array\n",
79 if (bbatt->att >= BCM43xx_NR_BB) {
81 "ERROR: bbatt(%u) >= size of LO array\n",
87 #endif /* BCM43xx_DEBUG */
93 struct bcm43xx_loctl * bcm43xx_get_lo_g_ctl_nopadmix(struct bcm43xx_wldev *dev,
94 const struct bcm43xx_rfatt *rfatt,
95 const struct bcm43xx_bbatt *bbatt)
97 struct bcm43xx_phy *phy = &dev->phy;
98 struct bcm43xx_txpower_lo_control *lo = phy->lo_control;
100 if (assert_rfatt_and_bbatt(rfatt, bbatt))
101 return &(lo->no_padmix[0][0]); /* Just prevent a crash */
102 return &(lo->no_padmix[bbatt->att][rfatt->att]);
105 struct bcm43xx_loctl * bcm43xx_get_lo_g_ctl(struct bcm43xx_wldev *dev,
106 const struct bcm43xx_rfatt *rfatt,
107 const struct bcm43xx_bbatt *bbatt)
109 struct bcm43xx_phy *phy = &dev->phy;
110 struct bcm43xx_txpower_lo_control *lo = phy->lo_control;
112 if (assert_rfatt_and_bbatt(rfatt, bbatt))
113 return &(lo->no_padmix[0][0]); /* Just prevent a crash */
114 if (rfatt->with_padmix)
115 return &(lo->with_padmix[bbatt->att][rfatt->att]);
116 return &(lo->no_padmix[bbatt->att][rfatt->att]);
119 /* Call a function for every possible LO control value-pair. */
120 static void bcm43xx_call_for_each_loctl(struct bcm43xx_wldev *dev,
121 void (*func)(struct bcm43xx_wldev *,
122 struct bcm43xx_loctl *))
124 struct bcm43xx_phy *phy = &dev->phy;
125 struct bcm43xx_txpower_lo_control *ctl = phy->lo_control;
128 for (i = 0; i < BCM43xx_NR_BB; i++) {
129 for (j = 0; j < BCM43xx_NR_RF; j++)
130 func(dev, &(ctl->with_padmix[i][j]));
132 for (i = 0; i < BCM43xx_NR_BB; i++) {
133 for (j = 0; j < BCM43xx_NR_RF; j++)
134 func(dev, &(ctl->no_padmix[i][j]));
138 static u16 lo_b_r15_loop(struct bcm43xx_wldev *dev)
143 for (i = 0; i < 10; i++){
144 bcm43xx_phy_write(dev, 0x0015, 0xAFA0);
146 bcm43xx_phy_write(dev, 0x0015, 0xEFA0);
148 bcm43xx_phy_write(dev, 0x0015, 0xFFA0);
150 ret += bcm43xx_phy_read(dev, 0x002C);
156 void bcm43xx_lo_b_measure(struct bcm43xx_wldev *dev)
158 struct bcm43xx_phy *phy = &dev->phy;
159 u16 regstack[12] = { 0 };
164 regstack[0] = bcm43xx_phy_read(dev, 0x0015);
165 regstack[1] = bcm43xx_radio_read16(dev, 0x0052) & 0xFFF0;
167 if (phy->radio_ver == 0x2053) {
168 regstack[2] = bcm43xx_phy_read(dev, 0x000A);
169 regstack[3] = bcm43xx_phy_read(dev, 0x002A);
170 regstack[4] = bcm43xx_phy_read(dev, 0x0035);
171 regstack[5] = bcm43xx_phy_read(dev, 0x0003);
172 regstack[6] = bcm43xx_phy_read(dev, 0x0001);
173 regstack[7] = bcm43xx_phy_read(dev, 0x0030);
175 regstack[8] = bcm43xx_radio_read16(dev, 0x0043);
176 regstack[9] = bcm43xx_radio_read16(dev, 0x007A);
177 regstack[10] = bcm43xx_read16(dev, 0x03EC);
178 regstack[11] = bcm43xx_radio_read16(dev, 0x0052) & 0x00F0;
180 bcm43xx_phy_write(dev, 0x0030, 0x00FF);
181 bcm43xx_write16(dev, 0x03EC, 0x3F3F);
182 bcm43xx_phy_write(dev, 0x0035, regstack[4] & 0xFF7F);
183 bcm43xx_radio_write16(dev, 0x007A, regstack[9] & 0xFFF0);
185 bcm43xx_phy_write(dev, 0x0015, 0xB000);
186 bcm43xx_phy_write(dev, 0x002B, 0x0004);
188 if (phy->radio_ver == 0x2053) {
189 bcm43xx_phy_write(dev, 0x002B, 0x0203);
190 bcm43xx_phy_write(dev, 0x002A, 0x08A3);
193 phy->minlowsig[0] = 0xFFFF;
195 for (i = 0; i < 4; i++) {
196 bcm43xx_radio_write16(dev, 0x0052, regstack[1] | i);
199 for (i = 0; i < 10; i++) {
200 bcm43xx_radio_write16(dev, 0x0052, regstack[1] | i);
201 mls = lo_b_r15_loop(dev) / 10;
202 if (mls < phy->minlowsig[0]) {
203 phy->minlowsig[0] = mls;
204 phy->minlowsigpos[0] = i;
207 bcm43xx_radio_write16(dev, 0x0052, regstack[1] | phy->minlowsigpos[0]);
209 phy->minlowsig[1] = 0xFFFF;
211 for (i = -4; i < 5; i += 2) {
212 for (j = -4; j < 5; j += 2) {
214 fval = (0x0100 * i) + j + 0x0100;
216 fval = (0x0100 * i) + j;
217 bcm43xx_phy_write(dev, 0x002F, fval);
218 mls = lo_b_r15_loop(dev) / 10;
219 if (mls < phy->minlowsig[1]) {
220 phy->minlowsig[1] = mls;
221 phy->minlowsigpos[1] = fval;
225 phy->minlowsigpos[1] += 0x0101;
227 bcm43xx_phy_write(dev, 0x002F, phy->minlowsigpos[1]);
228 if (phy->radio_ver == 0x2053) {
229 bcm43xx_phy_write(dev, 0x000A, regstack[2]);
230 bcm43xx_phy_write(dev, 0x002A, regstack[3]);
231 bcm43xx_phy_write(dev, 0x0035, regstack[4]);
232 bcm43xx_phy_write(dev, 0x0003, regstack[5]);
233 bcm43xx_phy_write(dev, 0x0001, regstack[6]);
234 bcm43xx_phy_write(dev, 0x0030, regstack[7]);
236 bcm43xx_radio_write16(dev, 0x0043, regstack[8]);
237 bcm43xx_radio_write16(dev, 0x007A, regstack[9]);
239 bcm43xx_radio_write16(dev, 0x0052,
240 (bcm43xx_radio_read16(dev, 0x0052) & 0x000F)
243 bcm43xx_write16(dev, 0x03EC, regstack[10]);
245 bcm43xx_phy_write(dev, 0x0015, regstack[0]);
248 static u16 lo_measure_feedthrough(struct bcm43xx_wldev *dev,
249 u16 lna, u16 pga, u16 trsw_rx)
251 struct bcm43xx_phy *phy = &dev->phy;
256 lna <<= BCM43xx_PHY_RFOVERVAL_LNA_SHIFT;
257 pga <<= BCM43xx_PHY_RFOVERVAL_PGA_SHIFT;
259 assert((lna & ~BCM43xx_PHY_RFOVERVAL_LNA) == 0);
260 assert((pga & ~BCM43xx_PHY_RFOVERVAL_PGA) == 0);
261 /*FIXME This assertion fails assert((trsw_rx & ~(BCM43xx_PHY_RFOVERVAL_TRSWRX |
262 BCM43xx_PHY_RFOVERVAL_BW)) == 0);
264 trsw_rx &= (BCM43xx_PHY_RFOVERVAL_TRSWRX | BCM43xx_PHY_RFOVERVAL_BW);
266 /* Construct the RF Override Value */
267 rfover = BCM43xx_PHY_RFOVERVAL_UNK;
271 if ((dev->dev->bus->sprom.r1.boardflags_lo & BCM43xx_BFL_EXTLNA) &&
273 rfover |= BCM43xx_PHY_RFOVERVAL_EXTLNA;
275 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL, 0xE300);
276 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL, rfover);
278 rfover |= BCM43xx_PHY_RFOVERVAL_BW_LBW;
279 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL, rfover);
281 rfover |= BCM43xx_PHY_RFOVERVAL_BW_LPF;
282 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL, rfover);
284 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL, 0xF300);
286 pga |= BCM43xx_PHY_PGACTL_UNKNOWN;
287 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL, pga);
289 pga |= BCM43xx_PHY_PGACTL_LOWBANDW;
290 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL, pga);
292 pga |= BCM43xx_PHY_PGACTL_LPF;
293 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL, pga);
296 feedthrough = bcm43xx_phy_read(dev, BCM43xx_PHY_LO_LEAKAGE);
298 /* This is a good place to check if we need to relax a bit,
299 * as this is the main function called regularly
300 * in the LO calibration. */
306 /* TXCTL Register and Value Table.
307 * Returns the "TXCTL Register".
308 * "value" is the "TXCTL Value".
309 * "pad_mix_gain" is the PAD Mixer Gain.
311 static u16 lo_txctl_register_table(struct bcm43xx_wldev *dev,
312 u16 *value, u16 *pad_mix_gain)
314 struct bcm43xx_phy *phy = &dev->phy;
317 if (phy->type == BCM43xx_PHYTYPE_B) {
319 if (phy->radio_rev <= 5) {
327 if (phy->rev >= 2 && phy->radio_rev == 8) {
340 *pad_mix_gain = padmix;
345 static void lo_measure_txctl_values(struct bcm43xx_wldev *dev)
347 struct bcm43xx_phy *phy = &dev->phy;
348 struct bcm43xx_txpower_lo_control *lo = phy->lo_control;
353 static const u8 tx_bias_values[] = {
354 0x09, 0x08, 0x0A, 0x01, 0x00,
355 0x02, 0x05, 0x04, 0x06,
357 static const u8 tx_magn_values[] = {
361 if (!has_loopback_gain(phy)) {
366 int lb_gain; /* Loopback gain (in dB) */
369 lb_gain = phy->max_lb_gain / 2;
372 pga = abs(10 - lb_gain) / 6;
373 pga = limit_value(pga, 0, 15);
380 if ((phy->rev >= 2) &&
381 (phy->radio_ver == 0x2050) &&
382 (phy->radio_rev == 8))
385 if ((10 - lb_gain) < cmp_val)
386 tmp = (10 - lb_gain);
394 radio_pctl_reg = cmp_val;
396 radio_pctl_reg = tmp;
399 bcm43xx_radio_write16(dev, 0x43,
400 (bcm43xx_radio_read16(dev, 0x43)
401 & 0xFFF0) | radio_pctl_reg);
402 bcm43xx_phy_set_baseband_attenuation(dev, 2);
404 reg = lo_txctl_register_table(dev, &mask, NULL);
406 bcm43xx_radio_write16(dev, reg,
407 bcm43xx_radio_read16(dev, reg)
410 if (has_tx_magnification(phy)) {
413 int min_feedth = 0xFFFF;
416 for (i = 0; i < ARRAY_SIZE(tx_magn_values); i++) {
417 tx_magn = tx_magn_values[i];
418 bcm43xx_radio_write16(dev, 0x52,
419 (bcm43xx_radio_read16(dev, 0x52)
420 & 0xFF0F) | tx_magn);
421 for (j = 0; j < ARRAY_SIZE(tx_bias_values); j++) {
422 tx_bias = tx_bias_values[j];
423 bcm43xx_radio_write16(dev, 0x52,
424 (bcm43xx_radio_read16(dev, 0x52)
425 & 0xFFF0) | tx_bias);
426 feedthrough = lo_measure_feedthrough(dev, 0, pga, trsw_rx);
427 if (feedthrough < min_feedth) {
428 lo->tx_bias = tx_bias;
429 lo->tx_magn = tx_magn;
430 min_feedth = feedthrough;
432 if (lo->tx_bias == 0)
435 bcm43xx_radio_write16(dev, 0x52,
436 (bcm43xx_radio_read16(dev, 0x52)
437 & 0xFF00) | lo->tx_bias | lo->tx_magn);
442 bcm43xx_radio_write16(dev, 0x52,
443 bcm43xx_radio_read16(dev, 0x52)
444 & 0xFFF0); /* TX bias == 0 */
448 static void lo_read_power_vector(struct bcm43xx_wldev *dev)
450 struct bcm43xx_phy *phy = &dev->phy;
451 struct bcm43xx_txpower_lo_control *lo = phy->lo_control;
454 u64 power_vector = 0;
455 int rf_offset, bb_offset;
456 struct bcm43xx_loctl *loctl;
458 for (i = 0; i < 8; i += 2) {
459 tmp = bcm43xx_shm_read16(dev, BCM43xx_SHM_SHARED,
461 /* Clear the top byte. We get holes in the bitmap... */
463 power_vector |= (tmp << (i * 8));
464 /* Clear the vector on the device. */
465 bcm43xx_shm_write16(dev, BCM43xx_SHM_SHARED,
470 lo->power_vector = power_vector;
471 power_vector = lo->power_vector;
473 for (i = 0; i < 64; i++) {
474 if (power_vector & ((u64)1ULL << i)) {
475 /* Now figure out which bcm43xx_loctl corresponds
478 rf_offset = i / lo->rfatt_list.len;
479 bb_offset = i % lo->rfatt_list.len;//FIXME?
480 loctl = bcm43xx_get_lo_g_ctl(dev, &lo->rfatt_list.list[rf_offset],
481 &lo->bbatt_list.list[bb_offset]);
482 /* And mark it as "used", as the device told us
483 * through the bitmap it is using it.
490 /* 802.11/LO/GPHY/MeasuringGains */
491 static void lo_measure_gain_values(struct bcm43xx_wldev *dev,
495 struct bcm43xx_phy *phy = &dev->phy;
501 if (has_loopback_gain(phy)) {
506 trsw_rx_gain = phy->trsw_rx_gain / 2;
507 if (max_rx_gain >= trsw_rx_gain) {
508 trsw_rx_gain = max_rx_gain - trsw_rx_gain;
512 trsw_rx_gain = max_rx_gain;
513 if (trsw_rx_gain < 9) {
514 phy->lna_lod_gain = 0;
516 phy->lna_lod_gain = 1;
519 trsw_rx_gain = limit_value(trsw_rx_gain, 0, 0x2D);
520 phy->pga_gain = trsw_rx_gain / 3;
521 if (phy->pga_gain >= 5) {
528 phy->trsw_rx_gain = 0x20;
529 if (max_rx_gain >= 0x14) {
530 phy->lna_lod_gain = 1;
532 } else if (max_rx_gain >= 0x12) {
533 phy->lna_lod_gain = 1;
535 } else if (max_rx_gain >= 0xF) {
536 phy->lna_lod_gain = 1;
539 phy->lna_lod_gain = 0;
544 tmp = bcm43xx_radio_read16(dev, 0x7A);
545 if (phy->lna_lod_gain == 0)
549 bcm43xx_radio_write16(dev, 0x7A, tmp);
552 struct lo_g_saved_values {
562 u16 phy_dacctl_hwpctl;
565 u16 phy_hpwr_tssictl;
567 u16 phy_analogoverval;
579 /* Radio registers */
585 static void lo_measure_setup(struct bcm43xx_wldev *dev,
586 struct lo_g_saved_values *sav)
588 struct ssb_sprom *sprom = &dev->dev->bus->sprom;
589 struct bcm43xx_phy *phy = &dev->phy;
590 struct bcm43xx_txpower_lo_control *lo = phy->lo_control;
593 if (has_hardware_pctl(phy)) {
594 sav->phy_lo_mask = bcm43xx_phy_read(dev, BCM43xx_PHY_LO_MASK);
595 sav->phy_extg_01 = bcm43xx_phy_read(dev, BCM43xx_PHY_EXTG(0x01));
596 sav->phy_dacctl_hwpctl = bcm43xx_phy_read(dev, BCM43xx_PHY_DACCTL);
597 sav->phy_base_14 = bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x14));
598 sav->phy_hpwr_tssictl = bcm43xx_phy_read(dev, BCM43xx_PHY_HPWR_TSSICTL);
600 bcm43xx_phy_write(dev, BCM43xx_PHY_HPWR_TSSICTL,
601 bcm43xx_phy_read(dev, BCM43xx_PHY_HPWR_TSSICTL)
603 bcm43xx_phy_write(dev, BCM43xx_PHY_EXTG(0x01),
604 bcm43xx_phy_read(dev, BCM43xx_PHY_EXTG(0x01))
606 bcm43xx_phy_write(dev, BCM43xx_PHY_DACCTL,
607 bcm43xx_phy_read(dev, BCM43xx_PHY_DACCTL)
609 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x14),
610 bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x14))
613 if (phy->type == BCM43xx_PHYTYPE_B &&
614 phy->radio_ver == 0x2050 &&
615 phy->radio_rev < 6) {
616 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x16), 0x410);
617 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x17), 0x820);
619 if (!lo->rebuild && has_hardware_pctl(phy))
620 lo_read_power_vector(dev);
622 sav->phy_analogover = bcm43xx_phy_read(dev, BCM43xx_PHY_ANALOGOVER);
623 sav->phy_analogoverval = bcm43xx_phy_read(dev, BCM43xx_PHY_ANALOGOVERVAL);
624 sav->phy_rfover = bcm43xx_phy_read(dev, BCM43xx_PHY_RFOVER);
625 sav->phy_rfoverval = bcm43xx_phy_read(dev, BCM43xx_PHY_RFOVERVAL);
626 sav->phy_classctl = bcm43xx_phy_read(dev, BCM43xx_PHY_CLASSCTL);
627 sav->phy_base_3E = bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x3E));
628 sav->phy_crs0 = bcm43xx_phy_read(dev, BCM43xx_PHY_CRS0);
630 bcm43xx_phy_write(dev, BCM43xx_PHY_CLASSCTL,
631 bcm43xx_phy_read(dev, BCM43xx_PHY_CLASSCTL)
633 bcm43xx_phy_write(dev, BCM43xx_PHY_CRS0,
634 bcm43xx_phy_read(dev, BCM43xx_PHY_CRS0)
636 bcm43xx_phy_write(dev, BCM43xx_PHY_ANALOGOVER,
637 bcm43xx_phy_read(dev, BCM43xx_PHY_ANALOGOVER)
639 bcm43xx_phy_write(dev, BCM43xx_PHY_ANALOGOVERVAL,
640 bcm43xx_phy_read(dev, BCM43xx_PHY_ANALOGOVERVAL)
642 if (phy->type == BCM43xx_PHYTYPE_G) {
643 if ((phy->rev >= 7) &&
644 (sprom->r1.boardflags_lo & BCM43xx_BFL_EXTLNA)) {
645 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVER, 0x933);
647 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVER, 0x133);
650 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVER, 0);
652 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x3E), 0);
654 sav->reg_3F4 = bcm43xx_read16(dev, 0x3F4);
655 sav->reg_3E2 = bcm43xx_read16(dev, 0x3E2);
656 sav->radio_43 = bcm43xx_radio_read16(dev, 0x43);
657 sav->radio_7A = bcm43xx_radio_read16(dev, 0x7A);
658 sav->phy_pgactl = bcm43xx_phy_read(dev, BCM43xx_PHY_PGACTL);
659 sav->phy_base_2A = bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x2A));
660 sav->phy_syncctl = bcm43xx_phy_read(dev, BCM43xx_PHY_SYNCCTL);
661 sav->phy_dacctl = bcm43xx_phy_read(dev, BCM43xx_PHY_DACCTL);
663 if (!has_tx_magnification(phy)) {
664 sav->radio_52 = bcm43xx_radio_read16(dev, 0x52);
665 sav->radio_52 &= 0x00F0;
667 if (phy->type == BCM43xx_PHYTYPE_B) {
668 sav->phy_base_30 = bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x30));
669 sav->phy_base_06 = bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x06));
670 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x30), 0x00FF);
671 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x06), 0x3F3F);
673 bcm43xx_write16(dev, 0x3E2,
674 bcm43xx_read16(dev, 0x3E2)
677 bcm43xx_write16(dev, 0x3F4,
678 bcm43xx_read16(dev, 0x3F4)
681 tmp = (phy->type == BCM43xx_PHYTYPE_G) ? BCM43xx_PHY_LO_MASK : BCM43xx_PHY_BASE(0x2E);
682 bcm43xx_phy_write(dev, tmp, 0x007F);
684 tmp = sav->phy_syncctl;
685 bcm43xx_phy_write(dev, BCM43xx_PHY_SYNCCTL, tmp & 0xFF7F);
687 bcm43xx_radio_write16(dev, 0x007A, tmp & 0xFFF0);
689 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x2A), 0x8A3);
690 if (phy->type == BCM43xx_PHYTYPE_G ||
691 (phy->type == BCM43xx_PHYTYPE_B &&
692 phy->radio_ver == 0x2050 &&
693 phy->radio_rev >= 6)) {
694 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x2B), 0x1003);
696 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x2B), 0x0802);
698 bcm43xx_dummy_transmission(dev);
699 bcm43xx_radio_selectchannel(dev, 6, 0);
700 bcm43xx_radio_read16(dev, 0x51); /* dummy read */
701 if (phy->type == BCM43xx_PHYTYPE_G)
702 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x2F), 0);
704 lo_measure_txctl_values(dev);
705 if (phy->type == BCM43xx_PHYTYPE_G && phy->rev >= 3) {
706 bcm43xx_phy_write(dev, BCM43xx_PHY_LO_MASK, 0xC078);
708 if (phy->type == BCM43xx_PHYTYPE_B)
709 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x2E), 0x8078);
711 bcm43xx_phy_write(dev, BCM43xx_PHY_LO_MASK, 0x8078);
715 static void lo_measure_restore(struct bcm43xx_wldev *dev,
716 struct lo_g_saved_values *sav)
718 struct bcm43xx_phy *phy = &dev->phy;
719 struct bcm43xx_txpower_lo_control *lo = phy->lo_control;
723 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL, 0xE300);
724 tmp = (phy->pga_gain << 8);
725 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL, tmp | 0xA0);
727 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL, tmp | 0xA2);
729 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL, tmp | 0xA3);
731 tmp = (phy->pga_gain | 0xEFA0);
732 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL, tmp);
734 if (has_hardware_pctl(phy)) {
735 bcm43xx_gphy_dc_lt_init(dev);
738 bcm43xx_lo_g_adjust_to(dev, 3, 2, 0);
740 bcm43xx_lo_g_adjust(dev);
742 if (phy->type == BCM43xx_PHYTYPE_G) {
744 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x2E), 0xC078);
746 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x2E), 0x8078);
748 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x2F), 0x0202);
750 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x2F), 0x0101);
752 bcm43xx_write16(dev, 0x3F4, sav->reg_3F4);
753 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL, sav->phy_pgactl);
754 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x2A), sav->phy_base_2A);
755 bcm43xx_phy_write(dev, BCM43xx_PHY_SYNCCTL, sav->phy_syncctl);
756 bcm43xx_phy_write(dev, BCM43xx_PHY_DACCTL, sav->phy_dacctl);
757 bcm43xx_radio_write16(dev, 0x43, sav->radio_43);
758 bcm43xx_radio_write16(dev, 0x7A, sav->radio_7A);
759 if (!has_tx_magnification(phy)) {
761 bcm43xx_radio_write16(dev, 0x52,
762 (bcm43xx_radio_read16(dev, 0x52)
765 bcm43xx_write16(dev, 0x3E2, sav->reg_3E2);
766 if (phy->type == BCM43xx_PHYTYPE_B &&
767 phy->radio_ver == 0x2050 &&
768 phy->radio_rev <= 5) {
769 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x30), sav->phy_base_30);
770 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x06), sav->phy_base_06);
773 bcm43xx_phy_write(dev, BCM43xx_PHY_ANALOGOVER, sav->phy_analogover);
774 bcm43xx_phy_write(dev, BCM43xx_PHY_ANALOGOVERVAL, sav->phy_analogoverval);
775 bcm43xx_phy_write(dev, BCM43xx_PHY_CLASSCTL, sav->phy_classctl);
776 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVER, sav->phy_rfover);
777 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL, sav->phy_rfoverval);
778 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x3E), sav->phy_base_3E);
779 bcm43xx_phy_write(dev, BCM43xx_PHY_CRS0, sav->phy_crs0);
781 if (has_hardware_pctl(phy)) {
782 tmp = (sav->phy_lo_mask & 0xBFFF);
783 bcm43xx_phy_write(dev, BCM43xx_PHY_LO_MASK, tmp);
784 bcm43xx_phy_write(dev, BCM43xx_PHY_EXTG(0x01), sav->phy_extg_01);
785 bcm43xx_phy_write(dev, BCM43xx_PHY_DACCTL, sav->phy_dacctl_hwpctl);
786 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x14), sav->phy_base_14);
787 bcm43xx_phy_write(dev, BCM43xx_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
789 bcm43xx_radio_selectchannel(dev, sav->old_channel, 1);
792 struct bcm43xx_lo_g_statemachine {
795 int state_val_multiplier;
797 struct bcm43xx_loctl min_loctl;
800 /* Loop over each possible value in this state. */
801 static int lo_probe_possible_loctls(struct bcm43xx_wldev *dev,
802 struct bcm43xx_loctl *probe_loctl,
803 struct bcm43xx_lo_g_statemachine *d)
805 struct bcm43xx_phy *phy = &dev->phy;
806 struct bcm43xx_txpower_lo_control *lo = phy->lo_control;
807 struct bcm43xx_loctl test_loctl;
808 struct bcm43xx_loctl orig_loctl;
809 struct bcm43xx_loctl prev_loctl = {
818 static const struct bcm43xx_loctl modifiers[] = {
821 { .i = 1, .q = -1, },
822 { .i = 0, .q = -1, },
823 { .i = -1, .q = -1, },
824 { .i = -1, .q = 0, },
825 { .i = -1, .q = 1, },
829 if (d->current_state == 0) {
832 } else if (d->current_state % 2 == 0) {
833 begin = d->current_state - 1;
834 end = d->current_state + 1;
836 begin = d->current_state - 2;
837 end = d->current_state + 2;
844 memcpy(&orig_loctl, probe_loctl, sizeof(struct bcm43xx_loctl));
846 d->current_state = i;
848 assert(i >= 1 && i <= 8);
849 memcpy(&test_loctl, &orig_loctl, sizeof(struct bcm43xx_loctl));
850 test_loctl.i += modifiers[i - 1].i * d->state_val_multiplier;
851 test_loctl.q += modifiers[i - 1].q * d->state_val_multiplier;
852 if ((test_loctl.i != prev_loctl.i ||
853 test_loctl.q != prev_loctl.q) &&
854 (abs(test_loctl.i) <= 16 &&
855 abs(test_loctl.q) <= 16)) {
856 bcm43xx_lo_write(dev, &test_loctl);
857 feedth = lo_measure_feedthrough(dev, phy->lna_gain,
860 if (feedth < d->lowest_feedth) {
861 memcpy(probe_loctl, &test_loctl, sizeof(struct bcm43xx_loctl));
863 d->lowest_feedth = feedth;
864 if ((d->nr_measured < 2) &&
865 (!has_loopback_gain(phy) || lo->rebuild))
869 memcpy(&prev_loctl, &test_loctl, sizeof(prev_loctl));
876 d->current_state = i;
882 static void lo_probe_loctls_statemachine(struct bcm43xx_wldev *dev,
883 struct bcm43xx_loctl *loctl,
886 struct bcm43xx_phy *phy = &dev->phy;
887 struct bcm43xx_txpower_lo_control *lo = phy->lo_control;
888 struct bcm43xx_lo_g_statemachine d;
891 struct bcm43xx_loctl probe_loctl;
892 int max_repeat = 1, repeat_cnt = 0;
895 d.state_val_multiplier = 1;
896 if (has_loopback_gain(phy) && !lo->rebuild)
897 d.state_val_multiplier = 3;
899 memcpy(&d.min_loctl, loctl, sizeof(struct bcm43xx_loctl));
900 if (has_loopback_gain(phy) && lo->rebuild)
903 bcm43xx_lo_write(dev, &d.min_loctl);
904 feedth = lo_measure_feedthrough(dev, phy->lna_gain,
907 if (!lo->rebuild && feedth < 0x258) {
912 feedth = lo_measure_feedthrough(dev, phy->lna_gain,
916 d.lowest_feedth = feedth;
920 assert(d.current_state >= 0 && d.current_state <= 8);
921 memcpy(&probe_loctl, &d.min_loctl, sizeof(struct bcm43xx_loctl));
922 found_lower = lo_probe_possible_loctls(dev, &probe_loctl, &d);
925 if ((probe_loctl.i == d.min_loctl.i) &&
926 (probe_loctl.q == d.min_loctl.q))
928 memcpy(&d.min_loctl, &probe_loctl, sizeof(struct bcm43xx_loctl));
930 } while (d.nr_measured < 24);
931 memcpy(loctl, &d.min_loctl, sizeof(struct bcm43xx_loctl));
933 if (has_loopback_gain(phy)) {
934 if (d.lowest_feedth > 0x1194)
936 else if (d.lowest_feedth < 0x5DC)
938 if (repeat_cnt == 0) {
939 if (d.lowest_feedth <= 0x5DC) {
940 d.state_val_multiplier = 1;
943 d.state_val_multiplier = 2;
944 } else if (repeat_cnt == 2)
945 d.state_val_multiplier = 1;
947 lo_measure_gain_values(dev, *max_rx_gain, has_loopback_gain(phy));
948 } while (++repeat_cnt < max_repeat);
951 static void lo_measure(struct bcm43xx_wldev *dev)
953 struct bcm43xx_phy *phy = &dev->phy;
954 struct bcm43xx_txpower_lo_control *lo = phy->lo_control;
955 struct bcm43xx_loctl loctl = {
959 struct bcm43xx_loctl *ploctl;
963 /* Values from the "TXCTL Register and Value Table" */
968 txctl_reg = lo_txctl_register_table(dev, &txctl_value, &pad_mix_gain);
970 for (rfidx = 0; rfidx < lo->rfatt_list.len; rfidx++) {
972 bcm43xx_radio_write16(dev, 0x43,
973 (bcm43xx_radio_read16(dev, 0x43)
974 & 0xFFF0) | lo->rfatt_list.list[rfidx].att);
975 bcm43xx_radio_write16(dev, txctl_reg,
976 (bcm43xx_radio_read16(dev, txctl_reg)
978 | (lo->rfatt_list.list[rfidx].with_padmix ? txctl_value : 0));
980 for (bbidx = 0; bbidx < lo->bbatt_list.len; bbidx++) {
982 ploctl = bcm43xx_get_lo_g_ctl_nopadmix(dev,
983 &lo->rfatt_list.list[rfidx],
984 &lo->bbatt_list.list[bbidx]);
986 ploctl = bcm43xx_get_lo_g_ctl(dev, &lo->rfatt_list.list[rfidx],
987 &lo->bbatt_list.list[bbidx]);
991 memcpy(&loctl, ploctl, sizeof(loctl));
993 max_rx_gain = lo->rfatt_list.list[rfidx].att * 2;
994 max_rx_gain += lo->bbatt_list.list[bbidx].att / 2;
995 if (lo->rfatt_list.list[rfidx].with_padmix)
996 max_rx_gain -= pad_mix_gain;
997 if (has_loopback_gain(phy))
998 max_rx_gain += phy->max_lb_gain;
999 lo_measure_gain_values(dev, max_rx_gain, has_loopback_gain(phy));
1001 bcm43xx_phy_set_baseband_attenuation(dev, lo->bbatt_list.list[bbidx].att);
1002 lo_probe_loctls_statemachine(dev, &loctl, &max_rx_gain);
1003 if (phy->type == BCM43xx_PHYTYPE_B) {
1007 memcpy(ploctl, &loctl, sizeof(loctl));
1013 static void do_validate_loctl(struct bcm43xx_wldev *dev,
1014 struct bcm43xx_loctl *control)
1016 const int is_initializing = (bcm43xx_status(dev) == BCM43xx_STAT_INITIALIZING);
1018 if (unlikely(abs(control->i) > 16 ||
1019 abs(control->q) > 16 ||
1020 (is_initializing && control->used))) {
1021 printk(KERN_ERR PFX "ERROR: LO control pair validation failed "
1022 "(first: %d, second: %d, used %u)\n",
1023 control->i, control->q, control->used);
1026 static void validate_all_loctls(struct bcm43xx_wldev *dev)
1028 bcm43xx_call_for_each_loctl(dev, do_validate_loctl);
1030 #else /* BCM43xx_DEBUG */
1031 static inline void validate_all_loctls(struct bcm43xx_wldev *dev) { }
1032 #endif /* BCM43xx_DEBUG */
1034 void bcm43xx_lo_g_measure(struct bcm43xx_wldev *dev)
1036 struct bcm43xx_phy *phy = &dev->phy;
1037 struct lo_g_saved_values sav;
1039 assert(phy->type == BCM43xx_PHYTYPE_B ||
1040 phy->type == BCM43xx_PHYTYPE_G);
1042 sav.old_channel = phy->channel;
1043 lo_measure_setup(dev, &sav);
1045 lo_measure_restore(dev, &sav);
1047 validate_all_loctls(dev);
1049 phy->lo_control->lo_measured = 1;
1050 phy->lo_control->rebuild = 0;
1053 void bcm43xx_lo_g_adjust(struct bcm43xx_wldev *dev)
1055 bcm43xx_lo_write(dev, bcm43xx_lo_g_ctl_current(dev));
1058 static inline void fixup_rfatt_for_txcontrol(struct bcm43xx_rfatt *rf,
1061 if (tx_control & BCM43xx_TXCTL_TXMIX) {
1067 void bcm43xx_lo_g_adjust_to(struct bcm43xx_wldev *dev,
1068 u16 rfatt, u16 bbatt, u16 tx_control)
1070 struct bcm43xx_rfatt rf;
1071 struct bcm43xx_bbatt bb;
1072 struct bcm43xx_loctl *loctl;
1074 memset(&rf, 0, sizeof(rf));
1075 memset(&bb, 0, sizeof(bb));
1078 fixup_rfatt_for_txcontrol(&rf, tx_control);
1079 loctl = bcm43xx_get_lo_g_ctl(dev, &rf, &bb);
1080 bcm43xx_lo_write(dev, loctl);
1083 struct bcm43xx_loctl * bcm43xx_lo_g_ctl_current(struct bcm43xx_wldev *dev)
1085 struct bcm43xx_phy *phy = &dev->phy;
1086 struct bcm43xx_rfatt rf;
1088 memcpy(&rf, &phy->rfatt, sizeof(rf));
1089 fixup_rfatt_for_txcontrol(&rf, phy->tx_control);
1091 return bcm43xx_get_lo_g_ctl(dev, &rf, &phy->bbatt);
1094 static void do_mark_unused(struct bcm43xx_wldev *dev,
1095 struct bcm43xx_loctl *control)
1100 void bcm43xx_lo_g_ctl_mark_all_unused(struct bcm43xx_wldev *dev)
1102 struct bcm43xx_phy *phy = &dev->phy;
1103 struct bcm43xx_txpower_lo_control *lo = phy->lo_control;
1105 bcm43xx_call_for_each_loctl(dev, do_mark_unused);
1109 void bcm43xx_lo_g_ctl_mark_cur_used(struct bcm43xx_wldev *dev)
1111 bcm43xx_lo_g_ctl_current(dev)->used = 1;