New: mac80211-based bcm43xx driver from the wireless-dev tree
[openwrt/openwrt.git] / package / bcm43xx-mac80211 / src / bcm43xx / bcm43xx_phy.c
1 /*
2
3 Broadcom BCM43xx wireless driver
4
5 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
6 Copyright (c) 2005, 2006 Stefano Brivio <st3@riseup.net>
7 Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
8 Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
9 Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; see the file COPYING. If not, write to
23 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
24 Boston, MA 02110-1301, USA.
25
26 */
27
28 #include <linux/delay.h>
29 #include <linux/types.h>
30
31 #include "bcm43xx.h"
32 #include "bcm43xx_phy.h"
33 #include "bcm43xx_main.h"
34 #include "bcm43xx_tables.h"
35 #include "bcm43xx_power.h"
36 #include "bcm43xx_lo.h"
37
38
39 static const s8 bcm43xx_tssi2dbm_b_table[] = {
40 0x4D, 0x4C, 0x4B, 0x4A,
41 0x4A, 0x49, 0x48, 0x47,
42 0x47, 0x46, 0x45, 0x45,
43 0x44, 0x43, 0x42, 0x42,
44 0x41, 0x40, 0x3F, 0x3E,
45 0x3D, 0x3C, 0x3B, 0x3A,
46 0x39, 0x38, 0x37, 0x36,
47 0x35, 0x34, 0x32, 0x31,
48 0x30, 0x2F, 0x2D, 0x2C,
49 0x2B, 0x29, 0x28, 0x26,
50 0x25, 0x23, 0x21, 0x1F,
51 0x1D, 0x1A, 0x17, 0x14,
52 0x10, 0x0C, 0x06, 0x00,
53 -7, -7, -7, -7,
54 -7, -7, -7, -7,
55 -7, -7, -7, -7,
56 };
57
58 static const s8 bcm43xx_tssi2dbm_g_table[] = {
59 77, 77, 77, 76,
60 76, 76, 75, 75,
61 74, 74, 73, 73,
62 73, 72, 72, 71,
63 71, 70, 70, 69,
64 68, 68, 67, 67,
65 66, 65, 65, 64,
66 63, 63, 62, 61,
67 60, 59, 58, 57,
68 56, 55, 54, 53,
69 52, 50, 49, 47,
70 45, 43, 40, 37,
71 33, 28, 22, 14,
72 5, -7, -20, -20,
73 -20, -20, -20, -20,
74 -20, -20, -20, -20,
75 };
76
77 const u8 bcm43xx_radio_channel_codes_bg[] = {
78 12, 17, 22, 27,
79 32, 37, 42, 47,
80 52, 57, 62, 67,
81 72, 84,
82 };
83
84
85 static void bcm43xx_phy_initg(struct bcm43xx_wldev *dev);
86
87 /* Reverse the bits of a 4bit value.
88 * Example: 1101 is flipped 1011
89 */
90 static u16 flip_4bit(u16 value)
91 {
92 u16 flipped = 0x0000;
93
94 assert((value & ~0x000F) == 0x0000);
95
96 flipped |= (value & 0x0001) << 3;
97 flipped |= (value & 0x0002) << 1;
98 flipped |= (value & 0x0004) >> 1;
99 flipped |= (value & 0x0008) >> 3;
100
101 return flipped;
102 }
103
104 static void generate_rfatt_list(struct bcm43xx_wldev *dev,
105 struct bcm43xx_rfatt_list *list)
106 {
107 struct bcm43xx_phy *phy = &dev->phy;
108
109 /* APHY.rev < 5 || GPHY.rev < 6 */
110 static const struct bcm43xx_rfatt rfatt_0[] = {
111 { .att = 3, .with_padmix = 0, },
112 { .att = 1, .with_padmix = 0, },
113 { .att = 5, .with_padmix = 0, },
114 { .att = 7, .with_padmix = 0, },
115 { .att = 9, .with_padmix = 0, },
116 { .att = 2, .with_padmix = 0, },
117 { .att = 0, .with_padmix = 0, },
118 { .att = 4, .with_padmix = 0, },
119 { .att = 6, .with_padmix = 0, },
120 { .att = 8, .with_padmix = 0, },
121 { .att = 1, .with_padmix = 1, },
122 { .att = 2, .with_padmix = 1, },
123 { .att = 3, .with_padmix = 1, },
124 { .att = 4, .with_padmix = 1, },
125 };
126 /* Radio.rev == 8 && Radio.version == 0x2050 */
127 static const struct bcm43xx_rfatt rfatt_1[] = {
128 { .att = 2, .with_padmix = 1, },
129 { .att = 4, .with_padmix = 1, },
130 { .att = 6, .with_padmix = 1, },
131 { .att = 8, .with_padmix = 1, },
132 { .att = 10, .with_padmix = 1, },
133 { .att = 12, .with_padmix = 1, },
134 { .att = 14, .with_padmix = 1, },
135 };
136 /* Otherwise */
137 static const struct bcm43xx_rfatt rfatt_2[] = {
138 { .att = 0, .with_padmix = 1, },
139 { .att = 2, .with_padmix = 1, },
140 { .att = 4, .with_padmix = 1, },
141 { .att = 6, .with_padmix = 1, },
142 { .att = 8, .with_padmix = 1, },
143 { .att = 9, .with_padmix = 1, },
144 { .att = 9, .with_padmix = 1, },
145 };
146
147 if ((phy->type == BCM43xx_PHYTYPE_A && phy->rev < 5) ||
148 (phy->type == BCM43xx_PHYTYPE_G && phy->rev < 6)) {
149 /* Software pctl */
150 list->list = rfatt_0;
151 list->len = ARRAY_SIZE(rfatt_0);
152 list->min_val = 0;
153 list->max_val = 9;
154 return;
155 }
156 if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) {
157 /* Hardware pctl */
158 list->list = rfatt_1;
159 list->len = ARRAY_SIZE(rfatt_1);
160 list->min_val = 2;
161 list->max_val = 14;
162 return;
163 }
164 /* Hardware pctl */
165 list->list = rfatt_2;
166 list->len = ARRAY_SIZE(rfatt_2);
167 list->min_val = 0;
168 list->max_val = 9;
169 }
170
171 static void generate_bbatt_list(struct bcm43xx_wldev *dev,
172 struct bcm43xx_bbatt_list *list)
173 {
174 static const struct bcm43xx_bbatt bbatt_0[] = {
175 { .att = 0, },
176 { .att = 1, },
177 { .att = 2, },
178 { .att = 3, },
179 { .att = 4, },
180 { .att = 5, },
181 { .att = 6, },
182 { .att = 7, },
183 { .att = 8, },
184 };
185
186 list->list = bbatt_0;
187 list->len = ARRAY_SIZE(bbatt_0);
188 list->min_val = 0;
189 list->max_val = 8;
190 }
191
192 static void bcm43xx_shm_clear_tssi(struct bcm43xx_wldev *dev)
193 {
194 struct bcm43xx_phy *phy = &dev->phy;
195
196 switch (phy->type) {
197 case BCM43xx_PHYTYPE_A:
198 bcm43xx_shm_write16(dev, BCM43xx_SHM_SHARED, 0x0068, 0x7F7F);
199 bcm43xx_shm_write16(dev, BCM43xx_SHM_SHARED, 0x006a, 0x7F7F);
200 break;
201 case BCM43xx_PHYTYPE_B:
202 case BCM43xx_PHYTYPE_G:
203 bcm43xx_shm_write16(dev, BCM43xx_SHM_SHARED, 0x0058, 0x7F7F);
204 bcm43xx_shm_write16(dev, BCM43xx_SHM_SHARED, 0x005a, 0x7F7F);
205 bcm43xx_shm_write16(dev, BCM43xx_SHM_SHARED, 0x0070, 0x7F7F);
206 bcm43xx_shm_write16(dev, BCM43xx_SHM_SHARED, 0x0072, 0x7F7F);
207 break;
208 }
209 }
210
211 void bcm43xx_raw_phy_lock(struct bcm43xx_wldev *dev)
212 {
213 struct bcm43xx_phy *phy = &dev->phy;
214
215 assert(irqs_disabled());
216 if (bcm43xx_read32(dev, BCM43xx_MMIO_STATUS_BITFIELD) == 0) {
217 phy->locked = 0;
218 return;
219 }
220 if (dev->dev->id.revision < 3) {
221 bcm43xx_mac_suspend(dev);
222 spin_lock(&phy->lock);
223 } else {
224 if (!bcm43xx_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
225 bcm43xx_power_saving_ctl_bits(dev, -1, 1);
226 }
227 phy->locked = 1;
228 }
229
230 void bcm43xx_raw_phy_unlock(struct bcm43xx_wldev *dev)
231 {
232 struct bcm43xx_phy *phy = &dev->phy;
233
234 assert(irqs_disabled());
235 if (dev->dev->id.revision < 3) {
236 if (phy->locked) {
237 spin_unlock(&phy->lock);
238 bcm43xx_mac_enable(dev);
239 }
240 } else {
241 if (!bcm43xx_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
242 bcm43xx_power_saving_ctl_bits(dev, -1, -1);
243 }
244 phy->locked = 0;
245 }
246
247 /* Different PHYs require different register routing flags.
248 * This adjusts (and does sanity checks on) the routing flags.
249 */
250 static inline u16 adjust_phyreg_for_phytype(struct bcm43xx_phy *phy,
251 u16 offset)
252 {
253 if (phy->type == BCM43xx_PHYTYPE_A) {
254 /* OFDM registers are base-registers for the A-PHY. */
255 offset &= ~BCM43xx_PHYROUTE_OFDM_GPHY;
256 }
257 if (offset & BCM43xx_PHYROUTE_EXT_GPHY) {
258 /* Ext-G registers are only available on G-PHYs */
259 if (phy->type != BCM43xx_PHYTYPE_G) {
260 dprintk(KERN_ERR PFX "EXT-G PHY access at "
261 "0x%04X on %u type PHY\n",
262 offset, phy->type);
263 }
264 }
265
266 return offset;
267 }
268
269 u16 bcm43xx_phy_read(struct bcm43xx_wldev *dev, u16 offset)
270 {
271 struct bcm43xx_phy *phy = &dev->phy;
272
273 offset = adjust_phyreg_for_phytype(phy, offset);
274 bcm43xx_write16(dev, BCM43xx_MMIO_PHY_CONTROL, offset);
275 return bcm43xx_read16(dev, BCM43xx_MMIO_PHY_DATA);
276 }
277
278 void bcm43xx_phy_write(struct bcm43xx_wldev *dev, u16 offset, u16 val)
279 {
280 struct bcm43xx_phy *phy = &dev->phy;
281
282 offset = adjust_phyreg_for_phytype(phy, offset);
283 bcm43xx_write16(dev, BCM43xx_MMIO_PHY_CONTROL, offset);
284 mmiowb();
285 bcm43xx_write16(dev, BCM43xx_MMIO_PHY_DATA, val);
286 }
287
288 /* This func is called "PHY calibrate" in the specs... */
289 void bcm43xx_phy_early_init(struct bcm43xx_wldev *dev)
290 {
291 struct bcm43xx_phy *phy = &dev->phy;
292 struct bcm43xx_txpower_lo_control *lo = phy->lo_control;
293
294 bcm43xx_read32(dev, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */
295 if (phy->type == BCM43xx_PHYTYPE_B ||
296 phy->type == BCM43xx_PHYTYPE_G) {
297 generate_rfatt_list(dev, &lo->rfatt_list);
298 generate_bbatt_list(dev, &lo->bbatt_list);
299 }
300 if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) {
301 /* Workaround: Temporarly disable gmode through the early init
302 * phase, as the gmode stuff is not needed for phy rev 1 */
303 phy->gmode = 0;
304 bcm43xx_wireless_core_reset(dev, 0);
305 bcm43xx_phy_initg(dev);
306 phy->gmode = 1;
307 bcm43xx_wireless_core_reset(dev, BCM43xx_TMSLOW_GMODE);
308 }
309 }
310
311 /* GPHY_TSSI_Power_Lookup_Table_Init */
312 static void bcm43xx_gphy_tssi_power_lt_init(struct bcm43xx_wldev *dev)
313 {
314 struct bcm43xx_phy *phy = &dev->phy;
315 int i;
316 u16 value;
317
318 for (i = 0; i < 32; i++)
319 bcm43xx_ofdmtab_write16(dev, 0x3C20, i, phy->tssi2dbm[i]);
320 for (i = 32; i < 64; i++)
321 bcm43xx_ofdmtab_write16(dev, 0x3C00, i - 32, phy->tssi2dbm[i]);
322 for (i = 0; i < 64; i += 2) {
323 value = (u16)phy->tssi2dbm[i];
324 value |= ((u16)phy->tssi2dbm[i + 1]) << 8;
325 bcm43xx_phy_write(dev, 0x380 + (i / 2), value);
326 }
327 }
328
329 /* GPHY_Gain_Lookup_Table_Init */
330 static void bcm43xx_gphy_gain_lt_init(struct bcm43xx_wldev *dev)
331 {
332 struct bcm43xx_phy *phy = &dev->phy;
333 struct bcm43xx_txpower_lo_control *lo = phy->lo_control;
334 u16 nr_written = 0;
335 u16 tmp;
336 u8 rf, bb;
337
338 if (!lo->lo_measured) {
339 bcm43xx_phy_write(dev, 0x3FF, 0);
340 return;
341 }
342
343 for (rf = 0; rf < lo->rfatt_list.len; rf++) {
344 for (bb = 0; bb < lo->bbatt_list.len; bb++) {
345 if (nr_written >= 0x40)
346 return;
347 tmp = lo->bbatt_list.list[bb].att;
348 tmp <<= 8;
349 if (phy->radio_rev == 8)
350 tmp |= 0x50;
351 else
352 tmp |= 0x40;
353 tmp |= lo->rfatt_list.list[rf].att;
354 bcm43xx_phy_write(dev, 0x3C0 + nr_written,
355 tmp);
356 nr_written++;
357 }
358 }
359 }
360
361 /* GPHY_DC_Lookup_Table */
362 void bcm43xx_gphy_dc_lt_init(struct bcm43xx_wldev *dev)
363 {
364 struct bcm43xx_phy *phy = &dev->phy;
365 struct bcm43xx_txpower_lo_control *lo = phy->lo_control;
366 struct bcm43xx_loctl *loctl0;
367 struct bcm43xx_loctl *loctl1;
368 int i;
369 int rf_offset, bb_offset;
370 u16 tmp;
371
372 for (i = 0;
373 i < lo->rfatt_list.len + lo->bbatt_list.len;
374 i += 2) {
375 rf_offset = i / lo->rfatt_list.len;
376 bb_offset = i % lo->rfatt_list.len;
377
378 loctl0 = bcm43xx_get_lo_g_ctl(dev, &lo->rfatt_list.list[rf_offset],
379 &lo->bbatt_list.list[bb_offset]);
380 if (i + 1 < lo->rfatt_list.len * lo->bbatt_list.len) {
381 rf_offset = (i + 1) / lo->rfatt_list.len;
382 bb_offset = (i + 1) % lo->rfatt_list.len;
383
384 loctl1 = bcm43xx_get_lo_g_ctl(dev, &lo->rfatt_list.list[rf_offset],
385 &lo->bbatt_list.list[bb_offset]);
386 } else
387 loctl1 = loctl0;
388
389 tmp = ((u16)loctl0->q & 0xF);
390 tmp |= ((u16)loctl0->i & 0xF) << 4;
391 tmp |= ((u16)loctl1->q & 0xF) << 8;
392 tmp |= ((u16)loctl1->i & 0xF) << 12;//FIXME?
393 bcm43xx_phy_write(dev, 0x3A0 + (i / 2),
394 tmp);
395 }
396 }
397
398 static void hardware_pctl_init_aphy(struct bcm43xx_wldev *dev)
399 {
400 //TODO
401 }
402
403 static void hardware_pctl_init_gphy(struct bcm43xx_wldev *dev)
404 {
405 struct bcm43xx_phy *phy = &dev->phy;
406
407 bcm43xx_phy_write(dev, 0x0036,
408 (bcm43xx_phy_read(dev, 0x0036) & 0xFFC0)
409 | (phy->tgt_idle_tssi - phy->cur_idle_tssi));
410 bcm43xx_phy_write(dev, 0x0478,
411 (bcm43xx_phy_read(dev, 0x0478) & 0xFF00)
412 | (phy->tgt_idle_tssi - phy->cur_idle_tssi));
413 bcm43xx_gphy_tssi_power_lt_init(dev);
414 bcm43xx_gphy_gain_lt_init(dev);
415 bcm43xx_phy_write(dev, 0x0060,
416 bcm43xx_phy_read(dev, 0x0060) & 0xFFBF);
417 bcm43xx_phy_write(dev, 0x0014, 0x0000);
418
419 assert(phy->rev >= 6);
420 bcm43xx_phy_write(dev, 0x0478,
421 bcm43xx_phy_read(dev, 0x0478)
422 | 0x0800);
423 bcm43xx_phy_write(dev, 0x0478,
424 bcm43xx_phy_read(dev, 0x0478)
425 & 0xFEFF);
426 bcm43xx_phy_write(dev, 0x0801,
427 bcm43xx_phy_read(dev, 0x0801)
428 & 0xFFBF);
429
430 bcm43xx_gphy_dc_lt_init(dev);
431 }
432
433 /* HardwarePowerControl for A and G PHY.
434 * This does nothing, if the card does not have HW PCTL
435 */
436 static void bcm43xx_hardware_pctl_init(struct bcm43xx_wldev *dev)
437 {
438 struct bcm43xx_phy *phy = &dev->phy;
439
440 if (!has_hardware_pctl(phy))
441 return;
442 if (phy->type == BCM43xx_PHYTYPE_A) {
443 hardware_pctl_init_aphy(dev);
444 return;
445 }
446 if (phy->type == BCM43xx_PHYTYPE_G) {
447 hardware_pctl_init_gphy(dev);
448 return;
449 }
450 assert(0);
451 }
452
453 static void bcm43xx_hardware_pctl_early_init(struct bcm43xx_wldev *dev)
454 {
455 struct bcm43xx_phy *phy = &dev->phy;
456
457 if (!has_hardware_pctl(phy)) {
458 bcm43xx_phy_write(dev, 0x047A, 0xC111);
459 return;
460 }
461
462 bcm43xx_phy_write(dev, 0x0036,
463 bcm43xx_phy_read(dev, 0x0036) & 0xFEFF);
464 bcm43xx_phy_write(dev, 0x002F, 0x0202);
465 bcm43xx_phy_write(dev, 0x047C,
466 bcm43xx_phy_read(dev, 0x047C) | 0x0002);
467 bcm43xx_phy_write(dev, 0x047A,
468 bcm43xx_phy_read(dev, 0x047A) | 0xF000);
469 if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) {
470 bcm43xx_phy_write(dev, 0x047A,
471 (bcm43xx_phy_read(dev, 0x047A)
472 & 0xFF0F) | 0x0010);
473 bcm43xx_phy_write(dev, 0x005D,
474 bcm43xx_phy_read(dev, 0x005D)
475 | 0x8000);
476 bcm43xx_phy_write(dev, 0x004E,
477 (bcm43xx_phy_read(dev, 0x004E)
478 & 0xFFC0) | 0x0010);
479 bcm43xx_phy_write(dev, 0x002E, 0xC07F);
480 bcm43xx_phy_write(dev, 0x0036,
481 bcm43xx_phy_read(dev, 0x0036)
482 | 0x0400);
483 } else {
484 bcm43xx_phy_write(dev, 0x0036,
485 bcm43xx_phy_read(dev, 0x0036)
486 | 0x0200);
487 bcm43xx_phy_write(dev, 0x0036,
488 bcm43xx_phy_read(dev, 0x0036)
489 | 0x0400);
490 bcm43xx_phy_write(dev, 0x005D,
491 bcm43xx_phy_read(dev, 0x005D)
492 & 0x7FFF);
493 bcm43xx_phy_write(dev, 0x004F,
494 bcm43xx_phy_read(dev, 0x004F)
495 & 0xFFFE);
496 bcm43xx_phy_write(dev, 0x004E,
497 (bcm43xx_phy_read(dev, 0x004E)
498 & 0xFFC0) | 0x0010);
499 bcm43xx_phy_write(dev, 0x002E, 0xC07F);
500 bcm43xx_phy_write(dev, 0x047A,
501 (bcm43xx_phy_read(dev, 0x047A)
502 & 0xFF0F) | 0x0010);
503 }
504 }
505
506 /* Intialize B/G PHY power control
507 * as described in http://bcm-specs.sipsolutions.net/InitPowerControl
508 */
509 static void bcm43xx_phy_init_pctl(struct bcm43xx_wldev *dev)
510 {
511 struct ssb_bus *bus = dev->dev->bus;
512 struct bcm43xx_phy *phy = &dev->phy;
513
514 if ((bus->board_vendor == SSB_BOARDVENDOR_BCM) &&
515 (bus->board_type == SSB_BOARD_BU4306))
516 return;
517
518 bcm43xx_phy_write(dev, 0x0028, 0x8018);
519
520 /* This does something with the Analog... */
521 bcm43xx_write16(dev, BCM43xx_MMIO_PHY0,
522 bcm43xx_read16(dev, BCM43xx_MMIO_PHY0)
523 & 0xFFDF);
524
525 if (phy->type == BCM43xx_PHYTYPE_G && !phy->gmode)
526 return;
527 bcm43xx_hardware_pctl_early_init(dev);
528 if (phy->cur_idle_tssi == 0) {
529 if (phy->radio_ver == 0x2050 && phy->analog == 0) {
530 bcm43xx_radio_write16(dev, 0x0076,
531 (bcm43xx_radio_read16(dev, 0x0076)
532 & 0x00F7) | 0x0084);
533 } else {
534 if (phy->radio_rev == 8)
535 bcm43xx_radio_set_txpower_bg(dev, 0xB, 0x1F, 0);
536 else
537 bcm43xx_radio_set_txpower_bg(dev, 0xB, 9, 0);
538 }
539 bcm43xx_dummy_transmission(dev);
540 phy->cur_idle_tssi = bcm43xx_phy_read(dev, BCM43xx_PHY_ITSSI);
541 if (BCM43xx_DEBUG) {
542 /* Current-Idle-TSSI sanity check. */
543 if (abs(phy->cur_idle_tssi - phy->tgt_idle_tssi) >= 20) {
544 dprintk(KERN_ERR PFX "!WARNING! Idle-TSSI phy->cur_idle_tssi "
545 "measuring failed. (cur=%d, tgt=%d). Disabling TX power "
546 "adjustment.\n", phy->cur_idle_tssi, phy->tgt_idle_tssi);
547 phy->cur_idle_tssi = 0;
548 }
549 }
550
551 if (phy->radio_ver == 0x2050 && phy->analog == 0) {
552 bcm43xx_radio_write16(dev, 0x0076,
553 bcm43xx_radio_read16(dev, 0x0076)
554 & 0xFF7B);
555 } else
556 bcm43xx_radio_set_txpower_bg(dev, -1, -1, -1);
557 }
558 bcm43xx_hardware_pctl_init(dev);
559 bcm43xx_shm_clear_tssi(dev);
560 }
561
562 static void bcm43xx_phy_agcsetup(struct bcm43xx_wldev *dev)
563 {
564 struct bcm43xx_phy *phy = &dev->phy;
565 u16 offset = 0x0000;
566
567 if (phy->rev == 1)
568 offset = 0x4C00;
569
570 bcm43xx_ofdmtab_write16(dev, offset, 0, 0x00FE);
571 bcm43xx_ofdmtab_write16(dev, offset, 1, 0x000D);
572 bcm43xx_ofdmtab_write16(dev, offset, 2, 0x0013);
573 bcm43xx_ofdmtab_write16(dev, offset, 3, 0x0019);
574
575 if (phy->rev == 1) {
576 bcm43xx_ofdmtab_write16(dev, 0x1800, 0, 0x2710);
577 bcm43xx_ofdmtab_write16(dev, 0x1801, 0, 0x9B83);
578 bcm43xx_ofdmtab_write16(dev, 0x1802, 0, 0x9B83);
579 bcm43xx_ofdmtab_write16(dev, 0x1803, 0, 0x0F8D);
580 bcm43xx_phy_write(dev, 0x0455, 0x0004);
581 }
582
583 bcm43xx_phy_write(dev, 0x04A5,
584 (bcm43xx_phy_read(dev, 0x04A5)
585 & 0x00FF) | 0x5700);
586 bcm43xx_phy_write(dev, 0x041A,
587 (bcm43xx_phy_read(dev, 0x041A)
588 & 0xFF80) | 0x000F);
589 bcm43xx_phy_write(dev, 0x041A,
590 (bcm43xx_phy_read(dev, 0x041A)
591 & 0xC07F) | 0x2B80);
592 bcm43xx_phy_write(dev, 0x048C,
593 (bcm43xx_phy_read(dev, 0x048C)
594 & 0xF0FF) | 0x0300);
595
596 bcm43xx_radio_write16(dev, 0x007A,
597 bcm43xx_radio_read16(dev, 0x007A)
598 | 0x0008);
599
600 bcm43xx_phy_write(dev, 0x04A0,
601 (bcm43xx_phy_read(dev, 0x04A0)
602 & 0xFFF0) | 0x0008);
603 bcm43xx_phy_write(dev, 0x04A1,
604 (bcm43xx_phy_read(dev, 0x04A1)
605 & 0xF0FF) | 0x0600);
606 bcm43xx_phy_write(dev, 0x04A2,
607 (bcm43xx_phy_read(dev, 0x04A2)
608 & 0xF0FF) | 0x0700);
609 bcm43xx_phy_write(dev, 0x04A0,
610 (bcm43xx_phy_read(dev, 0x04A0)
611 & 0xF0FF) | 0x0100);
612
613 if (phy->rev == 1) {
614 bcm43xx_phy_write(dev, 0x04A2,
615 (bcm43xx_phy_read(dev, 0x04A2)
616 & 0xFFF0) | 0x0007);
617 }
618
619 bcm43xx_phy_write(dev, 0x0488,
620 (bcm43xx_phy_read(dev, 0x0488)
621 & 0xFF00) | 0x001C);
622 bcm43xx_phy_write(dev, 0x0488,
623 (bcm43xx_phy_read(dev, 0x0488)
624 & 0xC0FF) | 0x0200);
625 bcm43xx_phy_write(dev, 0x0496,
626 (bcm43xx_phy_read(dev, 0x0496)
627 & 0xFF00) | 0x001C);
628 bcm43xx_phy_write(dev, 0x0489,
629 (bcm43xx_phy_read(dev, 0x0489)
630 & 0xFF00) | 0x0020);
631 bcm43xx_phy_write(dev, 0x0489,
632 (bcm43xx_phy_read(dev, 0x0489)
633 & 0xC0FF) | 0x0200);
634 bcm43xx_phy_write(dev, 0x0482,
635 (bcm43xx_phy_read(dev, 0x0482)
636 & 0xFF00) | 0x002E);
637 bcm43xx_phy_write(dev, 0x0496,
638 (bcm43xx_phy_read(dev, 0x0496)
639 & 0x00FF) | 0x1A00);
640 bcm43xx_phy_write(dev, 0x0481,
641 (bcm43xx_phy_read(dev, 0x0481)
642 & 0xFF00) | 0x0028);
643 bcm43xx_phy_write(dev, 0x0481,
644 (bcm43xx_phy_read(dev, 0x0481)
645 & 0x00FF) | 0x2C00);
646
647 if (phy->rev == 1) {
648 bcm43xx_phy_write(dev, 0x0430, 0x092B);
649 bcm43xx_phy_write(dev, 0x041B,
650 (bcm43xx_phy_read(dev, 0x041B)
651 & 0xFFE1) | 0x0002);
652 } else {
653 bcm43xx_phy_write(dev, 0x041B,
654 bcm43xx_phy_read(dev, 0x041B)
655 & 0xFFE1);
656 bcm43xx_phy_write(dev, 0x041F, 0x287A);
657 bcm43xx_phy_write(dev, 0x0420,
658 (bcm43xx_phy_read(dev, 0x0420)
659 & 0xFFF0) | 0x0004);
660 }
661
662 if (phy->rev >= 6) {
663 bcm43xx_phy_write(dev, 0x0422, 0x287A);
664 bcm43xx_phy_write(dev, 0x0420,
665 (bcm43xx_phy_read(dev, 0x0420)
666 & 0x0FFF) | 0x3000);
667 }
668
669 bcm43xx_phy_write(dev, 0x04A8,
670 (bcm43xx_phy_read(dev, 0x04A8)
671 & 0x8080) | 0x7874);
672 bcm43xx_phy_write(dev, 0x048E, 0x1C00);
673
674 offset = 0x0800;
675 if (phy->rev == 1) {
676 offset = 0x5400;
677 bcm43xx_phy_write(dev, 0x04AB,
678 (bcm43xx_phy_read(dev, 0x04AB)
679 & 0xF0FF) | 0x0600);
680 bcm43xx_phy_write(dev, 0x048B, 0x005E);
681 bcm43xx_phy_write(dev, 0x048C,
682 (bcm43xx_phy_read(dev, 0x048C)
683 & 0xFF00) | 0x001E);
684 bcm43xx_phy_write(dev, 0x048D, 0x0002);
685 }
686 bcm43xx_ofdmtab_write16(dev, offset, 0, 0x00);
687 bcm43xx_ofdmtab_write16(dev, offset, 1, 0x07);
688 bcm43xx_ofdmtab_write16(dev, offset, 2, 0x10);
689 bcm43xx_ofdmtab_write16(dev, offset, 3, 0x1C);
690
691 if (phy->rev >= 6) {
692 bcm43xx_phy_write(dev, 0x0426,
693 bcm43xx_phy_read(dev, 0x0426)
694 & 0xFFFC);
695 bcm43xx_phy_write(dev, 0x0426,
696 bcm43xx_phy_read(dev, 0x0426)
697 & 0xEFFF);
698 }
699 }
700
701 static void bcm43xx_phy_setupg(struct bcm43xx_wldev *dev)
702 {
703 struct ssb_bus *bus = dev->dev->bus;
704 struct bcm43xx_phy *phy = &dev->phy;
705 u16 i;
706
707 assert(phy->type == BCM43xx_PHYTYPE_G);
708 if (phy->rev == 1) {
709 bcm43xx_phy_write(dev, 0x0406, 0x4F19);
710 bcm43xx_phy_write(dev, BCM43xx_PHY_G_CRS,
711 (bcm43xx_phy_read(dev, BCM43xx_PHY_G_CRS) & 0xFC3F) | 0x0340);
712 bcm43xx_phy_write(dev, 0x042C, 0x005A);
713 bcm43xx_phy_write(dev, 0x0427, 0x001A);
714
715 for (i = 0; i < BCM43xx_TAB_FINEFREQG_SIZE; i++)
716 bcm43xx_ofdmtab_write16(dev, 0x5800, i, bcm43xx_tab_finefreqg[i]);
717 for (i = 0; i < BCM43xx_TAB_NOISEG1_SIZE; i++)
718 bcm43xx_ofdmtab_write16(dev, 0x1800, i, bcm43xx_tab_noiseg1[i]);
719 for (i = 0; i < BCM43xx_TAB_ROTOR_SIZE; i++)
720 bcm43xx_ofdmtab_write16(dev, 0x2000, i, bcm43xx_tab_rotor[i]);
721 } else {
722 /* nrssi values are signed 6-bit values. Not sure why we write 0x7654 here... */
723 bcm43xx_nrssi_hw_write(dev, 0xBA98, (s16)0x7654);
724
725 if (phy->rev == 2) {
726 bcm43xx_phy_write(dev, 0x04C0, 0x1861);
727 bcm43xx_phy_write(dev, 0x04C1, 0x0271);
728 } else if (phy->rev > 2) {
729 bcm43xx_phy_write(dev, 0x04C0, 0x0098);
730 bcm43xx_phy_write(dev, 0x04C1, 0x0070);
731 bcm43xx_phy_write(dev, 0x04C9, 0x0080);
732 }
733 bcm43xx_phy_write(dev, 0x042B, bcm43xx_phy_read(dev, 0x042B) | 0x800);
734
735 for (i = 0; i < 64; i++)
736 bcm43xx_ofdmtab_write16(dev, 0x4000, i, i);
737 for (i = 0; i < BCM43xx_TAB_NOISEG2_SIZE; i++)
738 bcm43xx_ofdmtab_write16(dev, 0x1800, i, bcm43xx_tab_noiseg2[i]);
739 }
740
741 if (phy->rev <= 2)
742 for (i = 0; i < BCM43xx_TAB_NOISESCALEG_SIZE; i++)
743 bcm43xx_ofdmtab_write16(dev, 0x1400, i, bcm43xx_tab_noisescaleg1[i]);
744 else if ((phy->rev >= 7) && (bcm43xx_phy_read(dev, 0x0449) & 0x0200))
745 for (i = 0; i < BCM43xx_TAB_NOISESCALEG_SIZE; i++)
746 bcm43xx_ofdmtab_write16(dev, 0x1400, i, bcm43xx_tab_noisescaleg3[i]);
747 else
748 for (i = 0; i < BCM43xx_TAB_NOISESCALEG_SIZE; i++)
749 bcm43xx_ofdmtab_write16(dev, 0x1400, i, bcm43xx_tab_noisescaleg2[i]);
750
751 if (phy->rev == 2)
752 for (i = 0; i < BCM43xx_TAB_SIGMASQR_SIZE; i++)
753 bcm43xx_ofdmtab_write16(dev, 0x5000, i, bcm43xx_tab_sigmasqr1[i]);
754 else if ((phy->rev > 2) && (phy->rev <= 8))
755 for (i = 0; i < BCM43xx_TAB_SIGMASQR_SIZE; i++)
756 bcm43xx_ofdmtab_write16(dev, 0x5000, i, bcm43xx_tab_sigmasqr2[i]);
757
758 if (phy->rev == 1) {
759 for (i = 0; i < BCM43xx_TAB_RETARD_SIZE; i++)
760 bcm43xx_ofdmtab_write32(dev, 0x2400, i, bcm43xx_tab_retard[i]);
761 for (i = 0; i < 4; i++) {
762 bcm43xx_ofdmtab_write16(dev, 0x5404, i, 0x0020);
763 bcm43xx_ofdmtab_write16(dev, 0x5408, i, 0x0020);
764 bcm43xx_ofdmtab_write16(dev, 0x540C, i, 0x0020);
765 bcm43xx_ofdmtab_write16(dev, 0x5410, i, 0x0020);
766 }
767 bcm43xx_phy_agcsetup(dev);
768
769 if ((bus->board_vendor == SSB_BOARDVENDOR_BCM) &&
770 (bus->board_type == SSB_BOARD_BU4306) &&
771 (bus->board_rev == 0x17))
772 return;
773
774 bcm43xx_ofdmtab_write16(dev, 0x5001, 0, 0x0002);
775 bcm43xx_ofdmtab_write16(dev, 0x5002, 0, 0x0001);
776 } else {
777 for (i = 0; i <= 0x2F; i++)
778 bcm43xx_ofdmtab_write16(dev, 0x1000, i, 0x0820);
779 bcm43xx_phy_agcsetup(dev);
780 bcm43xx_phy_read(dev, 0x0400); /* dummy read */
781 bcm43xx_phy_write(dev, 0x0403, 0x1000);
782 bcm43xx_ofdmtab_write16(dev, 0x3C02, 0, 0x000F);
783 bcm43xx_ofdmtab_write16(dev, 0x3C03, 0, 0x0014);
784
785 if ((bus->board_vendor == SSB_BOARDVENDOR_BCM) &&
786 (bus->board_type == SSB_BOARD_BU4306) &&
787 (bus->board_rev == 0x17))
788 return;
789
790 bcm43xx_ofdmtab_write16(dev, 0x0401, 0, 0x0002);
791 bcm43xx_ofdmtab_write16(dev, 0x0402, 0, 0x0001);
792 }
793 }
794
795 /* Initialize the noisescaletable for APHY */
796 static void bcm43xx_phy_init_noisescaletbl(struct bcm43xx_wldev *dev)
797 {
798 struct bcm43xx_phy *phy = &dev->phy;
799 int i;
800
801 for (i = 0; i < 12; i++) {
802 if (phy->rev == 2)
803 bcm43xx_ofdmtab_write16(dev, 0x1400, i, 0x6767);
804 else
805 bcm43xx_ofdmtab_write16(dev, 0x1400, i, 0x2323);
806 }
807 if (phy->rev == 2)
808 bcm43xx_ofdmtab_write16(dev, 0x1400, i, 0x6700);
809 else
810 bcm43xx_ofdmtab_write16(dev, 0x1400, i, 0x2300);
811 for (i = 0; i < 11; i++) {
812 if (phy->rev == 2)
813 bcm43xx_ofdmtab_write16(dev, 0x1400, i, 0x6767);
814 else
815 bcm43xx_ofdmtab_write16(dev, 0x1400, i, 0x2323);
816 }
817 if (phy->rev == 2)
818 bcm43xx_ofdmtab_write16(dev, 0x1400, i, 0x0067);
819 else
820 bcm43xx_ofdmtab_write16(dev, 0x1400, i, 0x0023);
821 }
822
823 static void bcm43xx_phy_setupa(struct bcm43xx_wldev *dev)
824 {
825 struct bcm43xx_phy *phy = &dev->phy;
826 u16 i;
827
828 assert(phy->type == BCM43xx_PHYTYPE_A);
829 switch (phy->rev) {
830 case 2:
831 bcm43xx_phy_write(dev, 0x008E, 0x3800);
832 bcm43xx_phy_write(dev, 0x0035, 0x03FF);
833 bcm43xx_phy_write(dev, 0x0036, 0x0400);
834
835 bcm43xx_ofdmtab_write16(dev, 0x3807, 0, 0x0051);
836
837 bcm43xx_phy_write(dev, 0x001C, 0x0FF9);
838 bcm43xx_phy_write(dev, 0x0020, bcm43xx_phy_read(dev, 0x0020) & 0xFF0F);
839 bcm43xx_ofdmtab_write16(dev, 0x3C0C, 0, 0x07BF);
840 bcm43xx_radio_write16(dev, 0x0002, 0x07BF);
841
842 bcm43xx_phy_write(dev, 0x0024, 0x4680);
843 bcm43xx_phy_write(dev, 0x0020, 0x0003);
844 bcm43xx_phy_write(dev, 0x001D, 0x0F40);
845 bcm43xx_phy_write(dev, 0x001F, 0x1C00);
846
847 bcm43xx_phy_write(dev, 0x002A,
848 (bcm43xx_phy_read(dev, 0x002A)
849 & 0x00FF) | 0x0400);
850 bcm43xx_phy_write(dev, 0x002B,
851 bcm43xx_phy_read(dev, 0x002B)
852 & 0xFBFF);
853 bcm43xx_phy_write(dev, 0x008E, 0x58C1);
854
855 bcm43xx_ofdmtab_write16(dev, 0x0803, 0, 0x000F);
856 bcm43xx_ofdmtab_write16(dev, 0x0804, 0, 0x001F);
857 bcm43xx_ofdmtab_write16(dev, 0x0805, 0, 0x002A);
858 bcm43xx_ofdmtab_write16(dev, 0x0805, 0, 0x0030);
859 bcm43xx_ofdmtab_write16(dev, 0x0807, 0, 0x003A);
860
861 bcm43xx_ofdmtab_write16(dev, 0x0000, 0, 0x0013);
862 bcm43xx_ofdmtab_write16(dev, 0x0000, 1, 0x0013);
863 bcm43xx_ofdmtab_write16(dev, 0x0000, 2, 0x0013);
864 bcm43xx_ofdmtab_write16(dev, 0x0000, 3, 0x0013);
865 bcm43xx_ofdmtab_write16(dev, 0x0000, 4, 0x0015);
866 bcm43xx_ofdmtab_write16(dev, 0x0000, 5, 0x0015);
867 bcm43xx_ofdmtab_write16(dev, 0x0000, 6, 0x0019);
868
869 bcm43xx_ofdmtab_write16(dev, 0x0404, 0, 0x0003);
870 bcm43xx_ofdmtab_write16(dev, 0x0405, 0, 0x0003);
871 bcm43xx_ofdmtab_write16(dev, 0x0406, 0, 0x0007);
872
873 for (i = 0; i < 16; i++)
874 bcm43xx_ofdmtab_write16(dev, 0x4000, i, (0x8 + i) & 0x000F);
875
876 bcm43xx_ofdmtab_write16(dev, 0x3003, 0, 0x1044);
877 bcm43xx_ofdmtab_write16(dev, 0x3004, 0, 0x7201);
878 bcm43xx_ofdmtab_write16(dev, 0x3006, 0, 0x0040);
879 bcm43xx_ofdmtab_write16(dev, 0x3001, 0, (bcm43xx_ofdmtab_read16(dev, 0x3001, 0) & 0x0010) | 0x0008);
880
881 for (i = 0; i < BCM43xx_TAB_FINEFREQA_SIZE; i++)
882 bcm43xx_ofdmtab_write16(dev, 0x5800, i, bcm43xx_tab_finefreqa[i]);
883 for (i = 0; i < BCM43xx_TAB_NOISEA2_SIZE; i++)
884 bcm43xx_ofdmtab_write16(dev, 0x1800, i, bcm43xx_tab_noisea2[i]);
885 for (i = 0; i < BCM43xx_TAB_ROTOR_SIZE; i++)
886 bcm43xx_ofdmtab_write32(dev, 0x2000, i, bcm43xx_tab_rotor[i]);
887 bcm43xx_phy_init_noisescaletbl(dev);
888 for (i = 0; i < BCM43xx_TAB_RETARD_SIZE; i++)
889 bcm43xx_ofdmtab_write32(dev, 0x2400, i, bcm43xx_tab_retard[i]);
890 break;
891 case 3:
892 for (i = 0; i < 64; i++)
893 bcm43xx_ofdmtab_write16(dev, 0x4000, i, i);
894
895 bcm43xx_ofdmtab_write16(dev, 0x3807, 0, 0x0051);
896
897 bcm43xx_phy_write(dev, 0x001C, 0x0FF9);
898 bcm43xx_phy_write(dev, 0x0020,
899 bcm43xx_phy_read(dev, 0x0020) & 0xFF0F);
900 bcm43xx_radio_write16(dev, 0x0002, 0x07BF);
901
902 bcm43xx_phy_write(dev, 0x0024, 0x4680);
903 bcm43xx_phy_write(dev, 0x0020, 0x0003);
904 bcm43xx_phy_write(dev, 0x001D, 0x0F40);
905 bcm43xx_phy_write(dev, 0x001F, 0x1C00);
906 bcm43xx_phy_write(dev, 0x002A,
907 (bcm43xx_phy_read(dev, 0x002A)
908 & 0x00FF) | 0x0400);
909
910 bcm43xx_ofdmtab_write16(dev, 0x3000, 1,
911 (bcm43xx_ofdmtab_read16(dev, 0x3000, 1)
912 & 0x0010) | 0x0008);
913 for (i = 0; i < BCM43xx_TAB_NOISEA3_SIZE; i++) {
914 bcm43xx_ofdmtab_write16(dev, 0x1800, i,
915 bcm43xx_tab_noisea3[i]);
916 }
917 bcm43xx_phy_init_noisescaletbl(dev);
918 for (i = 0; i < BCM43xx_TAB_SIGMASQR_SIZE; i++) {
919 bcm43xx_ofdmtab_write16(dev, 0x5000, i,
920 bcm43xx_tab_sigmasqr1[i]);
921 }
922
923 bcm43xx_phy_write(dev, 0x0003, 0x1808);
924
925 bcm43xx_ofdmtab_write16(dev, 0x0803, 0, 0x000F);
926 bcm43xx_ofdmtab_write16(dev, 0x0804, 0, 0x001F);
927 bcm43xx_ofdmtab_write16(dev, 0x0805, 0, 0x002A);
928 bcm43xx_ofdmtab_write16(dev, 0x0805, 0, 0x0030);
929 bcm43xx_ofdmtab_write16(dev, 0x0807, 0, 0x003A);
930
931 bcm43xx_ofdmtab_write16(dev, 0x0000, 0, 0x0013);
932 bcm43xx_ofdmtab_write16(dev, 0x0001, 0, 0x0013);
933 bcm43xx_ofdmtab_write16(dev, 0x0002, 0, 0x0013);
934 bcm43xx_ofdmtab_write16(dev, 0x0003, 0, 0x0013);
935 bcm43xx_ofdmtab_write16(dev, 0x0004, 0, 0x0015);
936 bcm43xx_ofdmtab_write16(dev, 0x0005, 0, 0x0015);
937 bcm43xx_ofdmtab_write16(dev, 0x0006, 0, 0x0019);
938
939 bcm43xx_ofdmtab_write16(dev, 0x0404, 0, 0x0003);
940 bcm43xx_ofdmtab_write16(dev, 0x0405, 0, 0x0003);
941 bcm43xx_ofdmtab_write16(dev, 0x0406, 0, 0x0007);
942
943 bcm43xx_ofdmtab_write16(dev, 0x3C02, 0, 0x000F);
944 bcm43xx_ofdmtab_write16(dev, 0x3C03, 0, 0x0014);
945 break;
946 default:
947 assert(0);
948 }
949 }
950
951 /* Initialize APHY. This is also called for the GPHY in some cases. */
952 static void bcm43xx_phy_inita(struct bcm43xx_wldev *dev)
953 {
954 struct ssb_bus *bus = dev->dev->bus;
955 struct bcm43xx_phy *phy = &dev->phy;
956 u16 tval;
957
958 if (phy->type == BCM43xx_PHYTYPE_A) {
959 bcm43xx_phy_setupa(dev);
960 } else {
961 bcm43xx_phy_setupg(dev);
962 if (phy->gmode &&
963 (dev->dev->bus->sprom.r1.boardflags_lo & BCM43xx_BFL_PACTRL))
964 bcm43xx_phy_write(dev, 0x046E, 0x03CF);
965 return;
966 }
967
968 bcm43xx_phy_write(dev, BCM43xx_PHY_A_CRS,
969 (bcm43xx_phy_read(dev, BCM43xx_PHY_A_CRS) & 0xF83C) | 0x0340);
970 bcm43xx_phy_write(dev, 0x0034, 0x0001);
971
972 TODO();//TODO: RSSI AGC
973 bcm43xx_phy_write(dev, BCM43xx_PHY_A_CRS,
974 bcm43xx_phy_read(dev, BCM43xx_PHY_A_CRS) | (1 << 14));
975 bcm43xx_radio_init2060(dev);
976
977 if ((bus->board_vendor == SSB_BOARDVENDOR_BCM) &&
978 ((bus->board_type == SSB_BOARD_BU4306) ||
979 (bus->board_type == SSB_BOARD_BU4309))) {
980 if (phy->lofcal == 0xFFFF) {
981 TODO();//TODO: LOF Cal
982 bcm43xx_radio_set_tx_iq(dev);
983 } else
984 bcm43xx_radio_write16(dev, 0x001E, phy->lofcal);
985 }
986
987 bcm43xx_phy_write(dev, 0x007A, 0xF111);
988
989 if (phy->cur_idle_tssi == 0) {
990 bcm43xx_radio_write16(dev, 0x0019, 0x0000);
991 bcm43xx_radio_write16(dev, 0x0017, 0x0020);
992
993 tval = bcm43xx_ofdmtab_read16(dev, 0x3001, 0);
994 if (phy->rev == 1) {
995 bcm43xx_ofdmtab_write16(dev, 0x3001, 0,
996 (bcm43xx_ofdmtab_read16(dev, 0x3001, 0) & 0xFF87)
997 | 0x0058);
998 } else {
999 bcm43xx_ofdmtab_write16(dev, 0x3001, 0,
1000 (bcm43xx_ofdmtab_read16(dev, 0x3001, 0) & 0xFFC3)
1001 | 0x002C);
1002 }
1003 bcm43xx_dummy_transmission(dev);
1004 phy->cur_idle_tssi = bcm43xx_phy_read(dev, BCM43xx_PHY_A_PCTL);
1005 bcm43xx_ofdmtab_write16(dev, 0x3001, 0, tval);
1006
1007 bcm43xx_radio_set_txpower_a(dev, 0x0018);
1008 }
1009 bcm43xx_shm_clear_tssi(dev);
1010 }
1011
1012 static void bcm43xx_phy_initb2(struct bcm43xx_wldev *dev)
1013 {
1014 struct bcm43xx_phy *phy = &dev->phy;
1015 u16 offset, val;
1016
1017 bcm43xx_write16(dev, 0x03EC, 0x3F22);
1018 bcm43xx_phy_write(dev, 0x0020, 0x301C);
1019 bcm43xx_phy_write(dev, 0x0026, 0x0000);
1020 bcm43xx_phy_write(dev, 0x0030, 0x00C6);
1021 bcm43xx_phy_write(dev, 0x0088, 0x3E00);
1022 val = 0x3C3D;
1023 for (offset = 0x0089; offset < 0x00A7; offset++) {
1024 bcm43xx_phy_write(dev, offset, val);
1025 val -= 0x0202;
1026 }
1027 bcm43xx_phy_write(dev, 0x03E4, 0x3000);
1028 if (phy->channel == 0xFF)
1029 bcm43xx_radio_selectchannel(dev, BCM43xx_DEFAULT_CHANNEL_BG, 0);
1030 else
1031 bcm43xx_radio_selectchannel(dev, phy->channel, 0);
1032 if (phy->radio_ver != 0x2050) {
1033 bcm43xx_radio_write16(dev, 0x0075, 0x0080);
1034 bcm43xx_radio_write16(dev, 0x0079, 0x0081);
1035 }
1036 bcm43xx_radio_write16(dev, 0x0050, 0x0020);
1037 bcm43xx_radio_write16(dev, 0x0050, 0x0023);
1038 if (phy->radio_ver == 0x2050) {
1039 bcm43xx_radio_write16(dev, 0x0050, 0x0020);
1040 bcm43xx_radio_write16(dev, 0x005A, 0x0070);
1041 bcm43xx_radio_write16(dev, 0x005B, 0x007B);
1042 bcm43xx_radio_write16(dev, 0x005C, 0x00B0);
1043 bcm43xx_radio_write16(dev, 0x007A, 0x000F);
1044 bcm43xx_phy_write(dev, 0x0038, 0x0677);
1045 bcm43xx_radio_init2050(dev);
1046 }
1047 bcm43xx_phy_write(dev, 0x0014, 0x0080);
1048 bcm43xx_phy_write(dev, 0x0032, 0x00CA);
1049 bcm43xx_phy_write(dev, 0x0032, 0x00CC);
1050 bcm43xx_phy_write(dev, 0x0035, 0x07C2);
1051 bcm43xx_lo_b_measure(dev);
1052 bcm43xx_phy_write(dev, 0x0026, 0xCC00);
1053 if (phy->radio_ver != 0x2050)
1054 bcm43xx_phy_write(dev, 0x0026, 0xCE00);
1055 bcm43xx_write16(dev, BCM43xx_MMIO_CHANNEL_EXT, 0x1000);
1056 bcm43xx_phy_write(dev, 0x002A, 0x88A3);
1057 if (phy->radio_ver != 0x2050)
1058 bcm43xx_phy_write(dev, 0x002A, 0x88C2);
1059 bcm43xx_radio_set_txpower_bg(dev, -1, -1, -1);
1060 bcm43xx_phy_init_pctl(dev);
1061 }
1062
1063 static void bcm43xx_phy_initb4(struct bcm43xx_wldev *dev)
1064 {
1065 struct bcm43xx_phy *phy = &dev->phy;
1066 u16 offset, val;
1067
1068 bcm43xx_write16(dev, 0x03EC, 0x3F22);
1069 bcm43xx_phy_write(dev, 0x0020, 0x301C);
1070 bcm43xx_phy_write(dev, 0x0026, 0x0000);
1071 bcm43xx_phy_write(dev, 0x0030, 0x00C6);
1072 bcm43xx_phy_write(dev, 0x0088, 0x3E00);
1073 val = 0x3C3D;
1074 for (offset = 0x0089; offset < 0x00A7; offset++) {
1075 bcm43xx_phy_write(dev, offset, val);
1076 val -= 0x0202;
1077 }
1078 bcm43xx_phy_write(dev, 0x03E4, 0x3000);
1079 if (phy->channel == 0xFF)
1080 bcm43xx_radio_selectchannel(dev, BCM43xx_DEFAULT_CHANNEL_BG, 0);
1081 else
1082 bcm43xx_radio_selectchannel(dev, phy->channel, 0);
1083 if (phy->radio_ver != 0x2050) {
1084 bcm43xx_radio_write16(dev, 0x0075, 0x0080);
1085 bcm43xx_radio_write16(dev, 0x0079, 0x0081);
1086 }
1087 bcm43xx_radio_write16(dev, 0x0050, 0x0020);
1088 bcm43xx_radio_write16(dev, 0x0050, 0x0023);
1089 if (phy->radio_ver == 0x2050) {
1090 bcm43xx_radio_write16(dev, 0x0050, 0x0020);
1091 bcm43xx_radio_write16(dev, 0x005A, 0x0070);
1092 bcm43xx_radio_write16(dev, 0x005B, 0x007B);
1093 bcm43xx_radio_write16(dev, 0x005C, 0x00B0);
1094 bcm43xx_radio_write16(dev, 0x007A, 0x000F);
1095 bcm43xx_phy_write(dev, 0x0038, 0x0677);
1096 bcm43xx_radio_init2050(dev);
1097 }
1098 bcm43xx_phy_write(dev, 0x0014, 0x0080);
1099 bcm43xx_phy_write(dev, 0x0032, 0x00CA);
1100 if (phy->radio_ver == 0x2050)
1101 bcm43xx_phy_write(dev, 0x0032, 0x00E0);
1102 bcm43xx_phy_write(dev, 0x0035, 0x07C2);
1103
1104 bcm43xx_lo_b_measure(dev);
1105
1106 bcm43xx_phy_write(dev, 0x0026, 0xCC00);
1107 if (phy->radio_ver == 0x2050)
1108 bcm43xx_phy_write(dev, 0x0026, 0xCE00);
1109 bcm43xx_write16(dev, BCM43xx_MMIO_CHANNEL_EXT, 0x1100);
1110 bcm43xx_phy_write(dev, 0x002A, 0x88A3);
1111 if (phy->radio_ver == 0x2050)
1112 bcm43xx_phy_write(dev, 0x002A, 0x88C2);
1113 bcm43xx_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF);
1114 if (dev->dev->bus->sprom.r1.boardflags_lo & BCM43xx_BFL_RSSI) {
1115 bcm43xx_calc_nrssi_slope(dev);
1116 bcm43xx_calc_nrssi_threshold(dev);
1117 }
1118 bcm43xx_phy_init_pctl(dev);
1119 }
1120
1121 static void bcm43xx_phy_initb5(struct bcm43xx_wldev *dev)
1122 {
1123 struct ssb_bus *bus = dev->dev->bus;
1124 struct bcm43xx_phy *phy = &dev->phy;
1125 u16 offset, value;
1126 u8 old_channel;
1127
1128 if (phy->analog == 1) {
1129 bcm43xx_radio_write16(dev, 0x007A,
1130 bcm43xx_radio_read16(dev, 0x007A)
1131 | 0x0050);
1132 }
1133 if ((bus->board_vendor != SSB_BOARDVENDOR_BCM) &&
1134 (bus->board_type != SSB_BOARD_BU4306)) {
1135 value = 0x2120;
1136 for (offset = 0x00A8 ; offset < 0x00C7; offset++) {
1137 bcm43xx_phy_write(dev, offset, value);
1138 value += 0x202;
1139 }
1140 }
1141 bcm43xx_phy_write(dev, 0x0035,
1142 (bcm43xx_phy_read(dev, 0x0035) & 0xF0FF)
1143 | 0x0700);
1144 if (phy->radio_ver == 0x2050)
1145 bcm43xx_phy_write(dev, 0x0038, 0x0667);
1146
1147 if (phy->gmode || phy->rev >= 2) {
1148 if (phy->radio_ver == 0x2050) {
1149 bcm43xx_radio_write16(dev, 0x007A,
1150 bcm43xx_radio_read16(dev, 0x007A)
1151 | 0x0020);
1152 bcm43xx_radio_write16(dev, 0x0051,
1153 bcm43xx_radio_read16(dev, 0x0051)
1154 | 0x0004);
1155 }
1156 bcm43xx_write16(dev, BCM43xx_MMIO_PHY_RADIO, 0x0000);
1157
1158 bcm43xx_phy_write(dev, 0x0802, bcm43xx_phy_read(dev, 0x0802) | 0x0100);
1159 bcm43xx_phy_write(dev, 0x042B, bcm43xx_phy_read(dev, 0x042B) | 0x2000);
1160
1161 bcm43xx_phy_write(dev, 0x001C, 0x186A);
1162
1163 bcm43xx_phy_write(dev, 0x0013, (bcm43xx_phy_read(dev, 0x0013) & 0x00FF) | 0x1900);
1164 bcm43xx_phy_write(dev, 0x0035, (bcm43xx_phy_read(dev, 0x0035) & 0xFFC0) | 0x0064);
1165 bcm43xx_phy_write(dev, 0x005D, (bcm43xx_phy_read(dev, 0x005D) & 0xFF80) | 0x000A);
1166 }
1167
1168 if (dev->bad_frames_preempt) {
1169 bcm43xx_phy_write(dev, BCM43xx_PHY_RADIO_BITFIELD,
1170 bcm43xx_phy_read(dev, BCM43xx_PHY_RADIO_BITFIELD) | (1 << 11));
1171 }
1172
1173 if (phy->analog == 1) {
1174 bcm43xx_phy_write(dev, 0x0026, 0xCE00);
1175 bcm43xx_phy_write(dev, 0x0021, 0x3763);
1176 bcm43xx_phy_write(dev, 0x0022, 0x1BC3);
1177 bcm43xx_phy_write(dev, 0x0023, 0x06F9);
1178 bcm43xx_phy_write(dev, 0x0024, 0x037E);
1179 } else
1180 bcm43xx_phy_write(dev, 0x0026, 0xCC00);
1181 bcm43xx_phy_write(dev, 0x0030, 0x00C6);
1182 bcm43xx_write16(dev, 0x03EC, 0x3F22);
1183
1184 if (phy->analog == 1)
1185 bcm43xx_phy_write(dev, 0x0020, 0x3E1C);
1186 else
1187 bcm43xx_phy_write(dev, 0x0020, 0x301C);
1188
1189 if (phy->analog == 0)
1190 bcm43xx_write16(dev, 0x03E4, 0x3000);
1191
1192 old_channel = phy->channel;
1193 /* Force to channel 7, even if not supported. */
1194 bcm43xx_radio_selectchannel(dev, 7, 0);
1195
1196 if (phy->radio_ver != 0x2050) {
1197 bcm43xx_radio_write16(dev, 0x0075, 0x0080);
1198 bcm43xx_radio_write16(dev, 0x0079, 0x0081);
1199 }
1200
1201 bcm43xx_radio_write16(dev, 0x0050, 0x0020);
1202 bcm43xx_radio_write16(dev, 0x0050, 0x0023);
1203
1204 if (phy->radio_ver == 0x2050) {
1205 bcm43xx_radio_write16(dev, 0x0050, 0x0020);
1206 bcm43xx_radio_write16(dev, 0x005A, 0x0070);
1207 }
1208
1209 bcm43xx_radio_write16(dev, 0x005B, 0x007B);
1210 bcm43xx_radio_write16(dev, 0x005C, 0x00B0);
1211
1212 bcm43xx_radio_write16(dev, 0x007A, bcm43xx_radio_read16(dev, 0x007A) | 0x0007);
1213
1214 bcm43xx_radio_selectchannel(dev, old_channel, 0);
1215
1216 bcm43xx_phy_write(dev, 0x0014, 0x0080);
1217 bcm43xx_phy_write(dev, 0x0032, 0x00CA);
1218 bcm43xx_phy_write(dev, 0x002A, 0x88A3);
1219
1220 bcm43xx_radio_set_txpower_bg(dev, -1, -1, -1);
1221
1222 if (phy->radio_ver == 0x2050)
1223 bcm43xx_radio_write16(dev, 0x005D, 0x000D);
1224
1225 bcm43xx_write16(dev, 0x03E4, (bcm43xx_read16(dev, 0x03E4) & 0xFFC0) | 0x0004);
1226 }
1227
1228 static void bcm43xx_phy_initb6(struct bcm43xx_wldev *dev)
1229 {
1230 struct bcm43xx_phy *phy = &dev->phy;
1231 u16 offset, val;
1232 u8 old_channel;
1233
1234 bcm43xx_phy_write(dev, 0x003E, 0x817A);
1235 bcm43xx_radio_write16(dev, 0x007A,
1236 (bcm43xx_radio_read16(dev, 0x007A) | 0x0058));
1237 if (phy->radio_rev == 4 || phy->radio_rev == 5) {
1238 bcm43xx_radio_write16(dev, 0x51, 0x37);
1239 bcm43xx_radio_write16(dev, 0x52, 0x70);
1240 bcm43xx_radio_write16(dev, 0x53, 0xB3);
1241 bcm43xx_radio_write16(dev, 0x54, 0x9B);
1242 bcm43xx_radio_write16(dev, 0x5A, 0x88);
1243 bcm43xx_radio_write16(dev, 0x5B, 0x88);
1244 bcm43xx_radio_write16(dev, 0x5D, 0x88);
1245 bcm43xx_radio_write16(dev, 0x5E, 0x88);
1246 bcm43xx_radio_write16(dev, 0x7D, 0x88);
1247 bcm43xx_hf_write(dev, bcm43xx_hf_read(dev)
1248 | BCM43xx_HF_TSSIRPSMW);
1249 }
1250 assert(phy->radio_rev != 6 && phy->radio_rev != 7); /* We had code for these revs here...*/
1251 if (phy->radio_rev == 8) {
1252 bcm43xx_radio_write16(dev, 0x51, 0);
1253 bcm43xx_radio_write16(dev, 0x52, 0x40);
1254 bcm43xx_radio_write16(dev, 0x53, 0xB7);
1255 bcm43xx_radio_write16(dev, 0x54, 0x98);
1256 bcm43xx_radio_write16(dev, 0x5A, 0x88);
1257 bcm43xx_radio_write16(dev, 0x5B, 0x6B);
1258 bcm43xx_radio_write16(dev, 0x5C, 0x0F);
1259 if (dev->dev->bus->sprom.r1.boardflags_lo & BCM43xx_BFL_ALTIQ) {
1260 bcm43xx_radio_write16(dev, 0x5D, 0xFA);
1261 bcm43xx_radio_write16(dev, 0x5E, 0xD8);
1262 } else {
1263 bcm43xx_radio_write16(dev, 0x5D, 0xF5);
1264 bcm43xx_radio_write16(dev, 0x5E, 0xB8);
1265 }
1266 bcm43xx_radio_write16(dev, 0x0073, 0x0003);
1267 bcm43xx_radio_write16(dev, 0x007D, 0x00A8);
1268 bcm43xx_radio_write16(dev, 0x007C, 0x0001);
1269 bcm43xx_radio_write16(dev, 0x007E, 0x0008);
1270 }
1271 val = 0x1E1F;
1272 for (offset = 0x0088; offset < 0x0098; offset++) {
1273 bcm43xx_phy_write(dev, offset, val);
1274 val -= 0x0202;
1275 }
1276 val = 0x3E3F;
1277 for (offset = 0x0098; offset < 0x00A8; offset++) {
1278 bcm43xx_phy_write(dev, offset, val);
1279 val -= 0x0202;
1280 }
1281 val = 0x2120;
1282 for (offset = 0x00A8; offset < 0x00C8; offset++) {
1283 bcm43xx_phy_write(dev, offset, (val & 0x3F3F));
1284 val += 0x0202;
1285 }
1286 if (phy->type == BCM43xx_PHYTYPE_G) {
1287 bcm43xx_radio_write16(dev, 0x007A,
1288 bcm43xx_radio_read16(dev, 0x007A) | 0x0020);
1289 bcm43xx_radio_write16(dev, 0x0051,
1290 bcm43xx_radio_read16(dev, 0x0051) | 0x0004);
1291 bcm43xx_phy_write(dev, 0x0802,
1292 bcm43xx_phy_read(dev, 0x0802) | 0x0100);
1293 bcm43xx_phy_write(dev, 0x042B,
1294 bcm43xx_phy_read(dev, 0x042B) | 0x2000);
1295 bcm43xx_phy_write(dev, 0x5B, 0);
1296 bcm43xx_phy_write(dev, 0x5C, 0);
1297 }
1298
1299 old_channel = phy->channel;
1300 if (old_channel >= 8)
1301 bcm43xx_radio_selectchannel(dev, 1, 0);
1302 else
1303 bcm43xx_radio_selectchannel(dev, 13, 0);
1304
1305 bcm43xx_radio_write16(dev, 0x0050, 0x0020);
1306 bcm43xx_radio_write16(dev, 0x0050, 0x0023);
1307 udelay(40);
1308 if (phy->radio_rev < 6 || phy->radio_rev == 8) {
1309 bcm43xx_radio_write16(dev, 0x7C,
1310 (bcm43xx_radio_read16(dev, 0x7C)
1311 | 0x0002));
1312 bcm43xx_radio_write16(dev, 0x50, 0x20);
1313 }
1314 if (phy->radio_rev <= 2) {
1315 bcm43xx_radio_write16(dev, 0x7C, 0x20);
1316 bcm43xx_radio_write16(dev, 0x5A, 0x70);
1317 bcm43xx_radio_write16(dev, 0x5B, 0x7B);
1318 bcm43xx_radio_write16(dev, 0x5C, 0xB0);
1319 }
1320 bcm43xx_radio_write16(dev, 0x007A,
1321 (bcm43xx_radio_read16(dev, 0x007A) & 0x00F8) | 0x0007);
1322
1323 bcm43xx_radio_selectchannel(dev, old_channel, 0);
1324
1325 bcm43xx_phy_write(dev, 0x0014, 0x0200);
1326 if (phy->radio_rev >= 6)
1327 bcm43xx_phy_write(dev, 0x2A, 0x88C2);
1328 else
1329 bcm43xx_phy_write(dev, 0x2A, 0x8AC0);
1330 bcm43xx_phy_write(dev, 0x0038, 0x0668);
1331 bcm43xx_radio_set_txpower_bg(dev, -1, -1, -1);
1332 if (phy->radio_rev <= 5) {
1333 bcm43xx_phy_write(dev, 0x5D,
1334 (bcm43xx_phy_read(dev, 0x5D)
1335 & 0xFF80) | 0x0003);
1336 }
1337 if (phy->radio_rev <= 2)
1338 bcm43xx_radio_write16(dev, 0x005D, 0x000D);
1339
1340 if (phy->analog == 4) {
1341 bcm43xx_write16(dev, 0x3E4, 9);
1342 bcm43xx_phy_write(dev, 0x61,
1343 bcm43xx_phy_read(dev, 0x61)
1344 & 0x0FFF);
1345 } else {
1346 bcm43xx_phy_write(dev, 0x0002,
1347 (bcm43xx_phy_read(dev, 0x0002) & 0xFFC0)
1348 | 0x0004);
1349 }
1350 if (phy->type == BCM43xx_PHYTYPE_B) {
1351 bcm43xx_write16(dev, 0x03E6, 0x8140);
1352 bcm43xx_phy_write(dev, 0x0016, 0x0410);
1353 bcm43xx_phy_write(dev, 0x0017, 0x0820);
1354 bcm43xx_phy_write(dev, 0x0062, 0x0007);
1355 bcm43xx_radio_init2050(dev);
1356 bcm43xx_lo_g_measure(dev);
1357 if (dev->dev->bus->sprom.r1.boardflags_lo & BCM43xx_BFL_RSSI) {
1358 bcm43xx_calc_nrssi_slope(dev);
1359 bcm43xx_calc_nrssi_threshold(dev);
1360 }
1361 bcm43xx_phy_init_pctl(dev);
1362 } else if (phy->type == BCM43xx_PHYTYPE_G)
1363 bcm43xx_write16(dev, 0x03E6, 0x0);
1364 }
1365
1366 static void bcm43xx_calc_loopback_gain(struct bcm43xx_wldev *dev)
1367 {
1368 struct bcm43xx_phy *phy = &dev->phy;
1369 u16 backup_phy[16] = {0};
1370 u16 backup_radio[3];
1371 u16 backup_bband;
1372 u16 i, j, loop_i_max;
1373 u16 trsw_rx;
1374 u16 loop1_outer_done, loop1_inner_done;
1375
1376 backup_phy[0] = bcm43xx_phy_read(dev, BCM43xx_PHY_CRS0);
1377 backup_phy[1] = bcm43xx_phy_read(dev, BCM43xx_PHY_CCKBBANDCFG);
1378 backup_phy[2] = bcm43xx_phy_read(dev, BCM43xx_PHY_RFOVER);
1379 backup_phy[3] = bcm43xx_phy_read(dev, BCM43xx_PHY_RFOVERVAL);
1380 if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
1381 backup_phy[4] = bcm43xx_phy_read(dev, BCM43xx_PHY_ANALOGOVER);
1382 backup_phy[5] = bcm43xx_phy_read(dev, BCM43xx_PHY_ANALOGOVERVAL);
1383 }
1384 backup_phy[6] = bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x5A));
1385 backup_phy[7] = bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x59));
1386 backup_phy[8] = bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x58));
1387 backup_phy[9] = bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x0A));
1388 backup_phy[10] = bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x03));
1389 backup_phy[11] = bcm43xx_phy_read(dev, BCM43xx_PHY_LO_MASK);
1390 backup_phy[12] = bcm43xx_phy_read(dev, BCM43xx_PHY_LO_CTL);
1391 backup_phy[13] = bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x2B));
1392 backup_phy[14] = bcm43xx_phy_read(dev, BCM43xx_PHY_PGACTL);
1393 backup_phy[15] = bcm43xx_phy_read(dev, BCM43xx_PHY_LO_LEAKAGE);
1394 backup_bband = phy->bbatt;
1395 backup_radio[0] = bcm43xx_radio_read16(dev, 0x52);
1396 backup_radio[1] = bcm43xx_radio_read16(dev, 0x43);
1397 backup_radio[2] = bcm43xx_radio_read16(dev, 0x7A);
1398
1399 bcm43xx_phy_write(dev, BCM43xx_PHY_CRS0,
1400 bcm43xx_phy_read(dev, BCM43xx_PHY_CRS0) & 0x3FFF);
1401 bcm43xx_phy_write(dev, BCM43xx_PHY_CCKBBANDCFG,
1402 bcm43xx_phy_read(dev, BCM43xx_PHY_CCKBBANDCFG) | 0x8000);
1403 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVER,
1404 bcm43xx_phy_read(dev, BCM43xx_PHY_RFOVER) | 0x0002);
1405 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL,
1406 bcm43xx_phy_read(dev, BCM43xx_PHY_RFOVERVAL) & 0xFFFD);
1407 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVER,
1408 bcm43xx_phy_read(dev, BCM43xx_PHY_RFOVER) | 0x0001);
1409 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL,
1410 bcm43xx_phy_read(dev, BCM43xx_PHY_RFOVERVAL) & 0xFFFE);
1411 if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
1412 bcm43xx_phy_write(dev, BCM43xx_PHY_ANALOGOVER,
1413 bcm43xx_phy_read(dev, BCM43xx_PHY_ANALOGOVER) | 0x0001);
1414 bcm43xx_phy_write(dev, BCM43xx_PHY_ANALOGOVERVAL,
1415 bcm43xx_phy_read(dev, BCM43xx_PHY_ANALOGOVERVAL) & 0xFFFE);
1416 bcm43xx_phy_write(dev, BCM43xx_PHY_ANALOGOVER,
1417 bcm43xx_phy_read(dev, BCM43xx_PHY_ANALOGOVER) | 0x0002);
1418 bcm43xx_phy_write(dev, BCM43xx_PHY_ANALOGOVERVAL,
1419 bcm43xx_phy_read(dev, BCM43xx_PHY_ANALOGOVERVAL) & 0xFFFD);
1420 }
1421 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVER,
1422 bcm43xx_phy_read(dev, BCM43xx_PHY_RFOVER) | 0x000C);
1423 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL,
1424 bcm43xx_phy_read(dev, BCM43xx_PHY_RFOVERVAL) | 0x000C);
1425 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVER,
1426 bcm43xx_phy_read(dev, BCM43xx_PHY_RFOVER) | 0x0030);
1427 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL,
1428 (bcm43xx_phy_read(dev, BCM43xx_PHY_RFOVERVAL)
1429 & 0xFFCF) | 0x10);
1430
1431 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x5A), 0x0780);
1432 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x59), 0xC810);
1433 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x58), 0x000D);
1434
1435 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x0A),
1436 bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x0A)) | 0x2000);
1437 if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
1438 bcm43xx_phy_write(dev, BCM43xx_PHY_ANALOGOVER,
1439 bcm43xx_phy_read(dev, BCM43xx_PHY_ANALOGOVER) | 0x0004);
1440 bcm43xx_phy_write(dev, BCM43xx_PHY_ANALOGOVERVAL,
1441 bcm43xx_phy_read(dev, BCM43xx_PHY_ANALOGOVERVAL) & 0xFFFB);
1442 }
1443 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x03),
1444 (bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x03))
1445 & 0xFF9F) | 0x40);
1446
1447 if (phy->radio_rev == 8) {
1448 bcm43xx_radio_write16(dev, 0x43, 0x000F);
1449 } else {
1450 bcm43xx_radio_write16(dev, 0x52, 0);
1451 bcm43xx_radio_write16(dev, 0x43,
1452 (bcm43xx_radio_read16(dev, 0x43)
1453 & 0xFFF0) | 0x9);
1454 }
1455 bcm43xx_phy_set_baseband_attenuation(dev, 11);
1456
1457 if (phy->rev >= 3)
1458 bcm43xx_phy_write(dev, BCM43xx_PHY_LO_MASK, 0xC020);
1459 else
1460 bcm43xx_phy_write(dev, BCM43xx_PHY_LO_MASK, 0x8020);
1461 bcm43xx_phy_write(dev, BCM43xx_PHY_LO_CTL, 0);
1462
1463 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x2B),
1464 (bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x2B))
1465 & 0xFFC0) | 0x01);
1466 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x2B),
1467 (bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x2B))
1468 & 0xC0FF) | 0x800);
1469
1470 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVER,
1471 bcm43xx_phy_read(dev, BCM43xx_PHY_RFOVER) | 0x0100);
1472 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL,
1473 bcm43xx_phy_read(dev, BCM43xx_PHY_RFOVERVAL) & 0xCFFF);
1474
1475 if (dev->dev->bus->sprom.r1.boardflags_lo & BCM43xx_BFL_EXTLNA) {
1476 if (phy->rev >= 7) {
1477 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVER,
1478 bcm43xx_phy_read(dev, BCM43xx_PHY_RFOVER)
1479 | 0x0800);
1480 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL,
1481 bcm43xx_phy_read(dev, BCM43xx_PHY_RFOVERVAL)
1482 | 0x8000);
1483 }
1484 }
1485 bcm43xx_radio_write16(dev, 0x7A,
1486 bcm43xx_radio_read16(dev, 0x7A)
1487 & 0x00F7);
1488
1489 j = 0;
1490 loop_i_max = (phy->radio_rev == 8) ? 15 : 9;
1491 for (i = 0; i < loop_i_max; i++) {
1492 for (j = 0; j < 16; j++) {
1493 bcm43xx_radio_write16(dev, 0x43, i);
1494 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL,
1495 (bcm43xx_phy_read(dev, BCM43xx_PHY_RFOVERVAL)
1496 & 0xF0FF) | (j << 8));
1497 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL,
1498 (bcm43xx_phy_read(dev, BCM43xx_PHY_PGACTL)
1499 & 0x0FFF) | 0xA000);
1500 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL,
1501 bcm43xx_phy_read(dev, BCM43xx_PHY_PGACTL)
1502 | 0xF000);
1503 udelay(20);
1504 if (bcm43xx_phy_read(dev, BCM43xx_PHY_LO_LEAKAGE) >= 0xDFC)
1505 goto exit_loop1;
1506 }
1507 }
1508 exit_loop1:
1509 loop1_outer_done = i;
1510 loop1_inner_done = j;
1511 if (j >= 8) {
1512 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL,
1513 bcm43xx_phy_read(dev, BCM43xx_PHY_RFOVERVAL)
1514 | 0x30);
1515 trsw_rx = 0x1B;
1516 for (j = j - 8; j < 16; j++) {
1517 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL,
1518 (bcm43xx_phy_read(dev, BCM43xx_PHY_RFOVERVAL)
1519 & 0xF0FF) | (j << 8));
1520 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL,
1521 (bcm43xx_phy_read(dev, BCM43xx_PHY_PGACTL)
1522 & 0x0FFF) | 0xA000);
1523 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL,
1524 bcm43xx_phy_read(dev, BCM43xx_PHY_PGACTL)
1525 | 0xF000);
1526 udelay(20);
1527 trsw_rx -= 3;
1528 if (bcm43xx_phy_read(dev, BCM43xx_PHY_LO_LEAKAGE) >= 0xDFC)
1529 goto exit_loop2;
1530 }
1531 } else
1532 trsw_rx = 0x18;
1533 exit_loop2:
1534
1535 if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
1536 bcm43xx_phy_write(dev, BCM43xx_PHY_ANALOGOVER, backup_phy[4]);
1537 bcm43xx_phy_write(dev, BCM43xx_PHY_ANALOGOVERVAL, backup_phy[5]);
1538 }
1539 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x5A), backup_phy[6]);
1540 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x59), backup_phy[7]);
1541 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x58), backup_phy[8]);
1542 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x0A), backup_phy[9]);
1543 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x03), backup_phy[10]);
1544 bcm43xx_phy_write(dev, BCM43xx_PHY_LO_MASK, backup_phy[11]);
1545 bcm43xx_phy_write(dev, BCM43xx_PHY_LO_CTL, backup_phy[12]);
1546 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x2B), backup_phy[13]);
1547 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL, backup_phy[14]);
1548
1549 bcm43xx_phy_set_baseband_attenuation(dev, backup_bband);
1550
1551 bcm43xx_radio_write16(dev, 0x52, backup_radio[0]);
1552 bcm43xx_radio_write16(dev, 0x43, backup_radio[1]);
1553 bcm43xx_radio_write16(dev, 0x7A, backup_radio[2]);
1554
1555 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVER, backup_phy[2] | 0x0003);
1556 udelay(10);
1557 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVER, backup_phy[2]);
1558 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL, backup_phy[3]);
1559 bcm43xx_phy_write(dev, BCM43xx_PHY_CRS0, backup_phy[0]);
1560 bcm43xx_phy_write(dev, BCM43xx_PHY_CCKBBANDCFG, backup_phy[1]);
1561
1562 phy->max_lb_gain = ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
1563 phy->trsw_rx_gain = trsw_rx * 2;
1564 }
1565
1566 static void bcm43xx_phy_initg(struct bcm43xx_wldev *dev)
1567 {
1568 struct bcm43xx_phy *phy = &dev->phy;
1569 u16 tmp;
1570
1571 if (phy->rev == 1)
1572 bcm43xx_phy_initb5(dev);
1573 else
1574 bcm43xx_phy_initb6(dev);
1575
1576 if (phy->rev >= 2 || phy->gmode)
1577 bcm43xx_phy_inita(dev);
1578
1579 if (phy->rev >= 2) {
1580 bcm43xx_phy_write(dev, BCM43xx_PHY_ANALOGOVER, 0);
1581 bcm43xx_phy_write(dev, BCM43xx_PHY_ANALOGOVERVAL, 0);
1582 }
1583 if (phy->rev == 2) {
1584 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVER, 0);
1585 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL, 0xC0);
1586 }
1587 if (phy->rev > 5) {
1588 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVER, 0x400);
1589 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL, 0xC0);
1590 }
1591 if (phy->gmode || phy->rev >= 2) {
1592 tmp = bcm43xx_phy_read(dev, BCM43xx_PHY_VERSION_OFDM);
1593 tmp &= BCM43xx_PHYVER_VERSION;
1594 if (tmp == 3 || tmp == 5) {
1595 bcm43xx_phy_write(dev, BCM43xx_PHY_OFDM(0xC2), 0x1816);
1596 bcm43xx_phy_write(dev, BCM43xx_PHY_OFDM(0xC3), 0x8006);
1597 }
1598 if (tmp == 5) {
1599 bcm43xx_phy_write(dev, BCM43xx_PHY_OFDM(0xCC),
1600 (bcm43xx_phy_read(dev, BCM43xx_PHY_OFDM(0xCC))
1601 & 0x00FF) | 0x1F00);
1602 }
1603 }
1604 if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
1605 bcm43xx_phy_write(dev, BCM43xx_PHY_OFDM(0x7E), 0x78);
1606 if (phy->radio_rev == 8) {
1607 bcm43xx_phy_write(dev, BCM43xx_PHY_EXTG(0x01),
1608 bcm43xx_phy_read(dev, BCM43xx_PHY_EXTG(0x01))
1609 | 0x80);
1610 bcm43xx_phy_write(dev, BCM43xx_PHY_OFDM(0x3E),
1611 bcm43xx_phy_read(dev, BCM43xx_PHY_OFDM(0x3E))
1612 | 0x4);
1613 }
1614 if (has_loopback_gain(phy))
1615 bcm43xx_calc_loopback_gain(dev);
1616
1617 if (phy->radio_rev != 8) {
1618 if (phy->initval == 0xFFFF)
1619 phy->initval = bcm43xx_radio_init2050(dev);
1620 else
1621 bcm43xx_radio_write16(dev, 0x0078, phy->initval);
1622 }
1623 if (phy->lo_control->tx_bias == 0xFF) {
1624 bcm43xx_lo_g_measure(dev);
1625 } else {
1626 if (has_tx_magnification(phy)) {
1627 bcm43xx_radio_write16(dev, 0x52,
1628 (bcm43xx_radio_read16(dev, 0x52) & 0xFF00) |
1629 phy->lo_control->tx_bias |
1630 phy->lo_control->tx_magn);
1631 } else {
1632 bcm43xx_radio_write16(dev, 0x52,
1633 (bcm43xx_radio_read16(dev, 0x52) & 0xFFF0) |
1634 phy->lo_control->tx_bias);
1635 }
1636 if (phy->rev >= 6) {
1637 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x36),
1638 (bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x36))
1639 & 0x0FFF) | (phy->lo_control->tx_bias << 12));
1640 }
1641 if (dev->dev->bus->sprom.r1.boardflags_lo & BCM43xx_BFL_PACTRL)
1642 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x2E), 0x8075);
1643 else
1644 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x2E), 0x807F);
1645 if (phy->rev < 2)
1646 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x2F), 0x101);
1647 else
1648 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x2F), 0x202);
1649 }
1650 if (phy->gmode || phy->rev >= 2) {
1651 bcm43xx_lo_g_adjust(dev);
1652 bcm43xx_phy_write(dev, BCM43xx_PHY_LO_MASK, 0x8078);
1653 }
1654
1655 if (!(dev->dev->bus->sprom.r1.boardflags_lo & BCM43xx_BFL_RSSI)) {
1656 /* The specs state to update the NRSSI LT with
1657 * the value 0x7FFFFFFF here. I think that is some weird
1658 * compiler optimization in the original driver.
1659 * Essentially, what we do here is resetting all NRSSI LT
1660 * entries to -32 (see the limit_value() in nrssi_hw_update())
1661 */
1662 bcm43xx_nrssi_hw_update(dev, 0xFFFF);//FIXME?
1663 bcm43xx_calc_nrssi_threshold(dev);
1664 } else if (phy->gmode || phy->rev >= 2) {
1665 if (phy->nrssi[0] == -1000) {
1666 assert(phy->nrssi[1] == -1000);
1667 bcm43xx_calc_nrssi_slope(dev);
1668 } else
1669 bcm43xx_calc_nrssi_threshold(dev);
1670 }
1671 if (phy->radio_rev == 8)
1672 bcm43xx_phy_write(dev, BCM43xx_PHY_EXTG(0x05), 0x3230);
1673 bcm43xx_phy_init_pctl(dev);
1674 /* FIXME: The spec says in the following if, the 0 should be replaced
1675 'if OFDM may not be used in the current locale'
1676 but OFDM is legal everywhere */
1677 if ((dev->dev->bus->chip_id == 0x4306 && dev->dev->bus->chip_package == 2) || 0) {
1678 bcm43xx_phy_write(dev, BCM43xx_PHY_CRS0,
1679 bcm43xx_phy_read(dev, BCM43xx_PHY_CRS0)
1680 & 0xBFFF);
1681 bcm43xx_phy_write(dev, BCM43xx_PHY_OFDM(0xC3),
1682 bcm43xx_phy_read(dev, BCM43xx_PHY_OFDM(0xC3))
1683 & 0x7FFF);
1684 }
1685 }
1686
1687 /* Set the baseband attenuation value on chip. */
1688 void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_wldev *dev,
1689 u16 baseband_attenuation)
1690 {
1691 struct bcm43xx_phy *phy = &dev->phy;
1692 u16 value;
1693
1694 if (phy->analog == 0) {
1695 value = (bcm43xx_read16(dev, 0x03E6) & 0xFFF0);
1696 value |= (baseband_attenuation & 0x000F);
1697 bcm43xx_write16(dev, 0x03E6, value);
1698 return;
1699 }
1700
1701 if (phy->analog > 1) {
1702 value = bcm43xx_phy_read(dev, 0x0060) & ~0x003C;
1703 value |= (baseband_attenuation << 2) & 0x003C;
1704 } else {
1705 value = bcm43xx_phy_read(dev, 0x0060) & ~0x0078;
1706 value |= (baseband_attenuation << 3) & 0x0078;
1707 }
1708 bcm43xx_phy_write(dev, 0x0060, value);
1709 }
1710
1711 /* http://bcm-specs.sipsolutions.net/EstimatePowerOut
1712 * This function converts a TSSI value to dBm in Q5.2
1713 */
1714 static s8 bcm43xx_phy_estimate_power_out(struct bcm43xx_wldev *dev, s8 tssi)
1715 {
1716 struct bcm43xx_phy *phy = &dev->phy;
1717 s8 dbm = 0;
1718 s32 tmp;
1719
1720 tmp = (phy->tgt_idle_tssi - phy->cur_idle_tssi + tssi);
1721
1722 switch (phy->type) {
1723 case BCM43xx_PHYTYPE_A:
1724 tmp += 0x80;
1725 tmp = limit_value(tmp, 0x00, 0xFF);
1726 dbm = phy->tssi2dbm[tmp];
1727 TODO(); //TODO: There's a FIXME on the specs
1728 break;
1729 case BCM43xx_PHYTYPE_B:
1730 case BCM43xx_PHYTYPE_G:
1731 tmp = limit_value(tmp, 0x00, 0x3F);
1732 dbm = phy->tssi2dbm[tmp];
1733 break;
1734 default:
1735 assert(0);
1736 }
1737
1738 return dbm;
1739 }
1740
1741 static void put_attenuation_into_ranges(struct bcm43xx_wldev *dev,
1742 int *_rfatt, int *_bbatt)
1743 {
1744 int rfatt = *_rfatt;
1745 int bbatt = *_bbatt;
1746
1747 /* Get baseband and radio attenuation values into their permitted ranges.
1748 * Radio attenuation affects power level 4 times as much as baseband. */
1749
1750 /* Range constants */
1751 const int rf_min = 0;
1752 const int rf_max = 9;
1753 const int bb_min = 0;
1754 const int bb_max = 11;
1755
1756 while (1) {
1757 if (rfatt > rf_max &&
1758 bbatt > bb_max - 4)
1759 break; /* Can not get it into ranges */
1760 if (rfatt < rf_min &&
1761 bbatt < bb_min + 4)
1762 break; /* Can not get it into ranges */
1763 if (bbatt > bb_max &&
1764 rfatt > rf_max - 1)
1765 break; /* Can not get it into ranges */
1766 if (bbatt < bb_min &&
1767 rfatt < rf_min + 1)
1768 break; /* Can not get it into ranges */
1769
1770 if (bbatt > bb_max) {
1771 bbatt -= 4;
1772 rfatt += 1;
1773 continue;
1774 }
1775 if (bbatt < bb_min) {
1776 bbatt += 4;
1777 rfatt -= 1;
1778 continue;
1779 }
1780 if (rfatt > rf_max) {
1781 rfatt -= 1;
1782 bbatt += 4;
1783 continue;
1784 }
1785 if (rfatt < rf_min) {
1786 rfatt += 1;
1787 bbatt -= 4;
1788 continue;
1789 }
1790 break;
1791 }
1792
1793 *_rfatt = limit_value(rfatt, rf_min, rf_max);
1794 *_bbatt = limit_value(bbatt, bb_min, bb_max);
1795 }
1796
1797 /* http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower */
1798 void bcm43xx_phy_xmitpower(struct bcm43xx_wldev *dev)
1799 {
1800 struct ssb_bus *bus = dev->dev->bus;
1801 struct bcm43xx_phy *phy = &dev->phy;
1802
1803 if (phy->cur_idle_tssi == 0)
1804 return;
1805 if ((bus->board_vendor == SSB_BOARDVENDOR_BCM) &&
1806 (bus->board_type == SSB_BOARD_BU4306))
1807 return;
1808
1809 switch (phy->type) {
1810 case BCM43xx_PHYTYPE_A: {
1811
1812 TODO(); //TODO: Nothing for A PHYs yet :-/
1813
1814 break;
1815 }
1816 case BCM43xx_PHYTYPE_B:
1817 case BCM43xx_PHYTYPE_G: {
1818 u16 tmp;
1819 u16 txpower;
1820 s8 v0, v1, v2, v3;
1821 s8 average;
1822 u8 max_pwr;
1823 s16 desired_pwr, estimated_pwr, pwr_adjust;
1824 int radio_att_delta, baseband_att_delta;
1825 int radio_attenuation, baseband_attenuation;
1826 unsigned long phylock_flags;
1827
1828 tmp = bcm43xx_shm_read16(dev, BCM43xx_SHM_SHARED, 0x0058);
1829 v0 = (s8)(tmp & 0x00FF);
1830 v1 = (s8)((tmp & 0xFF00) >> 8);
1831 tmp = bcm43xx_shm_read16(dev, BCM43xx_SHM_SHARED, 0x005A);
1832 v2 = (s8)(tmp & 0x00FF);
1833 v3 = (s8)((tmp & 0xFF00) >> 8);
1834 tmp = 0;
1835
1836 if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F) {
1837 tmp = bcm43xx_shm_read16(dev, BCM43xx_SHM_SHARED, 0x0070);
1838 v0 = (s8)(tmp & 0x00FF);
1839 v1 = (s8)((tmp & 0xFF00) >> 8);
1840 tmp = bcm43xx_shm_read16(dev, BCM43xx_SHM_SHARED, 0x0072);
1841 v2 = (s8)(tmp & 0x00FF);
1842 v3 = (s8)((tmp & 0xFF00) >> 8);
1843 if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F)
1844 return;
1845 v0 = (v0 + 0x20) & 0x3F;
1846 v1 = (v1 + 0x20) & 0x3F;
1847 v2 = (v2 + 0x20) & 0x3F;
1848 v3 = (v3 + 0x20) & 0x3F;
1849 tmp = 1;
1850 }
1851 bcm43xx_shm_clear_tssi(dev);
1852
1853 average = (v0 + v1 + v2 + v3 + 2) / 4;
1854
1855 if (tmp && (bcm43xx_shm_read16(dev, BCM43xx_SHM_SHARED, 0x005E) & 0x8))
1856 average -= 13;
1857
1858 estimated_pwr = bcm43xx_phy_estimate_power_out(dev, average);
1859
1860 max_pwr = dev->dev->bus->sprom.r1.maxpwr_bg;
1861
1862 if ((dev->dev->bus->sprom.r1.boardflags_lo & BCM43xx_BFL_PACTRL) &&
1863 (phy->type == BCM43xx_PHYTYPE_G))
1864 max_pwr -= 0x3;
1865
1866 /*TODO:
1867 max_pwr = min(REG - dev->dev->bus->sprom.antennagain_bgphy - 0x6, max_pwr)
1868 where REG is the max power as per the regulatory domain
1869 */
1870
1871 desired_pwr = phy->power_level;
1872 /* Convert the desired_pwr to Q5.2 and limit it. */
1873 desired_pwr = limit_value((desired_pwr << 2), 0, max_pwr);
1874
1875 pwr_adjust = desired_pwr - estimated_pwr;
1876 radio_att_delta = -((pwr_adjust + 7) >> 3);
1877 baseband_att_delta = (-(pwr_adjust >> 1)) - (4 * radio_att_delta);
1878 if ((radio_att_delta == 0) && (baseband_att_delta == 0)) {
1879 bcm43xx_lo_g_ctl_mark_cur_used(dev);
1880 return;
1881 }
1882
1883 /* Calculate the new attenuation values. */
1884 baseband_attenuation = phy->bbatt;
1885 baseband_attenuation += baseband_att_delta;
1886 radio_attenuation = phy->rfatt;
1887 radio_attenuation += radio_att_delta;
1888 put_attenuation_into_ranges(dev, &radio_attenuation,
1889 &baseband_attenuation);
1890
1891 txpower = phy->txctl1;
1892 if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 2)) {
1893 if (radio_attenuation <= 1) {
1894 if (txpower == 0) {
1895 txpower = 3;
1896 radio_attenuation += 2;
1897 baseband_attenuation += 2;
1898 } else if (dev->dev->bus->sprom.r1.boardflags_lo & BCM43xx_BFL_PACTRL) {
1899 baseband_attenuation += 4 * (radio_attenuation - 2);
1900 radio_attenuation = 2;
1901 }
1902 } else if (radio_attenuation > 4 && txpower != 0) {
1903 txpower = 0;
1904 if (baseband_attenuation < 3) {
1905 radio_attenuation -= 3;
1906 baseband_attenuation += 2;
1907 } else {
1908 radio_attenuation -= 2;
1909 baseband_attenuation -= 2;
1910 }
1911 }
1912 }
1913 phy->txctl1 = txpower;
1914 baseband_attenuation = limit_value(baseband_attenuation, 0, 11);
1915 radio_attenuation = limit_value(radio_attenuation, 0, 9);
1916
1917 bcm43xx_phy_lock(dev, phylock_flags);
1918 bcm43xx_radio_lock(dev);
1919 bcm43xx_radio_set_txpower_bg(dev, baseband_attenuation,
1920 radio_attenuation, txpower);
1921 bcm43xx_lo_g_ctl_mark_cur_used(dev);
1922 bcm43xx_radio_unlock(dev);
1923 bcm43xx_phy_unlock(dev, phylock_flags);
1924 break;
1925 }
1926 default:
1927 assert(0);
1928 }
1929 }
1930
1931 static inline
1932 s32 bcm43xx_tssi2dbm_ad(s32 num, s32 den)
1933 {
1934 if (num < 0)
1935 return num/den;
1936 else
1937 return (num+den/2)/den;
1938 }
1939
1940 static inline
1941 s8 bcm43xx_tssi2dbm_entry(s8 entry [], u8 index, s16 pab0, s16 pab1, s16 pab2)
1942 {
1943 s32 m1, m2, f = 256, q, delta;
1944 s8 i = 0;
1945
1946 m1 = bcm43xx_tssi2dbm_ad(16 * pab0 + index * pab1, 32);
1947 m2 = max(bcm43xx_tssi2dbm_ad(32768 + index * pab2, 256), 1);
1948 do {
1949 if (i > 15)
1950 return -EINVAL;
1951 q = bcm43xx_tssi2dbm_ad(f * 4096 -
1952 bcm43xx_tssi2dbm_ad(m2 * f, 16) * f, 2048);
1953 delta = abs(q - f);
1954 f = q;
1955 i++;
1956 } while (delta >= 2);
1957 entry[index] = limit_value(bcm43xx_tssi2dbm_ad(m1 * f, 8192), -127, 128);
1958 return 0;
1959 }
1960
1961 /* http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table */
1962 int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_wldev *dev)
1963 {
1964 struct bcm43xx_phy *phy = &dev->phy;
1965 s16 pab0, pab1, pab2;
1966 u8 idx;
1967 s8 *dyn_tssi2dbm;
1968
1969 if (phy->type == BCM43xx_PHYTYPE_A) {
1970 pab0 = (s16)(dev->dev->bus->sprom.r1.pa1b0);
1971 pab1 = (s16)(dev->dev->bus->sprom.r1.pa1b1);
1972 pab2 = (s16)(dev->dev->bus->sprom.r1.pa1b2);
1973 } else {
1974 pab0 = (s16)(dev->dev->bus->sprom.r1.pa0b0);
1975 pab1 = (s16)(dev->dev->bus->sprom.r1.pa0b1);
1976 pab2 = (s16)(dev->dev->bus->sprom.r1.pa0b2);
1977 }
1978
1979 if ((dev->dev->bus->chip_id == 0x4301) && (phy->radio_ver != 0x2050)) {
1980 phy->tgt_idle_tssi = 0x34;
1981 phy->tssi2dbm = bcm43xx_tssi2dbm_b_table;
1982 return 0;
1983 }
1984
1985 if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
1986 pab0 != -1 && pab1 != -1 && pab2 != -1) {
1987 /* The pabX values are set in SPROM. Use them. */
1988 if (phy->type == BCM43xx_PHYTYPE_A) {
1989 if ((s8)dev->dev->bus->sprom.r1.itssi_a != 0 &&
1990 (s8)dev->dev->bus->sprom.r1.itssi_a != -1)
1991 phy->tgt_idle_tssi = (s8)(dev->dev->bus->sprom.r1.itssi_a);
1992 else
1993 phy->tgt_idle_tssi = 62;
1994 } else {
1995 if ((s8)dev->dev->bus->sprom.r1.itssi_bg != 0 &&
1996 (s8)dev->dev->bus->sprom.r1.itssi_bg != -1)
1997 phy->tgt_idle_tssi = (s8)(dev->dev->bus->sprom.r1.itssi_bg);
1998 else
1999 phy->tgt_idle_tssi = 62;
2000 }
2001 dyn_tssi2dbm = kmalloc(64, GFP_KERNEL);
2002 if (dyn_tssi2dbm == NULL) {
2003 printk(KERN_ERR PFX "Could not allocate memory"
2004 "for tssi2dbm table\n");
2005 return -ENOMEM;
2006 }
2007 for (idx = 0; idx < 64; idx++)
2008 if (bcm43xx_tssi2dbm_entry(dyn_tssi2dbm, idx, pab0, pab1, pab2)) {
2009 phy->tssi2dbm = NULL;
2010 printk(KERN_ERR PFX "Could not generate "
2011 "tssi2dBm table\n");
2012 kfree(dyn_tssi2dbm);
2013 return -ENODEV;
2014 }
2015 phy->tssi2dbm = dyn_tssi2dbm;
2016 phy->dyn_tssi_tbl = 1;
2017 } else {
2018 /* pabX values not set in SPROM. */
2019 switch (phy->type) {
2020 case BCM43xx_PHYTYPE_A:
2021 /* APHY needs a generated table. */
2022 phy->tssi2dbm = NULL;
2023 printk(KERN_ERR PFX "Could not generate tssi2dBm "
2024 "table (wrong SPROM info)!\n");
2025 return -ENODEV;
2026 case BCM43xx_PHYTYPE_B:
2027 phy->tgt_idle_tssi = 0x34;
2028 phy->tssi2dbm = bcm43xx_tssi2dbm_b_table;
2029 break;
2030 case BCM43xx_PHYTYPE_G:
2031 phy->tgt_idle_tssi = 0x34;
2032 phy->tssi2dbm = bcm43xx_tssi2dbm_g_table;
2033 break;
2034 }
2035 }
2036
2037 return 0;
2038 }
2039
2040 int bcm43xx_phy_init(struct bcm43xx_wldev *dev)
2041 {
2042 struct bcm43xx_phy *phy = &dev->phy;
2043 int err = -ENODEV;
2044
2045 switch (phy->type) {
2046 case BCM43xx_PHYTYPE_A:
2047 if (phy->rev == 2 || phy->rev == 3) {
2048 bcm43xx_phy_inita(dev);
2049 err = 0;
2050 }
2051 break;
2052 case BCM43xx_PHYTYPE_B:
2053 switch (phy->rev) {
2054 case 2:
2055 bcm43xx_phy_initb2(dev);
2056 err = 0;
2057 break;
2058 case 4:
2059 bcm43xx_phy_initb4(dev);
2060 err = 0;
2061 break;
2062 case 5:
2063 bcm43xx_phy_initb5(dev);
2064 err = 0;
2065 break;
2066 case 6:
2067 bcm43xx_phy_initb6(dev);
2068 err = 0;
2069 break;
2070 }
2071 break;
2072 case BCM43xx_PHYTYPE_G:
2073 bcm43xx_phy_initg(dev);
2074 err = 0;
2075 break;
2076 }
2077 if (err)
2078 printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n");
2079
2080 return err;
2081 }
2082
2083 void bcm43xx_set_rx_antenna(struct bcm43xx_wldev *dev, int antenna)
2084 {
2085 struct bcm43xx_phy *phy = &dev->phy;
2086 u32 hf;
2087 u16 tmp;
2088 int autodiv = 0;
2089
2090 if (antenna == BCM43xx_ANTENNA_AUTO0 ||
2091 antenna == BCM43xx_ANTENNA_AUTO1)
2092 autodiv = 1;
2093
2094 hf = bcm43xx_hf_read(dev);
2095 hf &= ~BCM43xx_HF_ANTDIVHELP;
2096 bcm43xx_hf_write(dev, hf);
2097
2098 switch (phy->type) {
2099 case BCM43xx_PHYTYPE_A:
2100 case BCM43xx_PHYTYPE_G:
2101 tmp = bcm43xx_phy_read(dev, BCM43xx_PHY_BBANDCFG);
2102 tmp &= ~BCM43xx_PHY_BBANDCFG_RXANT;
2103 tmp |= (autodiv ? BCM43xx_ANTENNA_AUTO0 : antenna)
2104 << BCM43xx_PHY_BBANDCFG_RXANT_SHIFT;
2105 bcm43xx_phy_write(dev, BCM43xx_PHY_BBANDCFG, tmp);
2106
2107 if (autodiv) {
2108 tmp = bcm43xx_phy_read(dev, BCM43xx_PHY_ANTDWELL);
2109 if (antenna == BCM43xx_ANTENNA_AUTO0)
2110 tmp &= ~BCM43xx_PHY_ANTDWELL_AUTODIV1;
2111 else
2112 tmp |= BCM43xx_PHY_ANTDWELL_AUTODIV1;
2113 bcm43xx_phy_write(dev, BCM43xx_PHY_ANTDWELL, tmp);
2114 }
2115 if (phy->type == BCM43xx_PHYTYPE_G) {
2116 tmp = bcm43xx_phy_read(dev, BCM43xx_PHY_ANTWRSETT);
2117 if (autodiv)
2118 tmp |= BCM43xx_PHY_ANTWRSETT_ARXDIV;
2119 else
2120 tmp &= ~BCM43xx_PHY_ANTWRSETT_ARXDIV;
2121 bcm43xx_phy_write(dev, BCM43xx_PHY_ANTWRSETT, tmp);
2122 if (phy->rev >= 2) {
2123 tmp = bcm43xx_phy_read(dev, BCM43xx_PHY_OFDM61);
2124 tmp |= BCM43xx_PHY_OFDM61_10;
2125 bcm43xx_phy_write(dev, BCM43xx_PHY_OFDM61, tmp);
2126
2127 tmp = bcm43xx_phy_read(dev, BCM43xx_PHY_DIVSRCHGAINBACK);
2128 tmp = (tmp & 0xFF00) | 0x15;
2129 bcm43xx_phy_write(dev, BCM43xx_PHY_DIVSRCHGAINBACK, tmp);
2130
2131 if (phy->rev == 2) {
2132 bcm43xx_phy_write(dev, BCM43xx_PHY_ADIVRELATED, 8);
2133 } else {
2134 tmp = bcm43xx_phy_read(dev, BCM43xx_PHY_ADIVRELATED);
2135 tmp = (tmp & 0xFF00) | 8;
2136 bcm43xx_phy_write(dev, BCM43xx_PHY_ADIVRELATED, tmp);
2137 }
2138 }
2139 if (phy->rev >= 6)
2140 bcm43xx_phy_write(dev, BCM43xx_PHY_OFDM9B, 0xDC);
2141 } else {
2142 if (phy->rev < 3) {
2143 tmp = bcm43xx_phy_read(dev, BCM43xx_PHY_ANTDWELL);
2144 tmp = (tmp & 0xFF00) | 0x24;
2145 bcm43xx_phy_write(dev, BCM43xx_PHY_ANTDWELL, tmp);
2146 } else {
2147 tmp = bcm43xx_phy_read(dev, BCM43xx_PHY_OFDM61);
2148 tmp |= 0x10;
2149 bcm43xx_phy_write(dev, BCM43xx_PHY_OFDM61, tmp);
2150 if (phy->analog == 3) {
2151 bcm43xx_phy_write(dev, BCM43xx_PHY_CLIPPWRDOWNT, 0x1D);
2152 bcm43xx_phy_write(dev, BCM43xx_PHY_ADIVRELATED, 8);
2153 } else {
2154 bcm43xx_phy_write(dev, BCM43xx_PHY_CLIPPWRDOWNT, 0x3A);
2155 tmp = bcm43xx_phy_read(dev, BCM43xx_PHY_ADIVRELATED);
2156 tmp = (tmp & 0xFF00) | 8;
2157 bcm43xx_phy_write(dev, BCM43xx_PHY_ADIVRELATED, tmp);
2158 }
2159 }
2160 }
2161 break;
2162 case BCM43xx_PHYTYPE_B:
2163 tmp = bcm43xx_phy_read(dev, BCM43xx_PHY_CCKBBANDCFG);
2164 tmp &= ~BCM43xx_PHY_BBANDCFG_RXANT;
2165 tmp |= (autodiv ? BCM43xx_ANTENNA_AUTO0 : antenna)
2166 << BCM43xx_PHY_BBANDCFG_RXANT_SHIFT;
2167 bcm43xx_phy_write(dev, BCM43xx_PHY_CCKBBANDCFG, tmp);
2168 break;
2169 default:
2170 assert(0);
2171 }
2172
2173 hf |= BCM43xx_HF_ANTDIVHELP;
2174 bcm43xx_hf_write(dev, hf);
2175 }
2176
2177 /* Get the freq, as it has to be written to the device. */
2178 static inline
2179 u16 channel2freq_bg(u8 channel)
2180 {
2181 assert(channel >= 1 && channel <= 14);
2182
2183 return bcm43xx_radio_channel_codes_bg[channel - 1];
2184 }
2185
2186 /* Get the freq, as it has to be written to the device. */
2187 static inline
2188 u16 channel2freq_a(u8 channel)
2189 {
2190 assert(channel <= 200);
2191
2192 return (5000 + 5 * channel);
2193 }
2194
2195 void bcm43xx_radio_lock(struct bcm43xx_wldev *dev)
2196 {
2197 u32 status;
2198
2199 status = bcm43xx_read32(dev, BCM43xx_MMIO_STATUS_BITFIELD);
2200 status |= BCM43xx_SBF_RADIOREG_LOCK;
2201 bcm43xx_write32(dev, BCM43xx_MMIO_STATUS_BITFIELD, status);
2202 mmiowb();
2203 udelay(10);
2204 }
2205
2206 void bcm43xx_radio_unlock(struct bcm43xx_wldev *dev)
2207 {
2208 u32 status;
2209
2210 bcm43xx_read16(dev, BCM43xx_MMIO_PHY_VER); /* dummy read */
2211 status = bcm43xx_read32(dev, BCM43xx_MMIO_STATUS_BITFIELD);
2212 status &= ~BCM43xx_SBF_RADIOREG_LOCK;
2213 bcm43xx_write32(dev, BCM43xx_MMIO_STATUS_BITFIELD, status);
2214 mmiowb();
2215 }
2216
2217 u16 bcm43xx_radio_read16(struct bcm43xx_wldev *dev, u16 offset)
2218 {
2219 struct bcm43xx_phy *phy = &dev->phy;
2220
2221 switch (phy->type) {
2222 case BCM43xx_PHYTYPE_A:
2223 offset |= 0x0040;
2224 break;
2225 case BCM43xx_PHYTYPE_B:
2226 if (phy->radio_ver == 0x2053) {
2227 if (offset < 0x70)
2228 offset += 0x80;
2229 else if (offset < 0x80)
2230 offset += 0x70;
2231 } else if (phy->radio_ver == 0x2050) {
2232 offset |= 0x80;
2233 } else
2234 assert(0);
2235 break;
2236 case BCM43xx_PHYTYPE_G:
2237 offset |= 0x80;
2238 break;
2239 }
2240
2241 bcm43xx_write16(dev, BCM43xx_MMIO_RADIO_CONTROL, offset);
2242 return bcm43xx_read16(dev, BCM43xx_MMIO_RADIO_DATA_LOW);
2243 }
2244
2245 void bcm43xx_radio_write16(struct bcm43xx_wldev *dev, u16 offset, u16 val)
2246 {
2247 bcm43xx_write16(dev, BCM43xx_MMIO_RADIO_CONTROL, offset);
2248 mmiowb();
2249 bcm43xx_write16(dev, BCM43xx_MMIO_RADIO_DATA_LOW, val);
2250 }
2251
2252 static void bcm43xx_set_all_gains(struct bcm43xx_wldev *dev,
2253 s16 first, s16 second, s16 third)
2254 {
2255 struct bcm43xx_phy *phy = &dev->phy;
2256 u16 i;
2257 u16 start = 0x08, end = 0x18;
2258 u16 tmp;
2259 u16 table;
2260
2261 if (phy->rev <= 1) {
2262 start = 0x10;
2263 end = 0x20;
2264 }
2265
2266 table = BCM43xx_OFDMTAB_GAINX;
2267 if (phy->rev <= 1)
2268 table = BCM43xx_OFDMTAB_GAINX_R1;
2269 for (i = 0; i < 4; i++)
2270 bcm43xx_ofdmtab_write16(dev, table, i, first);
2271
2272 for (i = start; i < end; i++)
2273 bcm43xx_ofdmtab_write16(dev, table, i, second);
2274
2275 if (third != -1) {
2276 tmp = ((u16)third << 14) | ((u16)third << 6);
2277 bcm43xx_phy_write(dev, 0x04A0,
2278 (bcm43xx_phy_read(dev, 0x04A0) & 0xBFBF) | tmp);
2279 bcm43xx_phy_write(dev, 0x04A1,
2280 (bcm43xx_phy_read(dev, 0x04A1) & 0xBFBF) | tmp);
2281 bcm43xx_phy_write(dev, 0x04A2,
2282 (bcm43xx_phy_read(dev, 0x04A2) & 0xBFBF) | tmp);
2283 }
2284 bcm43xx_dummy_transmission(dev);
2285 }
2286
2287 static void bcm43xx_set_original_gains(struct bcm43xx_wldev *dev)
2288 {
2289 struct bcm43xx_phy *phy = &dev->phy;
2290 u16 i, tmp;
2291 u16 table;
2292 u16 start = 0x0008, end = 0x0018;
2293
2294 if (phy->rev <= 1) {
2295 start = 0x0010;
2296 end = 0x0020;
2297 }
2298
2299 table = BCM43xx_OFDMTAB_GAINX;
2300 if (phy->rev <= 1)
2301 table = BCM43xx_OFDMTAB_GAINX_R1;
2302 for (i = 0; i < 4; i++) {
2303 tmp = (i & 0xFFFC);
2304 tmp |= (i & 0x0001) << 1;
2305 tmp |= (i & 0x0002) >> 1;
2306
2307 bcm43xx_ofdmtab_write16(dev, table, i, tmp);
2308 }
2309
2310 for (i = start; i < end; i++)
2311 bcm43xx_ofdmtab_write16(dev, table, i, i - start);
2312
2313 bcm43xx_phy_write(dev, 0x04A0,
2314 (bcm43xx_phy_read(dev, 0x04A0) & 0xBFBF) | 0x4040);
2315 bcm43xx_phy_write(dev, 0x04A1,
2316 (bcm43xx_phy_read(dev, 0x04A1) & 0xBFBF) | 0x4040);
2317 bcm43xx_phy_write(dev, 0x04A2,
2318 (bcm43xx_phy_read(dev, 0x04A2) & 0xBFBF) | 0x4000);
2319 bcm43xx_dummy_transmission(dev);
2320 }
2321
2322 /* Synthetic PU workaround */
2323 static void bcm43xx_synth_pu_workaround(struct bcm43xx_wldev *dev, u8 channel)
2324 {
2325 struct bcm43xx_phy *phy = &dev->phy;
2326
2327 if (phy->radio_ver != 0x2050 || phy->radio_rev >= 6) {
2328 /* We do not need the workaround. */
2329 return;
2330 }
2331
2332 if (channel <= 10) {
2333 bcm43xx_write16(dev, BCM43xx_MMIO_CHANNEL,
2334 channel2freq_bg(channel + 4));
2335 } else {
2336 bcm43xx_write16(dev, BCM43xx_MMIO_CHANNEL,
2337 channel2freq_bg(1));
2338 }
2339 udelay(100);
2340 bcm43xx_write16(dev, BCM43xx_MMIO_CHANNEL,
2341 channel2freq_bg(channel));
2342 }
2343
2344 u8 bcm43xx_radio_aci_detect(struct bcm43xx_wldev *dev, u8 channel)
2345 {
2346 struct bcm43xx_phy *phy = &dev->phy;
2347 u8 ret = 0;
2348 u16 saved, rssi, temp;
2349 int i, j = 0;
2350
2351 saved = bcm43xx_phy_read(dev, 0x0403);
2352 bcm43xx_radio_selectchannel(dev, channel, 0);
2353 bcm43xx_phy_write(dev, 0x0403, (saved & 0xFFF8) | 5);
2354 if (phy->aci_hw_rssi)
2355 rssi = bcm43xx_phy_read(dev, 0x048A) & 0x3F;
2356 else
2357 rssi = saved & 0x3F;
2358 /* clamp temp to signed 5bit */
2359 if (rssi > 32)
2360 rssi -= 64;
2361 for (i = 0;i < 100; i++) {
2362 temp = (bcm43xx_phy_read(dev, 0x047F) >> 8) & 0x3F;
2363 if (temp > 32)
2364 temp -= 64;
2365 if (temp < rssi)
2366 j++;
2367 if (j >= 20)
2368 ret = 1;
2369 }
2370 bcm43xx_phy_write(dev, 0x0403, saved);
2371
2372 return ret;
2373 }
2374
2375 u8 bcm43xx_radio_aci_scan(struct bcm43xx_wldev *dev)
2376 {
2377 struct bcm43xx_phy *phy = &dev->phy;
2378 u8 ret[13];
2379 unsigned int channel = phy->channel;
2380 unsigned int i, j, start, end;
2381 unsigned long phylock_flags;
2382
2383 if (!((phy->type == BCM43xx_PHYTYPE_G) && (phy->rev > 0)))
2384 return 0;
2385
2386 bcm43xx_phy_lock(dev, phylock_flags);
2387 bcm43xx_radio_lock(dev);
2388 bcm43xx_phy_write(dev, 0x0802,
2389 bcm43xx_phy_read(dev, 0x0802) & 0xFFFC);
2390 bcm43xx_phy_write(dev, BCM43xx_PHY_G_CRS,
2391 bcm43xx_phy_read(dev, BCM43xx_PHY_G_CRS) & 0x7FFF);
2392 bcm43xx_set_all_gains(dev, 3, 8, 1);
2393
2394 start = (channel - 5 > 0) ? channel - 5 : 1;
2395 end = (channel + 5 < 14) ? channel + 5 : 13;
2396
2397 for (i = start; i <= end; i++) {
2398 if (abs(channel - i) > 2)
2399 ret[i-1] = bcm43xx_radio_aci_detect(dev, i);
2400 }
2401 bcm43xx_radio_selectchannel(dev, channel, 0);
2402 bcm43xx_phy_write(dev, 0x0802,
2403 (bcm43xx_phy_read(dev, 0x0802) & 0xFFFC) | 0x0003);
2404 bcm43xx_phy_write(dev, 0x0403,
2405 bcm43xx_phy_read(dev, 0x0403) & 0xFFF8);
2406 bcm43xx_phy_write(dev, BCM43xx_PHY_G_CRS,
2407 bcm43xx_phy_read(dev, BCM43xx_PHY_G_CRS) | 0x8000);
2408 bcm43xx_set_original_gains(dev);
2409 for (i = 0; i < 13; i++) {
2410 if (!ret[i])
2411 continue;
2412 end = (i + 5 < 13) ? i + 5 : 13;
2413 for (j = i; j < end; j++)
2414 ret[j] = 1;
2415 }
2416 bcm43xx_radio_unlock(dev);
2417 bcm43xx_phy_unlock(dev, phylock_flags);
2418
2419 return ret[channel - 1];
2420 }
2421
2422 /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
2423 void bcm43xx_nrssi_hw_write(struct bcm43xx_wldev *dev, u16 offset, s16 val)
2424 {
2425 bcm43xx_phy_write(dev, BCM43xx_PHY_NRSSILT_CTRL, offset);
2426 mmiowb();
2427 bcm43xx_phy_write(dev, BCM43xx_PHY_NRSSILT_DATA, (u16)val);
2428 }
2429
2430 /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
2431 s16 bcm43xx_nrssi_hw_read(struct bcm43xx_wldev *dev, u16 offset)
2432 {
2433 u16 val;
2434
2435 bcm43xx_phy_write(dev, BCM43xx_PHY_NRSSILT_CTRL, offset);
2436 val = bcm43xx_phy_read(dev, BCM43xx_PHY_NRSSILT_DATA);
2437
2438 return (s16)val;
2439 }
2440
2441 /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
2442 void bcm43xx_nrssi_hw_update(struct bcm43xx_wldev *dev, u16 val)
2443 {
2444 u16 i;
2445 s16 tmp;
2446
2447 for (i = 0; i < 64; i++) {
2448 tmp = bcm43xx_nrssi_hw_read(dev, i);
2449 tmp -= val;
2450 tmp = limit_value(tmp, -32, 31);
2451 bcm43xx_nrssi_hw_write(dev, i, tmp);
2452 }
2453 }
2454
2455 /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
2456 void bcm43xx_nrssi_mem_update(struct bcm43xx_wldev *dev)
2457 {
2458 struct bcm43xx_phy *phy = &dev->phy;
2459 s16 i, delta;
2460 s32 tmp;
2461
2462 delta = 0x1F - phy->nrssi[0];
2463 for (i = 0; i < 64; i++) {
2464 tmp = (i - delta) * phy->nrssislope;
2465 tmp /= 0x10000;
2466 tmp += 0x3A;
2467 tmp = limit_value(tmp, 0, 0x3F);
2468 phy->nrssi_lt[i] = tmp;
2469 }
2470 }
2471
2472 static void bcm43xx_calc_nrssi_offset(struct bcm43xx_wldev *dev)
2473 {
2474 struct bcm43xx_phy *phy = &dev->phy;
2475 u16 backup[20] = { 0 };
2476 s16 v47F;
2477 u16 i;
2478 u16 saved = 0xFFFF;
2479
2480 backup[0] = bcm43xx_phy_read(dev, 0x0001);
2481 backup[1] = bcm43xx_phy_read(dev, 0x0811);
2482 backup[2] = bcm43xx_phy_read(dev, 0x0812);
2483 if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
2484 backup[3] = bcm43xx_phy_read(dev, 0x0814);
2485 backup[4] = bcm43xx_phy_read(dev, 0x0815);
2486 }
2487 backup[5] = bcm43xx_phy_read(dev, 0x005A);
2488 backup[6] = bcm43xx_phy_read(dev, 0x0059);
2489 backup[7] = bcm43xx_phy_read(dev, 0x0058);
2490 backup[8] = bcm43xx_phy_read(dev, 0x000A);
2491 backup[9] = bcm43xx_phy_read(dev, 0x0003);
2492 backup[10] = bcm43xx_radio_read16(dev, 0x007A);
2493 backup[11] = bcm43xx_radio_read16(dev, 0x0043);
2494
2495 bcm43xx_phy_write(dev, 0x0429,
2496 bcm43xx_phy_read(dev, 0x0429) & 0x7FFF);
2497 bcm43xx_phy_write(dev, 0x0001,
2498 (bcm43xx_phy_read(dev, 0x0001) & 0x3FFF) | 0x4000);
2499 bcm43xx_phy_write(dev, 0x0811,
2500 bcm43xx_phy_read(dev, 0x0811) | 0x000C);
2501 bcm43xx_phy_write(dev, 0x0812,
2502 (bcm43xx_phy_read(dev, 0x0812) & 0xFFF3) | 0x0004);
2503 bcm43xx_phy_write(dev, 0x0802,
2504 bcm43xx_phy_read(dev, 0x0802) & ~(0x1 | 0x2));
2505 if (phy->rev >= 6) {
2506 backup[12] = bcm43xx_phy_read(dev, 0x002E);
2507 backup[13] = bcm43xx_phy_read(dev, 0x002F);
2508 backup[14] = bcm43xx_phy_read(dev, 0x080F);
2509 backup[15] = bcm43xx_phy_read(dev, 0x0810);
2510 backup[16] = bcm43xx_phy_read(dev, 0x0801);
2511 backup[17] = bcm43xx_phy_read(dev, 0x0060);
2512 backup[18] = bcm43xx_phy_read(dev, 0x0014);
2513 backup[19] = bcm43xx_phy_read(dev, 0x0478);
2514
2515 bcm43xx_phy_write(dev, 0x002E, 0);
2516 bcm43xx_phy_write(dev, 0x002F, 0);
2517 bcm43xx_phy_write(dev, 0x080F, 0);
2518 bcm43xx_phy_write(dev, 0x0810, 0);
2519 bcm43xx_phy_write(dev, 0x0478,
2520 bcm43xx_phy_read(dev, 0x0478) | 0x0100);
2521 bcm43xx_phy_write(dev, 0x0801,
2522 bcm43xx_phy_read(dev, 0x0801) | 0x0040);
2523 bcm43xx_phy_write(dev, 0x0060,
2524 bcm43xx_phy_read(dev, 0x0060) | 0x0040);
2525 bcm43xx_phy_write(dev, 0x0014,
2526 bcm43xx_phy_read(dev, 0x0014) | 0x0200);
2527 }
2528 bcm43xx_radio_write16(dev, 0x007A,
2529 bcm43xx_radio_read16(dev, 0x007A) | 0x0070);
2530 bcm43xx_radio_write16(dev, 0x007A,
2531 bcm43xx_radio_read16(dev, 0x007A) | 0x0080);
2532 udelay(30);
2533
2534 v47F = (s16)((bcm43xx_phy_read(dev, 0x047F) >> 8) & 0x003F);
2535 if (v47F >= 0x20)
2536 v47F -= 0x40;
2537 if (v47F == 31) {
2538 for (i = 7; i >= 4; i--) {
2539 bcm43xx_radio_write16(dev, 0x007B, i);
2540 udelay(20);
2541 v47F = (s16)((bcm43xx_phy_read(dev, 0x047F) >> 8) & 0x003F);
2542 if (v47F >= 0x20)
2543 v47F -= 0x40;
2544 if (v47F < 31 && saved == 0xFFFF)
2545 saved = i;
2546 }
2547 if (saved == 0xFFFF)
2548 saved = 4;
2549 } else {
2550 bcm43xx_radio_write16(dev, 0x007A,
2551 bcm43xx_radio_read16(dev, 0x007A) & 0x007F);
2552 if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
2553 bcm43xx_phy_write(dev, 0x0814,
2554 bcm43xx_phy_read(dev, 0x0814) | 0x0001);
2555 bcm43xx_phy_write(dev, 0x0815,
2556 bcm43xx_phy_read(dev, 0x0815) & 0xFFFE);
2557 }
2558 bcm43xx_phy_write(dev, 0x0811,
2559 bcm43xx_phy_read(dev, 0x0811) | 0x000C);
2560 bcm43xx_phy_write(dev, 0x0812,
2561 bcm43xx_phy_read(dev, 0x0812) | 0x000C);
2562 bcm43xx_phy_write(dev, 0x0811,
2563 bcm43xx_phy_read(dev, 0x0811) | 0x0030);
2564 bcm43xx_phy_write(dev, 0x0812,
2565 bcm43xx_phy_read(dev, 0x0812) | 0x0030);
2566 bcm43xx_phy_write(dev, 0x005A, 0x0480);
2567 bcm43xx_phy_write(dev, 0x0059, 0x0810);
2568 bcm43xx_phy_write(dev, 0x0058, 0x000D);
2569 if (phy->rev == 0) {
2570 bcm43xx_phy_write(dev, 0x0003, 0x0122);
2571 } else {
2572 bcm43xx_phy_write(dev, 0x000A,
2573 bcm43xx_phy_read(dev, 0x000A)
2574 | 0x2000);
2575 }
2576 if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
2577 bcm43xx_phy_write(dev, 0x0814,
2578 bcm43xx_phy_read(dev, 0x0814) | 0x0004);
2579 bcm43xx_phy_write(dev, 0x0815,
2580 bcm43xx_phy_read(dev, 0x0815) & 0xFFFB);
2581 }
2582 bcm43xx_phy_write(dev, 0x0003,
2583 (bcm43xx_phy_read(dev, 0x0003) & 0xFF9F)
2584 | 0x0040);
2585 bcm43xx_radio_write16(dev, 0x007A,
2586 bcm43xx_radio_read16(dev, 0x007A) | 0x000F);
2587 bcm43xx_set_all_gains(dev, 3, 0, 1);
2588 bcm43xx_radio_write16(dev, 0x0043,
2589 (bcm43xx_radio_read16(dev, 0x0043)
2590 & 0x00F0) | 0x000F);
2591 udelay(30);
2592 v47F = (s16)((bcm43xx_phy_read(dev, 0x047F) >> 8) & 0x003F);
2593 if (v47F >= 0x20)
2594 v47F -= 0x40;
2595 if (v47F == -32) {
2596 for (i = 0; i < 4; i++) {
2597 bcm43xx_radio_write16(dev, 0x007B, i);
2598 udelay(20);
2599 v47F = (s16)((bcm43xx_phy_read(dev, 0x047F) >> 8) & 0x003F);
2600 if (v47F >= 0x20)
2601 v47F -= 0x40;
2602 if (v47F > -31 && saved == 0xFFFF)
2603 saved = i;
2604 }
2605 if (saved == 0xFFFF)
2606 saved = 3;
2607 } else
2608 saved = 0;
2609 }
2610 bcm43xx_radio_write16(dev, 0x007B, saved);
2611
2612 if (phy->rev >= 6) {
2613 bcm43xx_phy_write(dev, 0x002E, backup[12]);
2614 bcm43xx_phy_write(dev, 0x002F, backup[13]);
2615 bcm43xx_phy_write(dev, 0x080F, backup[14]);
2616 bcm43xx_phy_write(dev, 0x0810, backup[15]);
2617 }
2618 if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
2619 bcm43xx_phy_write(dev, 0x0814, backup[3]);
2620 bcm43xx_phy_write(dev, 0x0815, backup[4]);
2621 }
2622 bcm43xx_phy_write(dev, 0x005A, backup[5]);
2623 bcm43xx_phy_write(dev, 0x0059, backup[6]);
2624 bcm43xx_phy_write(dev, 0x0058, backup[7]);
2625 bcm43xx_phy_write(dev, 0x000A, backup[8]);
2626 bcm43xx_phy_write(dev, 0x0003, backup[9]);
2627 bcm43xx_radio_write16(dev, 0x0043, backup[11]);
2628 bcm43xx_radio_write16(dev, 0x007A, backup[10]);
2629 bcm43xx_phy_write(dev, 0x0802,
2630 bcm43xx_phy_read(dev, 0x0802) | 0x1 | 0x2);
2631 bcm43xx_phy_write(dev, 0x0429,
2632 bcm43xx_phy_read(dev, 0x0429) | 0x8000);
2633 bcm43xx_set_original_gains(dev);
2634 if (phy->rev >= 6) {
2635 bcm43xx_phy_write(dev, 0x0801, backup[16]);
2636 bcm43xx_phy_write(dev, 0x0060, backup[17]);
2637 bcm43xx_phy_write(dev, 0x0014, backup[18]);
2638 bcm43xx_phy_write(dev, 0x0478, backup[19]);
2639 }
2640 bcm43xx_phy_write(dev, 0x0001, backup[0]);
2641 bcm43xx_phy_write(dev, 0x0812, backup[2]);
2642 bcm43xx_phy_write(dev, 0x0811, backup[1]);
2643 }
2644
2645 void bcm43xx_calc_nrssi_slope(struct bcm43xx_wldev *dev)
2646 {
2647 struct bcm43xx_phy *phy = &dev->phy;
2648 u16 backup[18] = { 0 };
2649 u16 tmp;
2650 s16 nrssi0, nrssi1;
2651
2652 switch (phy->type) {
2653 case BCM43xx_PHYTYPE_B:
2654 backup[0] = bcm43xx_radio_read16(dev, 0x007A);
2655 backup[1] = bcm43xx_radio_read16(dev, 0x0052);
2656 backup[2] = bcm43xx_radio_read16(dev, 0x0043);
2657 backup[3] = bcm43xx_phy_read(dev, 0x0030);
2658 backup[4] = bcm43xx_phy_read(dev, 0x0026);
2659 backup[5] = bcm43xx_phy_read(dev, 0x0015);
2660 backup[6] = bcm43xx_phy_read(dev, 0x002A);
2661 backup[7] = bcm43xx_phy_read(dev, 0x0020);
2662 backup[8] = bcm43xx_phy_read(dev, 0x005A);
2663 backup[9] = bcm43xx_phy_read(dev, 0x0059);
2664 backup[10] = bcm43xx_phy_read(dev, 0x0058);
2665 backup[11] = bcm43xx_read16(dev, 0x03E2);
2666 backup[12] = bcm43xx_read16(dev, 0x03E6);
2667 backup[13] = bcm43xx_read16(dev, BCM43xx_MMIO_CHANNEL_EXT);
2668
2669 tmp = bcm43xx_radio_read16(dev, 0x007A);
2670 tmp &= (phy->rev >= 5) ? 0x007F : 0x000F;
2671 bcm43xx_radio_write16(dev, 0x007A, tmp);
2672 bcm43xx_phy_write(dev, 0x0030, 0x00FF);
2673 bcm43xx_write16(dev, 0x03EC, 0x7F7F);
2674 bcm43xx_phy_write(dev, 0x0026, 0x0000);
2675 bcm43xx_phy_write(dev, 0x0015,
2676 bcm43xx_phy_read(dev, 0x0015) | 0x0020);
2677 bcm43xx_phy_write(dev, 0x002A, 0x08A3);
2678 bcm43xx_radio_write16(dev, 0x007A,
2679 bcm43xx_radio_read16(dev, 0x007A) | 0x0080);
2680
2681 nrssi0 = (s16)bcm43xx_phy_read(dev, 0x0027);
2682 bcm43xx_radio_write16(dev, 0x007A,
2683 bcm43xx_radio_read16(dev, 0x007A) & 0x007F);
2684 if (phy->rev >= 2) {
2685 bcm43xx_write16(dev, 0x03E6, 0x0040);
2686 } else if (phy->rev == 0) {
2687 bcm43xx_write16(dev, 0x03E6, 0x0122);
2688 } else {
2689 bcm43xx_write16(dev, BCM43xx_MMIO_CHANNEL_EXT,
2690 bcm43xx_read16(dev, BCM43xx_MMIO_CHANNEL_EXT) & 0x2000);
2691 }
2692 bcm43xx_phy_write(dev, 0x0020, 0x3F3F);
2693 bcm43xx_phy_write(dev, 0x0015, 0xF330);
2694 bcm43xx_radio_write16(dev, 0x005A, 0x0060);
2695 bcm43xx_radio_write16(dev, 0x0043,
2696 bcm43xx_radio_read16(dev, 0x0043) & 0x00F0);
2697 bcm43xx_phy_write(dev, 0x005A, 0x0480);
2698 bcm43xx_phy_write(dev, 0x0059, 0x0810);
2699 bcm43xx_phy_write(dev, 0x0058, 0x000D);
2700 udelay(20);
2701
2702 nrssi1 = (s16)bcm43xx_phy_read(dev, 0x0027);
2703 bcm43xx_phy_write(dev, 0x0030, backup[3]);
2704 bcm43xx_radio_write16(dev, 0x007A, backup[0]);
2705 bcm43xx_write16(dev, 0x03E2, backup[11]);
2706 bcm43xx_phy_write(dev, 0x0026, backup[4]);
2707 bcm43xx_phy_write(dev, 0x0015, backup[5]);
2708 bcm43xx_phy_write(dev, 0x002A, backup[6]);
2709 bcm43xx_synth_pu_workaround(dev, phy->channel);
2710 if (phy->rev != 0)
2711 bcm43xx_write16(dev, 0x03F4, backup[13]);
2712
2713 bcm43xx_phy_write(dev, 0x0020, backup[7]);
2714 bcm43xx_phy_write(dev, 0x005A, backup[8]);
2715 bcm43xx_phy_write(dev, 0x0059, backup[9]);
2716 bcm43xx_phy_write(dev, 0x0058, backup[10]);
2717 bcm43xx_radio_write16(dev, 0x0052, backup[1]);
2718 bcm43xx_radio_write16(dev, 0x0043, backup[2]);
2719
2720 if (nrssi0 == nrssi1)
2721 phy->nrssislope = 0x00010000;
2722 else
2723 phy->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
2724
2725 if (nrssi0 <= -4) {
2726 phy->nrssi[0] = nrssi0;
2727 phy->nrssi[1] = nrssi1;
2728 }
2729 break;
2730 case BCM43xx_PHYTYPE_G:
2731 if (phy->radio_rev >= 9)
2732 return;
2733 if (phy->radio_rev == 8)
2734 bcm43xx_calc_nrssi_offset(dev);
2735
2736 bcm43xx_phy_write(dev, BCM43xx_PHY_G_CRS,
2737 bcm43xx_phy_read(dev, BCM43xx_PHY_G_CRS) & 0x7FFF);
2738 bcm43xx_phy_write(dev, 0x0802,
2739 bcm43xx_phy_read(dev, 0x0802) & 0xFFFC);
2740 backup[7] = bcm43xx_read16(dev, 0x03E2);
2741 bcm43xx_write16(dev, 0x03E2,
2742 bcm43xx_read16(dev, 0x03E2) | 0x8000);
2743 backup[0] = bcm43xx_radio_read16(dev, 0x007A);
2744 backup[1] = bcm43xx_radio_read16(dev, 0x0052);
2745 backup[2] = bcm43xx_radio_read16(dev, 0x0043);
2746 backup[3] = bcm43xx_phy_read(dev, 0x0015);
2747 backup[4] = bcm43xx_phy_read(dev, 0x005A);
2748 backup[5] = bcm43xx_phy_read(dev, 0x0059);
2749 backup[6] = bcm43xx_phy_read(dev, 0x0058);
2750 backup[8] = bcm43xx_read16(dev, 0x03E6);
2751 backup[9] = bcm43xx_read16(dev, BCM43xx_MMIO_CHANNEL_EXT);
2752 if (phy->rev >= 3) {
2753 backup[10] = bcm43xx_phy_read(dev, 0x002E);
2754 backup[11] = bcm43xx_phy_read(dev, 0x002F);
2755 backup[12] = bcm43xx_phy_read(dev, 0x080F);
2756 backup[13] = bcm43xx_phy_read(dev, BCM43xx_PHY_G_LO_CONTROL);
2757 backup[14] = bcm43xx_phy_read(dev, 0x0801);
2758 backup[15] = bcm43xx_phy_read(dev, 0x0060);
2759 backup[16] = bcm43xx_phy_read(dev, 0x0014);
2760 backup[17] = bcm43xx_phy_read(dev, 0x0478);
2761 bcm43xx_phy_write(dev, 0x002E, 0);
2762 bcm43xx_phy_write(dev, BCM43xx_PHY_G_LO_CONTROL, 0);
2763 switch (phy->rev) {
2764 case 4: case 6: case 7:
2765 bcm43xx_phy_write(dev, 0x0478,
2766 bcm43xx_phy_read(dev, 0x0478)
2767 | 0x0100);
2768 bcm43xx_phy_write(dev, 0x0801,
2769 bcm43xx_phy_read(dev, 0x0801)
2770 | 0x0040);
2771 break;
2772 case 3: case 5:
2773 bcm43xx_phy_write(dev, 0x0801,
2774 bcm43xx_phy_read(dev, 0x0801)
2775 & 0xFFBF);
2776 break;
2777 }
2778 bcm43xx_phy_write(dev, 0x0060,
2779 bcm43xx_phy_read(dev, 0x0060)
2780 | 0x0040);
2781 bcm43xx_phy_write(dev, 0x0014,
2782 bcm43xx_phy_read(dev, 0x0014)
2783 | 0x0200);
2784 }
2785 bcm43xx_radio_write16(dev, 0x007A,
2786 bcm43xx_radio_read16(dev, 0x007A) | 0x0070);
2787 bcm43xx_set_all_gains(dev, 0, 8, 0);
2788 bcm43xx_radio_write16(dev, 0x007A,
2789 bcm43xx_radio_read16(dev, 0x007A) & 0x00F7);
2790 if (phy->rev >= 2) {
2791 bcm43xx_phy_write(dev, 0x0811,
2792 (bcm43xx_phy_read(dev, 0x0811) & 0xFFCF) | 0x0030);
2793 bcm43xx_phy_write(dev, 0x0812,
2794 (bcm43xx_phy_read(dev, 0x0812) & 0xFFCF) | 0x0010);
2795 }
2796 bcm43xx_radio_write16(dev, 0x007A,
2797 bcm43xx_radio_read16(dev, 0x007A) | 0x0080);
2798 udelay(20);
2799
2800 nrssi0 = (s16)((bcm43xx_phy_read(dev, 0x047F) >> 8) & 0x003F);
2801 if (nrssi0 >= 0x0020)
2802 nrssi0 -= 0x0040;
2803
2804 bcm43xx_radio_write16(dev, 0x007A,
2805 bcm43xx_radio_read16(dev, 0x007A) & 0x007F);
2806 if (phy->rev >= 2) {
2807 bcm43xx_phy_write(dev, 0x0003,
2808 (bcm43xx_phy_read(dev, 0x0003)
2809 & 0xFF9F) | 0x0040);
2810 }
2811
2812 bcm43xx_write16(dev, BCM43xx_MMIO_CHANNEL_EXT,
2813 bcm43xx_read16(dev, BCM43xx_MMIO_CHANNEL_EXT)
2814 | 0x2000);
2815 bcm43xx_radio_write16(dev, 0x007A,
2816 bcm43xx_radio_read16(dev, 0x007A) | 0x000F);
2817 bcm43xx_phy_write(dev, 0x0015, 0xF330);
2818 if (phy->rev >= 2) {
2819 bcm43xx_phy_write(dev, 0x0812,
2820 (bcm43xx_phy_read(dev, 0x0812) & 0xFFCF) | 0x0020);
2821 bcm43xx_phy_write(dev, 0x0811,
2822 (bcm43xx_phy_read(dev, 0x0811) & 0xFFCF) | 0x0020);
2823 }
2824
2825 bcm43xx_set_all_gains(dev, 3, 0, 1);
2826 if (phy->radio_rev == 8) {
2827 bcm43xx_radio_write16(dev, 0x0043, 0x001F);
2828 } else {
2829 tmp = bcm43xx_radio_read16(dev, 0x0052) & 0xFF0F;
2830 bcm43xx_radio_write16(dev, 0x0052, tmp | 0x0060);
2831 tmp = bcm43xx_radio_read16(dev, 0x0043) & 0xFFF0;
2832 bcm43xx_radio_write16(dev, 0x0043, tmp | 0x0009);
2833 }
2834 bcm43xx_phy_write(dev, 0x005A, 0x0480);
2835 bcm43xx_phy_write(dev, 0x0059, 0x0810);
2836 bcm43xx_phy_write(dev, 0x0058, 0x000D);
2837 udelay(20);
2838 nrssi1 = (s16)((bcm43xx_phy_read(dev, 0x047F) >> 8) & 0x003F);
2839 if (nrssi1 >= 0x0020)
2840 nrssi1 -= 0x0040;
2841 if (nrssi0 == nrssi1)
2842 phy->nrssislope = 0x00010000;
2843 else
2844 phy->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
2845 if (nrssi0 >= -4) {
2846 phy->nrssi[0] = nrssi1;
2847 phy->nrssi[1] = nrssi0;
2848 }
2849 if (phy->rev >= 3) {
2850 bcm43xx_phy_write(dev, 0x002E, backup[10]);
2851 bcm43xx_phy_write(dev, 0x002F, backup[11]);
2852 bcm43xx_phy_write(dev, 0x080F, backup[12]);
2853 bcm43xx_phy_write(dev, BCM43xx_PHY_G_LO_CONTROL, backup[13]);
2854 }
2855 if (phy->rev >= 2) {
2856 bcm43xx_phy_write(dev, 0x0812,
2857 bcm43xx_phy_read(dev, 0x0812) & 0xFFCF);
2858 bcm43xx_phy_write(dev, 0x0811,
2859 bcm43xx_phy_read(dev, 0x0811) & 0xFFCF);
2860 }
2861
2862 bcm43xx_radio_write16(dev, 0x007A, backup[0]);
2863 bcm43xx_radio_write16(dev, 0x0052, backup[1]);
2864 bcm43xx_radio_write16(dev, 0x0043, backup[2]);
2865 bcm43xx_write16(dev, 0x03E2, backup[7]);
2866 bcm43xx_write16(dev, 0x03E6, backup[8]);
2867 bcm43xx_write16(dev, BCM43xx_MMIO_CHANNEL_EXT, backup[9]);
2868 bcm43xx_phy_write(dev, 0x0015, backup[3]);
2869 bcm43xx_phy_write(dev, 0x005A, backup[4]);
2870 bcm43xx_phy_write(dev, 0x0059, backup[5]);
2871 bcm43xx_phy_write(dev, 0x0058, backup[6]);
2872 bcm43xx_synth_pu_workaround(dev, phy->channel);
2873 bcm43xx_phy_write(dev, 0x0802,
2874 bcm43xx_phy_read(dev, 0x0802) | (0x0001 | 0x0002));
2875 bcm43xx_set_original_gains(dev);
2876 bcm43xx_phy_write(dev, BCM43xx_PHY_G_CRS,
2877 bcm43xx_phy_read(dev, BCM43xx_PHY_G_CRS) | 0x8000);
2878 if (phy->rev >= 3) {
2879 bcm43xx_phy_write(dev, 0x0801, backup[14]);
2880 bcm43xx_phy_write(dev, 0x0060, backup[15]);
2881 bcm43xx_phy_write(dev, 0x0014, backup[16]);
2882 bcm43xx_phy_write(dev, 0x0478, backup[17]);
2883 }
2884 bcm43xx_nrssi_mem_update(dev);
2885 bcm43xx_calc_nrssi_threshold(dev);
2886 break;
2887 default:
2888 assert(0);
2889 }
2890 }
2891
2892 void bcm43xx_calc_nrssi_threshold(struct bcm43xx_wldev *dev)
2893 {
2894 struct bcm43xx_phy *phy = &dev->phy;
2895 s32 threshold;
2896 s32 a, b;
2897 s16 tmp16;
2898 u16 tmp_u16;
2899
2900 switch (phy->type) {
2901 case BCM43xx_PHYTYPE_B: {
2902 if (phy->radio_ver != 0x2050)
2903 return;
2904 if (!(dev->dev->bus->sprom.r1.boardflags_lo & BCM43xx_BFL_RSSI))
2905 return;
2906
2907 if (phy->radio_rev >= 6) {
2908 threshold = (phy->nrssi[1] - phy->nrssi[0]) * 32;
2909 threshold += 20 * (phy->nrssi[0] + 1);
2910 threshold /= 40;
2911 } else
2912 threshold = phy->nrssi[1] - 5;
2913
2914 threshold = limit_value(threshold, 0, 0x3E);
2915 bcm43xx_phy_read(dev, 0x0020); /* dummy read */
2916 bcm43xx_phy_write(dev, 0x0020, (((u16)threshold) << 8) | 0x001C);
2917
2918 if (phy->radio_rev >= 6) {
2919 bcm43xx_phy_write(dev, 0x0087, 0x0E0D);
2920 bcm43xx_phy_write(dev, 0x0086, 0x0C0B);
2921 bcm43xx_phy_write(dev, 0x0085, 0x0A09);
2922 bcm43xx_phy_write(dev, 0x0084, 0x0808);
2923 bcm43xx_phy_write(dev, 0x0083, 0x0808);
2924 bcm43xx_phy_write(dev, 0x0082, 0x0604);
2925 bcm43xx_phy_write(dev, 0x0081, 0x0302);
2926 bcm43xx_phy_write(dev, 0x0080, 0x0100);
2927 }
2928 break;
2929 }
2930 case BCM43xx_PHYTYPE_G:
2931 if (!phy->gmode ||
2932 !(dev->dev->bus->sprom.r1.boardflags_lo & BCM43xx_BFL_RSSI)) {
2933 tmp16 = bcm43xx_nrssi_hw_read(dev, 0x20);
2934 if (tmp16 >= 0x20)
2935 tmp16 -= 0x40;
2936 if (tmp16 < 3) {
2937 bcm43xx_phy_write(dev, 0x048A,
2938 (bcm43xx_phy_read(dev, 0x048A)
2939 & 0xF000) | 0x09EB);
2940 } else {
2941 bcm43xx_phy_write(dev, 0x048A,
2942 (bcm43xx_phy_read(dev, 0x048A)
2943 & 0xF000) | 0x0AED);
2944 }
2945 } else {
2946 if (phy->interfmode == BCM43xx_INTERFMODE_NONWLAN) {
2947 a = 0xE;
2948 b = 0xA;
2949 } else if (!phy->aci_wlan_automatic && phy->aci_enable) {
2950 a = 0x13;
2951 b = 0x12;
2952 } else {
2953 a = 0xE;
2954 b = 0x11;
2955 }
2956
2957 a = a * (phy->nrssi[1] - phy->nrssi[0]);
2958 a += (phy->nrssi[0] << 6);
2959 if (a < 32)
2960 a += 31;
2961 else
2962 a += 32;
2963 a = a >> 6;
2964 a = limit_value(a, -31, 31);
2965
2966 b = b * (phy->nrssi[1] - phy->nrssi[0]);
2967 b += (phy->nrssi[0] << 6);
2968 if (b < 32)
2969 b += 31;
2970 else
2971 b += 32;
2972 b = b >> 6;
2973 b = limit_value(b, -31, 31);
2974
2975 tmp_u16 = bcm43xx_phy_read(dev, 0x048A) & 0xF000;
2976 tmp_u16 |= ((u32)b & 0x0000003F);
2977 tmp_u16 |= (((u32)a & 0x0000003F) << 6);
2978 bcm43xx_phy_write(dev, 0x048A, tmp_u16);
2979 }
2980 break;
2981 default:
2982 assert(0);
2983 }
2984 }
2985
2986 /* Stack implementation to save/restore values from the
2987 * interference mitigation code.
2988 * It is save to restore values in random order.
2989 */
2990 static void _stack_save(u32 *_stackptr, size_t *stackidx,
2991 u8 id, u16 offset, u16 value)
2992 {
2993 u32 *stackptr = &(_stackptr[*stackidx]);
2994
2995 assert((offset & 0xF000) == 0x0000);
2996 assert((id & 0xF0) == 0x00);
2997 *stackptr = offset;
2998 *stackptr |= ((u32)id) << 12;
2999 *stackptr |= ((u32)value) << 16;
3000 (*stackidx)++;
3001 assert(*stackidx < BCM43xx_INTERFSTACK_SIZE);
3002 }
3003
3004 static u16 _stack_restore(u32 *stackptr,
3005 u8 id, u16 offset)
3006 {
3007 size_t i;
3008
3009 assert((offset & 0xF000) == 0x0000);
3010 assert((id & 0xF0) == 0x00);
3011 for (i = 0; i < BCM43xx_INTERFSTACK_SIZE; i++, stackptr++) {
3012 if ((*stackptr & 0x00000FFF) != offset)
3013 continue;
3014 if (((*stackptr & 0x0000F000) >> 12) != id)
3015 continue;
3016 return ((*stackptr & 0xFFFF0000) >> 16);
3017 }
3018 assert(0);
3019
3020 return 0;
3021 }
3022
3023 #define phy_stacksave(offset) \
3024 do { \
3025 _stack_save(stack, &stackidx, 0x1, (offset), \
3026 bcm43xx_phy_read(dev, (offset))); \
3027 } while (0)
3028 #define phy_stackrestore(offset) \
3029 do { \
3030 bcm43xx_phy_write(dev, (offset), \
3031 _stack_restore(stack, 0x1, \
3032 (offset))); \
3033 } while (0)
3034 #define radio_stacksave(offset) \
3035 do { \
3036 _stack_save(stack, &stackidx, 0x2, (offset), \
3037 bcm43xx_radio_read16(dev, (offset))); \
3038 } while (0)
3039 #define radio_stackrestore(offset) \
3040 do { \
3041 bcm43xx_radio_write16(dev, (offset), \
3042 _stack_restore(stack, 0x2, \
3043 (offset))); \
3044 } while (0)
3045 #define ofdmtab_stacksave(table, offset) \
3046 do { \
3047 _stack_save(stack, &stackidx, 0x3, (offset)|(table), \
3048 bcm43xx_ofdmtab_read16(dev, (table), (offset))); \
3049 } while (0)
3050 #define ofdmtab_stackrestore(table, offset) \
3051 do { \
3052 bcm43xx_ofdmtab_write16(dev, (table), (offset), \
3053 _stack_restore(stack, 0x3, \
3054 (offset)|(table))); \
3055 } while (0)
3056
3057 static void
3058 bcm43xx_radio_interference_mitigation_enable(struct bcm43xx_wldev *dev,
3059 int mode)
3060 {
3061 struct bcm43xx_phy *phy = &dev->phy;
3062 u16 tmp, flipped;
3063 size_t stackidx = 0;
3064 u32 *stack = phy->interfstack;
3065
3066 switch (mode) {
3067 case BCM43xx_INTERFMODE_NONWLAN:
3068 if (phy->rev != 1) {
3069 bcm43xx_phy_write(dev, 0x042B,
3070 bcm43xx_phy_read(dev, 0x042B) | 0x0800);
3071 bcm43xx_phy_write(dev, BCM43xx_PHY_G_CRS,
3072 bcm43xx_phy_read(dev, BCM43xx_PHY_G_CRS) & ~0x4000);
3073 break;
3074 }
3075 radio_stacksave(0x0078);
3076 tmp = (bcm43xx_radio_read16(dev, 0x0078) & 0x001E);
3077 flipped = flip_4bit(tmp);
3078 if (flipped < 10 && flipped >= 8)
3079 flipped = 7;
3080 else if (flipped >= 10)
3081 flipped -= 3;
3082 flipped = flip_4bit(flipped);
3083 flipped = (flipped << 1) | 0x0020;
3084 bcm43xx_radio_write16(dev, 0x0078, flipped);
3085
3086 bcm43xx_calc_nrssi_threshold(dev);
3087
3088 phy_stacksave(0x0406);
3089 bcm43xx_phy_write(dev, 0x0406, 0x7E28);
3090
3091 bcm43xx_phy_write(dev, 0x042B,
3092 bcm43xx_phy_read(dev, 0x042B) | 0x0800);
3093 bcm43xx_phy_write(dev, BCM43xx_PHY_RADIO_BITFIELD,
3094 bcm43xx_phy_read(dev, BCM43xx_PHY_RADIO_BITFIELD) | 0x1000);
3095
3096 phy_stacksave(0x04A0);
3097 bcm43xx_phy_write(dev, 0x04A0,
3098 (bcm43xx_phy_read(dev, 0x04A0) & 0xC0C0) | 0x0008);
3099 phy_stacksave(0x04A1);
3100 bcm43xx_phy_write(dev, 0x04A1,
3101 (bcm43xx_phy_read(dev, 0x04A1) & 0xC0C0) | 0x0605);
3102 phy_stacksave(0x04A2);
3103 bcm43xx_phy_write(dev, 0x04A2,
3104 (bcm43xx_phy_read(dev, 0x04A2) & 0xC0C0) | 0x0204);
3105 phy_stacksave(0x04A8);
3106 bcm43xx_phy_write(dev, 0x04A8,
3107 (bcm43xx_phy_read(dev, 0x04A8) & 0xC0C0) | 0x0803);
3108 phy_stacksave(0x04AB);
3109 bcm43xx_phy_write(dev, 0x04AB,
3110 (bcm43xx_phy_read(dev, 0x04AB) & 0xC0C0) | 0x0605);
3111
3112 phy_stacksave(0x04A7);
3113 bcm43xx_phy_write(dev, 0x04A7, 0x0002);
3114 phy_stacksave(0x04A3);
3115 bcm43xx_phy_write(dev, 0x04A3, 0x287A);
3116 phy_stacksave(0x04A9);
3117 bcm43xx_phy_write(dev, 0x04A9, 0x2027);
3118 phy_stacksave(0x0493);
3119 bcm43xx_phy_write(dev, 0x0493, 0x32F5);
3120 phy_stacksave(0x04AA);
3121 bcm43xx_phy_write(dev, 0x04AA, 0x2027);
3122 phy_stacksave(0x04AC);
3123 bcm43xx_phy_write(dev, 0x04AC, 0x32F5);
3124 break;
3125 case BCM43xx_INTERFMODE_MANUALWLAN:
3126 if (bcm43xx_phy_read(dev, 0x0033) & 0x0800)
3127 break;
3128
3129 phy->aci_enable = 1;
3130
3131 phy_stacksave(BCM43xx_PHY_RADIO_BITFIELD);
3132 phy_stacksave(BCM43xx_PHY_G_CRS);
3133 if (phy->rev < 2) {
3134 phy_stacksave(0x0406);
3135 } else {
3136 phy_stacksave(0x04C0);
3137 phy_stacksave(0x04C1);
3138 }
3139 phy_stacksave(0x0033);
3140 phy_stacksave(0x04A7);
3141 phy_stacksave(0x04A3);
3142 phy_stacksave(0x04A9);
3143 phy_stacksave(0x04AA);
3144 phy_stacksave(0x04AC);
3145 phy_stacksave(0x0493);
3146 phy_stacksave(0x04A1);
3147 phy_stacksave(0x04A0);
3148 phy_stacksave(0x04A2);
3149 phy_stacksave(0x048A);
3150 phy_stacksave(0x04A8);
3151 phy_stacksave(0x04AB);
3152 if (phy->rev == 2) {
3153 phy_stacksave(0x04AD);
3154 phy_stacksave(0x04AE);
3155 } else if (phy->rev >= 3) {
3156 phy_stacksave(0x04AD);
3157 phy_stacksave(0x0415);
3158 phy_stacksave(0x0416);
3159 phy_stacksave(0x0417);
3160 ofdmtab_stacksave(0x1A00, 0x2);
3161 ofdmtab_stacksave(0x1A00, 0x3);
3162 }
3163 phy_stacksave(0x042B);
3164 phy_stacksave(0x048C);
3165
3166 bcm43xx_phy_write(dev, BCM43xx_PHY_RADIO_BITFIELD,
3167 bcm43xx_phy_read(dev, BCM43xx_PHY_RADIO_BITFIELD)
3168 & ~0x1000);
3169 bcm43xx_phy_write(dev, BCM43xx_PHY_G_CRS,
3170 (bcm43xx_phy_read(dev, BCM43xx_PHY_G_CRS)
3171 & 0xFFFC) | 0x0002);
3172
3173 bcm43xx_phy_write(dev, 0x0033, 0x0800);
3174 bcm43xx_phy_write(dev, 0x04A3, 0x2027);
3175 bcm43xx_phy_write(dev, 0x04A9, 0x1CA8);
3176 bcm43xx_phy_write(dev, 0x0493, 0x287A);
3177 bcm43xx_phy_write(dev, 0x04AA, 0x1CA8);
3178 bcm43xx_phy_write(dev, 0x04AC, 0x287A);
3179
3180 bcm43xx_phy_write(dev, 0x04A0,
3181 (bcm43xx_phy_read(dev, 0x04A0)
3182 & 0xFFC0) | 0x001A);
3183 bcm43xx_phy_write(dev, 0x04A7, 0x000D);
3184
3185 if (phy->rev < 2) {
3186 bcm43xx_phy_write(dev, 0x0406, 0xFF0D);
3187 } else if (phy->rev == 2) {
3188 bcm43xx_phy_write(dev, 0x04C0, 0xFFFF);
3189 bcm43xx_phy_write(dev, 0x04C1, 0x00A9);
3190 } else {
3191 bcm43xx_phy_write(dev, 0x04C0, 0x00C1);
3192 bcm43xx_phy_write(dev, 0x04C1, 0x0059);
3193 }
3194
3195 bcm43xx_phy_write(dev, 0x04A1,
3196 (bcm43xx_phy_read(dev, 0x04A1)
3197 & 0xC0FF) | 0x1800);
3198 bcm43xx_phy_write(dev, 0x04A1,
3199 (bcm43xx_phy_read(dev, 0x04A1)
3200 & 0xFFC0) | 0x0015);
3201 bcm43xx_phy_write(dev, 0x04A8,
3202 (bcm43xx_phy_read(dev, 0x04A8)
3203 & 0xCFFF) | 0x1000);
3204 bcm43xx_phy_write(dev, 0x04A8,
3205 (bcm43xx_phy_read(dev, 0x04A8)
3206 & 0xF0FF) | 0x0A00);
3207 bcm43xx_phy_write(dev, 0x04AB,
3208 (bcm43xx_phy_read(dev, 0x04AB)
3209 & 0xCFFF) | 0x1000);
3210 bcm43xx_phy_write(dev, 0x04AB,
3211 (bcm43xx_phy_read(dev, 0x04AB)
3212 & 0xF0FF) | 0x0800);
3213 bcm43xx_phy_write(dev, 0x04AB,
3214 (bcm43xx_phy_read(dev, 0x04AB)
3215 & 0xFFCF) | 0x0010);
3216 bcm43xx_phy_write(dev, 0x04AB,
3217 (bcm43xx_phy_read(dev, 0x04AB)
3218 & 0xFFF0) | 0x0005);
3219 bcm43xx_phy_write(dev, 0x04A8,
3220 (bcm43xx_phy_read(dev, 0x04A8)
3221 & 0xFFCF) | 0x0010);
3222 bcm43xx_phy_write(dev, 0x04A8,
3223 (bcm43xx_phy_read(dev, 0x04A8)
3224 & 0xFFF0) | 0x0006);
3225 bcm43xx_phy_write(dev, 0x04A2,
3226 (bcm43xx_phy_read(dev, 0x04A2)
3227 & 0xF0FF) | 0x0800);
3228 bcm43xx_phy_write(dev, 0x04A0,
3229 (bcm43xx_phy_read(dev, 0x04A0)
3230 & 0xF0FF) | 0x0500);
3231 bcm43xx_phy_write(dev, 0x04A2,
3232 (bcm43xx_phy_read(dev, 0x04A2)
3233 & 0xFFF0) | 0x000B);
3234
3235 if (phy->rev >= 3) {
3236 bcm43xx_phy_write(dev, 0x048A,
3237 bcm43xx_phy_read(dev, 0x048A)
3238 & ~0x8000);
3239 bcm43xx_phy_write(dev, 0x0415,
3240 (bcm43xx_phy_read(dev, 0x0415)
3241 & 0x8000) | 0x36D8);
3242 bcm43xx_phy_write(dev, 0x0416,
3243 (bcm43xx_phy_read(dev, 0x0416)
3244 & 0x8000) | 0x36D8);
3245 bcm43xx_phy_write(dev, 0x0417,
3246 (bcm43xx_phy_read(dev, 0x0417)
3247 & 0xFE00) | 0x016D);
3248 } else {
3249 bcm43xx_phy_write(dev, 0x048A,
3250 bcm43xx_phy_read(dev, 0x048A)
3251 | 0x1000);
3252 bcm43xx_phy_write(dev, 0x048A,
3253 (bcm43xx_phy_read(dev, 0x048A)
3254 & 0x9FFF) | 0x2000);
3255 bcm43xx_hf_write(dev, bcm43xx_hf_read(dev) | BCM43xx_HF_ACIW);
3256 }
3257 if (phy->rev >= 2) {
3258 bcm43xx_phy_write(dev, 0x042B,
3259 bcm43xx_phy_read(dev, 0x042B)
3260 | 0x0800);
3261 }
3262 bcm43xx_phy_write(dev, 0x048C,
3263 (bcm43xx_phy_read(dev, 0x048C)
3264 & 0xF0FF) | 0x0200);
3265 if (phy->rev == 2) {
3266 bcm43xx_phy_write(dev, 0x04AE,
3267 (bcm43xx_phy_read(dev, 0x04AE)
3268 & 0xFF00) | 0x007F);
3269 bcm43xx_phy_write(dev, 0x04AD,
3270 (bcm43xx_phy_read(dev, 0x04AD)
3271 & 0x00FF) | 0x1300);
3272 } else if (phy->rev >= 6) {
3273 bcm43xx_ofdmtab_write16(dev, 0x1A00, 0x3, 0x007F);
3274 bcm43xx_ofdmtab_write16(dev, 0x1A00, 0x2, 0x007F);
3275 bcm43xx_phy_write(dev, 0x04AD,
3276 bcm43xx_phy_read(dev, 0x04AD)
3277 & 0x00FF);
3278 }
3279 bcm43xx_calc_nrssi_slope(dev);
3280 break;
3281 default:
3282 assert(0);
3283 }
3284 }
3285
3286 static void
3287 bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_wldev *dev,
3288 int mode)
3289 {
3290 struct bcm43xx_phy *phy = &dev->phy;
3291 u32 *stack = phy->interfstack;
3292
3293 switch (mode) {
3294 case BCM43xx_INTERFMODE_NONWLAN:
3295 if (phy->rev != 1) {
3296 bcm43xx_phy_write(dev, 0x042B,
3297 bcm43xx_phy_read(dev, 0x042B) & ~0x0800);
3298 bcm43xx_phy_write(dev, BCM43xx_PHY_G_CRS,
3299 bcm43xx_phy_read(dev, BCM43xx_PHY_G_CRS) | 0x4000);
3300 break;
3301 }
3302 radio_stackrestore(0x0078);
3303 bcm43xx_calc_nrssi_threshold(dev);
3304 phy_stackrestore(0x0406);
3305 bcm43xx_phy_write(dev, 0x042B,
3306 bcm43xx_phy_read(dev, 0x042B) & ~0x0800);
3307 if (!dev->bad_frames_preempt) {
3308 bcm43xx_phy_write(dev, BCM43xx_PHY_RADIO_BITFIELD,
3309 bcm43xx_phy_read(dev, BCM43xx_PHY_RADIO_BITFIELD)
3310 & ~(1 << 11));
3311 }
3312 bcm43xx_phy_write(dev, BCM43xx_PHY_G_CRS,
3313 bcm43xx_phy_read(dev, BCM43xx_PHY_G_CRS) | 0x4000);
3314 phy_stackrestore(0x04A0);
3315 phy_stackrestore(0x04A1);
3316 phy_stackrestore(0x04A2);
3317 phy_stackrestore(0x04A8);
3318 phy_stackrestore(0x04AB);
3319 phy_stackrestore(0x04A7);
3320 phy_stackrestore(0x04A3);
3321 phy_stackrestore(0x04A9);
3322 phy_stackrestore(0x0493);
3323 phy_stackrestore(0x04AA);
3324 phy_stackrestore(0x04AC);
3325 break;
3326 case BCM43xx_INTERFMODE_MANUALWLAN:
3327 if (!(bcm43xx_phy_read(dev, 0x0033) & 0x0800))
3328 break;
3329
3330 phy->aci_enable = 0;
3331
3332 phy_stackrestore(BCM43xx_PHY_RADIO_BITFIELD);
3333 phy_stackrestore(BCM43xx_PHY_G_CRS);
3334 phy_stackrestore(0x0033);
3335 phy_stackrestore(0x04A3);
3336 phy_stackrestore(0x04A9);
3337 phy_stackrestore(0x0493);
3338 phy_stackrestore(0x04AA);
3339 phy_stackrestore(0x04AC);
3340 phy_stackrestore(0x04A0);
3341 phy_stackrestore(0x04A7);
3342 if (phy->rev >= 2) {
3343 phy_stackrestore(0x04C0);
3344 phy_stackrestore(0x04C1);
3345 } else
3346 phy_stackrestore(0x0406);
3347 phy_stackrestore(0x04A1);
3348 phy_stackrestore(0x04AB);
3349 phy_stackrestore(0x04A8);
3350 if (phy->rev == 2) {
3351 phy_stackrestore(0x04AD);
3352 phy_stackrestore(0x04AE);
3353 } else if (phy->rev >= 3) {
3354 phy_stackrestore(0x04AD);
3355 phy_stackrestore(0x0415);
3356 phy_stackrestore(0x0416);
3357 phy_stackrestore(0x0417);
3358 ofdmtab_stackrestore(0x1A00, 0x2);
3359 ofdmtab_stackrestore(0x1A00, 0x3);
3360 }
3361 phy_stackrestore(0x04A2);
3362 phy_stackrestore(0x048A);
3363 phy_stackrestore(0x042B);
3364 phy_stackrestore(0x048C);
3365 bcm43xx_hf_write(dev, bcm43xx_hf_read(dev) & ~BCM43xx_HF_ACIW);
3366 bcm43xx_calc_nrssi_slope(dev);
3367 break;
3368 default:
3369 assert(0);
3370 }
3371 }
3372
3373 #undef phy_stacksave
3374 #undef phy_stackrestore
3375 #undef radio_stacksave
3376 #undef radio_stackrestore
3377 #undef ofdmtab_stacksave
3378 #undef ofdmtab_stackrestore
3379
3380 int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_wldev *dev,
3381 int mode)
3382 {
3383 struct bcm43xx_phy *phy = &dev->phy;
3384 int currentmode;
3385
3386 if ((phy->type != BCM43xx_PHYTYPE_G) ||
3387 (phy->rev == 0) ||
3388 (!phy->gmode))
3389 return -ENODEV;
3390
3391 phy->aci_wlan_automatic = 0;
3392 switch (mode) {
3393 case BCM43xx_INTERFMODE_AUTOWLAN:
3394 phy->aci_wlan_automatic = 1;
3395 if (phy->aci_enable)
3396 mode = BCM43xx_INTERFMODE_MANUALWLAN;
3397 else
3398 mode = BCM43xx_INTERFMODE_NONE;
3399 break;
3400 case BCM43xx_INTERFMODE_NONE:
3401 case BCM43xx_INTERFMODE_NONWLAN:
3402 case BCM43xx_INTERFMODE_MANUALWLAN:
3403 break;
3404 default:
3405 return -EINVAL;
3406 }
3407
3408 currentmode = phy->interfmode;
3409 if (currentmode == mode)
3410 return 0;
3411 if (currentmode != BCM43xx_INTERFMODE_NONE)
3412 bcm43xx_radio_interference_mitigation_disable(dev, currentmode);
3413
3414 if (mode == BCM43xx_INTERFMODE_NONE) {
3415 phy->aci_enable = 0;
3416 phy->aci_hw_rssi = 0;
3417 } else
3418 bcm43xx_radio_interference_mitigation_enable(dev, mode);
3419 phy->interfmode = mode;
3420
3421 return 0;
3422 }
3423
3424 static u16 bcm43xx_radio_core_calibration_value(struct bcm43xx_wldev *dev)
3425 {
3426 u16 reg, index, ret;
3427
3428 static const u8 rcc_table[] = {
3429 0x02, 0x03, 0x01, 0x0F,
3430 0x06, 0x07, 0x05, 0x0F,
3431 0x0A, 0x0B, 0x09, 0x0F,
3432 0x0E, 0x0F, 0x0D, 0x0F,
3433 };
3434
3435 reg = bcm43xx_radio_read16(dev, 0x60);
3436 index = (reg & 0x001E) >> 1;
3437 ret = rcc_table[index] << 1;
3438 ret |= (reg & 0x0001);
3439 ret |= 0x0020;
3440
3441 return ret;
3442 }
3443
3444 #define LPD(L, P, D) (((L) << 2) | ((P) << 1) | ((D) << 0))
3445 static u16 radio2050_rfover_val(struct bcm43xx_wldev *dev,
3446 u16 phy_register,
3447 unsigned int lpd)
3448 {
3449 struct bcm43xx_phy *phy = &dev->phy;
3450 struct ssb_sprom *sprom = &(dev->dev->bus->sprom);
3451
3452 if (!phy->gmode)
3453 return 0;
3454
3455 if (has_loopback_gain(phy)) {
3456 int max_lb_gain = phy->max_lb_gain;
3457 u16 extlna;
3458 u16 i;
3459
3460 if (phy->radio_rev == 8)
3461 max_lb_gain += 0x3E;
3462 else
3463 max_lb_gain += 0x26;
3464 if (max_lb_gain >= 0x46) {
3465 extlna = 0x3000;
3466 max_lb_gain -= 0x46;
3467 } else if (max_lb_gain >= 0x3A) {
3468 extlna = 0x1000;
3469 max_lb_gain -= 0x3A;
3470 } else if (max_lb_gain >= 0x2E) {
3471 extlna = 0x2000;
3472 max_lb_gain -= 0x2E;
3473 } else {
3474 extlna = 0;
3475 max_lb_gain -= 0x10;
3476 }
3477
3478 for (i = 0; i < 16; i++) {
3479 max_lb_gain -= (i * 6);
3480 if (max_lb_gain < 6)
3481 break;
3482 }
3483
3484 if ((phy->rev < 7) ||
3485 !(sprom->r1.boardflags_lo & BCM43xx_BFL_EXTLNA)) {
3486 if (phy_register == BCM43xx_PHY_RFOVER) {
3487 return 0x1B3;
3488 } else if (phy_register == BCM43xx_PHY_RFOVERVAL) {
3489 extlna |= (i << 8);
3490 switch (lpd) {
3491 case LPD(0, 1, 1):
3492 return 0x0F92;
3493 case LPD(0, 0, 1):
3494 case LPD(1, 0, 1):
3495 return (0x0092 | extlna);
3496 case LPD(1, 0, 0):
3497 return (0x0093 | extlna);
3498 }
3499 assert(0);
3500 }
3501 assert(0);
3502 } else {
3503 if (phy_register == BCM43xx_PHY_RFOVER) {
3504 return 0x9B3;
3505 } else if (phy_register == BCM43xx_PHY_RFOVERVAL) {
3506 if (extlna)
3507 extlna |= 0x8000;
3508 extlna |= (i << 8);
3509 switch (lpd) {
3510 case LPD(0, 1, 1):
3511 return 0x8F92;
3512 case LPD(0, 0, 1):
3513 return (0x8092 | extlna);
3514 case LPD(1, 0, 1):
3515 return (0x2092 | extlna);
3516 case LPD(1, 0, 0):
3517 return (0x2093 | extlna);
3518 }
3519 assert(0);
3520 }
3521 assert(0);
3522 }
3523 } else {
3524 if ((phy->rev < 7) ||
3525 !(sprom->r1.boardflags_lo & BCM43xx_BFL_EXTLNA)) {
3526 if (phy_register == BCM43xx_PHY_RFOVER) {
3527 return 0x1B3;
3528 } else if (phy_register == BCM43xx_PHY_RFOVERVAL) {
3529 switch (lpd) {
3530 case LPD(0, 1, 1):
3531 return 0x0FB2;
3532 case LPD(0, 0, 1):
3533 return 0x00B2;
3534 case LPD(1, 0, 1):
3535 return 0x30B2;
3536 case LPD(1, 0, 0):
3537 return 0x30B3;
3538 }
3539 assert(0);
3540 }
3541 assert(0);
3542 } else {
3543 if (phy_register == BCM43xx_PHY_RFOVER) {
3544 return 0x9B3;
3545 } else if (phy_register == BCM43xx_PHY_RFOVERVAL) {
3546 switch (lpd) {
3547 case LPD(0, 1, 1):
3548 return 0x8FB2;
3549 case LPD(0, 0, 1):
3550 return 0x80B2;
3551 case LPD(1, 0, 1):
3552 return 0x20B2;
3553 case LPD(1, 0, 0):
3554 return 0x20B3;
3555 }
3556 assert(0);
3557 }
3558 assert(0);
3559 }
3560 }
3561 return 0;
3562 }
3563
3564 struct init2050_saved_values {
3565 /* Core registers */
3566 u16 reg_3EC;
3567 u16 reg_3E6;
3568 u16 reg_3F4;
3569 /* Radio registers */
3570 u16 radio_43;
3571 u16 radio_51;
3572 u16 radio_52;
3573 /* PHY registers */
3574 u16 phy_pgactl;
3575 u16 phy_base_5A;
3576 u16 phy_base_59;
3577 u16 phy_base_58;
3578 u16 phy_base_30;
3579 u16 phy_rfover;
3580 u16 phy_rfoverval;
3581 u16 phy_analogover;
3582 u16 phy_analogoverval;
3583 u16 phy_crs0;
3584 u16 phy_classctl;
3585 u16 phy_lo_mask;
3586 u16 phy_lo_ctl;
3587 u16 phy_syncctl;
3588 };
3589
3590 u16 bcm43xx_radio_init2050(struct bcm43xx_wldev *dev)
3591 {
3592 struct bcm43xx_phy *phy = &dev->phy;
3593 struct init2050_saved_values sav;
3594 u16 rcc;
3595 u16 radio78;
3596 u16 ret;
3597 u16 i, j;
3598 u32 tmp1 = 0, tmp2 = 0;
3599
3600 memset(&sav, 0, sizeof(sav)); /* get rid of "may be used uninitialized..." */
3601
3602 sav.radio_43 = bcm43xx_radio_read16(dev, 0x43);
3603 sav.radio_51 = bcm43xx_radio_read16(dev, 0x51);
3604 sav.radio_52 = bcm43xx_radio_read16(dev, 0x52);
3605 sav.phy_pgactl = bcm43xx_phy_read(dev, BCM43xx_PHY_PGACTL);
3606 sav.phy_base_5A = bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x5A));
3607 sav.phy_base_59 = bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x59));
3608 sav.phy_base_58 = bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x58));
3609
3610 if (phy->type == BCM43xx_PHYTYPE_B) {
3611 sav.phy_base_30 = bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x30));
3612 sav.reg_3EC = bcm43xx_read16(dev, 0x3EC);
3613
3614 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x30), 0xFF);
3615 bcm43xx_write16(dev, 0x3EC, 0x3F3F);
3616 } else if (phy->gmode || phy->rev >= 2) {
3617 sav.phy_rfover = bcm43xx_phy_read(dev, BCM43xx_PHY_RFOVER);
3618 sav.phy_rfoverval = bcm43xx_phy_read(dev, BCM43xx_PHY_RFOVERVAL);
3619 sav.phy_analogover = bcm43xx_phy_read(dev, BCM43xx_PHY_ANALOGOVER);
3620 sav.phy_analogoverval = bcm43xx_phy_read(dev, BCM43xx_PHY_ANALOGOVERVAL);
3621 sav.phy_crs0 = bcm43xx_phy_read(dev, BCM43xx_PHY_CRS0);
3622 sav.phy_classctl = bcm43xx_phy_read(dev, BCM43xx_PHY_CLASSCTL);
3623
3624 bcm43xx_phy_write(dev, BCM43xx_PHY_ANALOGOVER,
3625 bcm43xx_phy_read(dev, BCM43xx_PHY_ANALOGOVER)
3626 | 0x0003);
3627 bcm43xx_phy_write(dev, BCM43xx_PHY_ANALOGOVERVAL,
3628 bcm43xx_phy_read(dev, BCM43xx_PHY_ANALOGOVERVAL)
3629 & 0xFFFC);
3630 bcm43xx_phy_write(dev, BCM43xx_PHY_CRS0,
3631 bcm43xx_phy_read(dev, BCM43xx_PHY_CRS0)
3632 & 0x7FFF);
3633 bcm43xx_phy_write(dev, BCM43xx_PHY_CLASSCTL,
3634 bcm43xx_phy_read(dev, BCM43xx_PHY_CLASSCTL)
3635 & 0xFFFC);
3636 if (has_loopback_gain(phy)) {
3637 sav.phy_lo_mask = bcm43xx_phy_read(dev, BCM43xx_PHY_LO_MASK);
3638 sav.phy_lo_ctl = bcm43xx_phy_read(dev, BCM43xx_PHY_LO_CTL);
3639
3640 if (phy->rev >= 3)
3641 bcm43xx_phy_write(dev, BCM43xx_PHY_LO_MASK, 0xC020);
3642 else
3643 bcm43xx_phy_write(dev, BCM43xx_PHY_LO_MASK, 0x8020);
3644 bcm43xx_phy_write(dev, BCM43xx_PHY_LO_CTL, 0);
3645 }
3646
3647 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL,
3648 radio2050_rfover_val(dev, BCM43xx_PHY_RFOVERVAL,
3649 LPD(0, 1, 1)));
3650 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVER,
3651 radio2050_rfover_val(dev, BCM43xx_PHY_RFOVER, 0));
3652 }
3653 bcm43xx_write16(dev, 0x3E2, bcm43xx_read16(dev, 0x3E2) | 0x8000);
3654
3655 sav.phy_syncctl = bcm43xx_phy_read(dev, BCM43xx_PHY_SYNCCTL);
3656 bcm43xx_phy_write(dev, BCM43xx_PHY_SYNCCTL,
3657 bcm43xx_phy_read(dev, BCM43xx_PHY_SYNCCTL)
3658 & 0xFF7F);
3659 sav.reg_3E6 = bcm43xx_read16(dev, 0x3E6);
3660 sav.reg_3F4 = bcm43xx_read16(dev, 0x3F4);
3661
3662 if (phy->analog == 0) {
3663 bcm43xx_write16(dev, 0x03E6, 0x0122);
3664 } else {
3665 if (phy->analog >= 2) {
3666 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x03),
3667 (bcm43xx_phy_read(dev, BCM43xx_PHY_BASE(0x03))
3668 & 0xFFBF) | 0x40);
3669 }
3670 bcm43xx_write16(dev, BCM43xx_MMIO_CHANNEL_EXT,
3671 (bcm43xx_read16(dev, BCM43xx_MMIO_CHANNEL_EXT) | 0x2000));
3672 }
3673
3674 rcc = bcm43xx_radio_core_calibration_value(dev);
3675
3676 if (phy->type == BCM43xx_PHYTYPE_B)
3677 bcm43xx_radio_write16(dev, 0x78, 0x26);
3678 if (phy->gmode || phy->rev >= 2) {
3679 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL,
3680 radio2050_rfover_val(dev, BCM43xx_PHY_RFOVERVAL,
3681 LPD(0, 1, 1)));
3682 }
3683 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL, 0xBFAF);
3684 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x2B), 0x1403);
3685 if (phy->gmode || phy->rev >= 2) {
3686 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL,
3687 radio2050_rfover_val(dev, BCM43xx_PHY_RFOVERVAL,
3688 LPD(0, 0, 1)));
3689 }
3690 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL, 0xBFA0);
3691 bcm43xx_radio_write16(dev, 0x51,
3692 bcm43xx_radio_read16(dev, 0x51)
3693 | 0x0004);
3694 if (phy->radio_rev == 8) {
3695 bcm43xx_radio_write16(dev, 0x43, 0x1F);
3696 } else {
3697 bcm43xx_radio_write16(dev, 0x52, 0);
3698 bcm43xx_radio_write16(dev, 0x43,
3699 (bcm43xx_radio_read16(dev, 0x43)
3700 & 0xFFF0) | 0x0009);
3701 }
3702 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x58), 0);
3703
3704 for (i = 0; i < 16; i++) {
3705 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x5A), 0x0480);
3706 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x59), 0xC810);
3707 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x58), 0x000D);
3708 if (phy->gmode || phy->rev >= 2) {
3709 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL,
3710 radio2050_rfover_val(dev, BCM43xx_PHY_RFOVERVAL,
3711 LPD(1, 0, 1)));
3712 }
3713 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL, 0xAFB0);
3714 udelay(10);
3715 if (phy->gmode || phy->rev >= 2) {
3716 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL,
3717 radio2050_rfover_val(dev, BCM43xx_PHY_RFOVERVAL,
3718 LPD(1, 0, 1)));
3719 }
3720 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL, 0xEFB0);
3721 udelay(10);
3722 if (phy->gmode || phy->rev >= 2) {
3723 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL,
3724 radio2050_rfover_val(dev, BCM43xx_PHY_RFOVERVAL,
3725 LPD(1, 0, 0)));
3726 }
3727 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL, 0xFFF0);
3728 udelay(20);
3729 tmp1 += bcm43xx_phy_read(dev, BCM43xx_PHY_LO_LEAKAGE);
3730 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x58), 0);
3731 if (phy->gmode || phy->rev >= 2) {
3732 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL,
3733 radio2050_rfover_val(dev, BCM43xx_PHY_RFOVERVAL,
3734 LPD(1, 0, 1)));
3735 }
3736 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL, 0xAFB0);
3737 }
3738 udelay(10);
3739
3740 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x58), 0);
3741 tmp1++;
3742 tmp1 >>= 9;
3743
3744 for (i = 0; i < 16; i++) {
3745 radio78 = ((flip_4bit(i) << 1) | 0x20);
3746 bcm43xx_radio_write16(dev, 0x78, radio78);
3747 udelay(10);
3748 for (j = 0; j < 16; j++) {
3749 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x5A), 0x0D80);
3750 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x59), 0xC810);
3751 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x58), 0x000D);
3752 if (phy->gmode || phy->rev >= 2) {
3753 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL,
3754 radio2050_rfover_val(dev, BCM43xx_PHY_RFOVERVAL,
3755 LPD(1, 0, 1)));
3756 }
3757 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL, 0xAFB0);
3758 udelay(10);
3759 if (phy->gmode || phy->rev >= 2) {
3760 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL,
3761 radio2050_rfover_val(dev, BCM43xx_PHY_RFOVERVAL,
3762 LPD(1, 0, 1)));
3763 }
3764 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL, 0xEFB0);
3765 udelay(10);
3766 if (phy->gmode || phy->rev >= 2) {
3767 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL,
3768 radio2050_rfover_val(dev, BCM43xx_PHY_RFOVERVAL,
3769 LPD(1, 0, 0)));
3770 }
3771 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL, 0xFFF0);
3772 udelay(10);
3773 tmp2 += bcm43xx_phy_read(dev, BCM43xx_PHY_LO_LEAKAGE);
3774 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x58), 0);
3775 if (phy->gmode || phy->rev >= 2) {
3776 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL,
3777 radio2050_rfover_val(dev, BCM43xx_PHY_RFOVERVAL,
3778 LPD(1, 0, 1)));
3779 }
3780 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL, 0xAFB0);
3781 }
3782 tmp2++;
3783 tmp2 >>= 8;
3784 if (tmp1 < tmp2)
3785 break;
3786 }
3787
3788 /* Restore the registers */
3789 bcm43xx_phy_write(dev, BCM43xx_PHY_PGACTL, sav.phy_pgactl);
3790 bcm43xx_radio_write16(dev, 0x51, sav.radio_51);
3791 bcm43xx_radio_write16(dev, 0x52, sav.radio_52);
3792 bcm43xx_radio_write16(dev, 0x43, sav.radio_43);
3793 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x5A), sav.phy_base_5A);
3794 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x59), sav.phy_base_59);
3795 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x58), sav.phy_base_58);
3796 bcm43xx_write16(dev, 0x3E6, sav.reg_3E6);
3797 if (phy->analog != 0)
3798 bcm43xx_write16(dev, 0x3F4, sav.reg_3F4);
3799 bcm43xx_phy_write(dev, BCM43xx_PHY_SYNCCTL, sav.phy_syncctl);
3800 bcm43xx_synth_pu_workaround(dev, phy->channel);
3801 if (phy->type == BCM43xx_PHYTYPE_B) {
3802 bcm43xx_phy_write(dev, BCM43xx_PHY_BASE(0x30), sav.phy_base_30);
3803 bcm43xx_write16(dev, 0x3EC, sav.reg_3EC);
3804 } else if (phy->gmode) {
3805 bcm43xx_write16(dev, BCM43xx_MMIO_PHY_RADIO,
3806 bcm43xx_read16(dev, BCM43xx_MMIO_PHY_RADIO)
3807 & 0x7FFF);
3808 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVER, sav.phy_rfover);
3809 bcm43xx_phy_write(dev, BCM43xx_PHY_RFOVERVAL, sav.phy_rfoverval);
3810 bcm43xx_phy_write(dev, BCM43xx_PHY_ANALOGOVER, sav.phy_analogover);
3811 bcm43xx_phy_write(dev, BCM43xx_PHY_ANALOGOVERVAL, sav.phy_analogoverval);
3812 bcm43xx_phy_write(dev, BCM43xx_PHY_CRS0, sav.phy_crs0);
3813 bcm43xx_phy_write(dev, BCM43xx_PHY_CLASSCTL, sav.phy_classctl);
3814 if (has_loopback_gain(phy)) {
3815 bcm43xx_phy_write(dev, BCM43xx_PHY_LO_MASK, sav.phy_lo_mask);
3816 bcm43xx_phy_write(dev, BCM43xx_PHY_LO_CTL, sav.phy_lo_ctl);
3817 }
3818 }
3819 if (i > 15)
3820 ret = radio78;
3821 else
3822 ret = rcc;
3823
3824 return ret;
3825 }
3826
3827 void bcm43xx_radio_init2060(struct bcm43xx_wldev *dev)
3828 {
3829 int err;
3830
3831 bcm43xx_radio_write16(dev, 0x0004, 0x00C0);
3832 bcm43xx_radio_write16(dev, 0x0005, 0x0008);
3833 bcm43xx_radio_write16(dev, 0x0009, 0x0040);
3834 bcm43xx_radio_write16(dev, 0x0005, 0x00AA);
3835 bcm43xx_radio_write16(dev, 0x0032, 0x008F);
3836 bcm43xx_radio_write16(dev, 0x0006, 0x008F);
3837 bcm43xx_radio_write16(dev, 0x0034, 0x008F);
3838 bcm43xx_radio_write16(dev, 0x002C, 0x0007);
3839 bcm43xx_radio_write16(dev, 0x0082, 0x0080);
3840 bcm43xx_radio_write16(dev, 0x0080, 0x0000);
3841 bcm43xx_radio_write16(dev, 0x003F, 0x00DA);
3842 bcm43xx_radio_write16(dev, 0x0005, bcm43xx_radio_read16(dev, 0x0005) & ~0x0008);
3843 bcm43xx_radio_write16(dev, 0x0081, bcm43xx_radio_read16(dev, 0x0081) & ~0x0010);
3844 bcm43xx_radio_write16(dev, 0x0081, bcm43xx_radio_read16(dev, 0x0081) & ~0x0020);
3845 bcm43xx_radio_write16(dev, 0x0081, bcm43xx_radio_read16(dev, 0x0081) & ~0x0020);
3846 udelay(400);
3847
3848 bcm43xx_radio_write16(dev, 0x0081, (bcm43xx_radio_read16(dev, 0x0081) & ~0x0020) | 0x0010);
3849 udelay(400);
3850
3851 bcm43xx_radio_write16(dev, 0x0005, (bcm43xx_radio_read16(dev, 0x0005) & ~0x0008) | 0x0008);
3852 bcm43xx_radio_write16(dev, 0x0085, bcm43xx_radio_read16(dev, 0x0085) & ~0x0010);
3853 bcm43xx_radio_write16(dev, 0x0005, bcm43xx_radio_read16(dev, 0x0005) & ~0x0008);
3854 bcm43xx_radio_write16(dev, 0x0081, bcm43xx_radio_read16(dev, 0x0081) & ~0x0040);
3855 bcm43xx_radio_write16(dev, 0x0081, (bcm43xx_radio_read16(dev, 0x0081) & ~0x0040) | 0x0040);
3856 bcm43xx_radio_write16(dev, 0x0005, (bcm43xx_radio_read16(dev, 0x0081) & ~0x0008) | 0x0008);
3857 bcm43xx_phy_write(dev, 0x0063, 0xDDC6);
3858 bcm43xx_phy_write(dev, 0x0069, 0x07BE);
3859 bcm43xx_phy_write(dev, 0x006A, 0x0000);
3860
3861 err = bcm43xx_radio_selectchannel(dev, BCM43xx_DEFAULT_CHANNEL_A, 0);
3862 assert(err == 0);
3863 udelay(1000);
3864 }
3865
3866 static inline
3867 u16 freq_r3A_value(u16 frequency)
3868 {
3869 u16 value;
3870
3871 if (frequency < 5091)
3872 value = 0x0040;
3873 else if (frequency < 5321)
3874 value = 0x0000;
3875 else if (frequency < 5806)
3876 value = 0x0080;
3877 else
3878 value = 0x0040;
3879
3880 return value;
3881 }
3882
3883 void bcm43xx_radio_set_tx_iq(struct bcm43xx_wldev *dev)
3884 {
3885 static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 };
3886 static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A };
3887 u16 tmp = bcm43xx_radio_read16(dev, 0x001E);
3888 int i, j;
3889
3890 for (i = 0; i < 5; i++) {
3891 for (j = 0; j < 5; j++) {
3892 if (tmp == (data_high[i] << 4 | data_low[j])) {
3893 bcm43xx_phy_write(dev, 0x0069, (i - j) << 8 | 0x00C0);
3894 return;
3895 }
3896 }
3897 }
3898 }
3899
3900 int bcm43xx_radio_selectchannel(struct bcm43xx_wldev *dev,
3901 u8 channel,
3902 int synthetic_pu_workaround)
3903 {
3904 struct bcm43xx_phy *phy = &dev->phy;
3905 u16 r8, tmp;
3906 u16 freq;
3907 u16 channelcookie;
3908
3909 /* First we set the channel radio code to prevent the
3910 * firmware from sending ghost packets.
3911 */
3912 channelcookie = channel;
3913 if (phy->type == BCM43xx_PHYTYPE_A)
3914 channelcookie |= 0x100;
3915 bcm43xx_shm_write16(dev, BCM43xx_SHM_SHARED,
3916 BCM43xx_SHM_SH_CHAN, channelcookie);
3917
3918 if (phy->type == BCM43xx_PHYTYPE_A) {
3919 if (channel > 200)
3920 return -EINVAL;
3921 freq = channel2freq_a(channel);
3922
3923 r8 = bcm43xx_radio_read16(dev, 0x0008);
3924 bcm43xx_write16(dev, 0x03F0, freq);
3925 bcm43xx_radio_write16(dev, 0x0008, r8);
3926
3927 TODO();//TODO: write max channel TX power? to Radio 0x2D
3928 tmp = bcm43xx_radio_read16(dev, 0x002E);
3929 tmp &= 0x0080;
3930 TODO();//TODO: OR tmp with the Power out estimation for this channel?
3931 bcm43xx_radio_write16(dev, 0x002E, tmp);
3932
3933 if (freq >= 4920 && freq <= 5500) {
3934 /*
3935 * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F;
3936 * = (freq * 0.025862069
3937 */
3938 r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */
3939 }
3940 bcm43xx_radio_write16(dev, 0x0007, (r8 << 4) | r8);
3941 bcm43xx_radio_write16(dev, 0x0020, (r8 << 4) | r8);
3942 bcm43xx_radio_write16(dev, 0x0021, (r8 << 4) | r8);
3943 bcm43xx_radio_write16(dev, 0x0022,
3944 (bcm43xx_radio_read16(dev, 0x0022)
3945 & 0x000F) | (r8 << 4));
3946 bcm43xx_radio_write16(dev, 0x002A, (r8 << 4));
3947 bcm43xx_radio_write16(dev, 0x002B, (r8 << 4));
3948 bcm43xx_radio_write16(dev, 0x0008,
3949 (bcm43xx_radio_read16(dev, 0x0008)
3950 & 0x00F0) | (r8 << 4));
3951 bcm43xx_radio_write16(dev, 0x0029,
3952 (bcm43xx_radio_read16(dev, 0x0029)
3953 & 0xFF0F) | 0x00B0);
3954 bcm43xx_radio_write16(dev, 0x0035, 0x00AA);
3955 bcm43xx_radio_write16(dev, 0x0036, 0x0085);
3956 bcm43xx_radio_write16(dev, 0x003A,
3957 (bcm43xx_radio_read16(dev, 0x003A)
3958 & 0xFF20) | freq_r3A_value(freq));
3959 bcm43xx_radio_write16(dev, 0x003D,
3960 bcm43xx_radio_read16(dev, 0x003D) & 0x00FF);
3961 bcm43xx_radio_write16(dev, 0x0081,
3962 (bcm43xx_radio_read16(dev, 0x0081)
3963 & 0xFF7F) | 0x0080);
3964 bcm43xx_radio_write16(dev, 0x0035,
3965 bcm43xx_radio_read16(dev, 0x0035) & 0xFFEF);
3966 bcm43xx_radio_write16(dev, 0x0035,
3967 (bcm43xx_radio_read16(dev, 0x0035)
3968 & 0xFFEF) | 0x0010);
3969 bcm43xx_radio_set_tx_iq(dev);
3970 TODO(); //TODO: TSSI2dbm workaround
3971 bcm43xx_phy_xmitpower(dev);//FIXME correct?
3972 } else {
3973 if ((channel < 1) || (channel > 14))
3974 return -EINVAL;
3975
3976 if (synthetic_pu_workaround)
3977 bcm43xx_synth_pu_workaround(dev, channel);
3978
3979 bcm43xx_write16(dev, BCM43xx_MMIO_CHANNEL,
3980 channel2freq_bg(channel));
3981
3982 if (channel == 14) {
3983 if (dev->dev->bus->sprom.r1.country_code == SSB_SPROM1CCODE_JAPAN)
3984 bcm43xx_hf_write(dev, bcm43xx_hf_read(dev) & ~BCM43xx_HF_ACPR);
3985 else
3986 bcm43xx_hf_write(dev, bcm43xx_hf_read(dev) | BCM43xx_HF_ACPR);
3987 bcm43xx_write16(dev, BCM43xx_MMIO_CHANNEL_EXT,
3988 bcm43xx_read16(dev, BCM43xx_MMIO_CHANNEL_EXT)
3989 | (1 << 11));
3990 } else {
3991 bcm43xx_write16(dev, BCM43xx_MMIO_CHANNEL_EXT,
3992 bcm43xx_read16(dev, BCM43xx_MMIO_CHANNEL_EXT)
3993 & 0xF7BF);
3994 }
3995 }
3996
3997 phy->channel = channel;
3998 //XXX: Using the longer of 2 timeouts (8000 vs 2000 usecs). Specs states
3999 // that 2000 usecs might suffice.
4000 udelay(8000);
4001
4002 return 0;
4003 }
4004
4005 /* http://bcm-specs.sipsolutions.net/TX_Gain_Base_Band */
4006 static u16 bcm43xx_get_txgain_base_band(u16 txpower)
4007 {
4008 u16 ret;
4009
4010 assert(txpower <= 63);
4011
4012 if (txpower >= 54)
4013 ret = 2;
4014 else if (txpower >= 49)
4015 ret = 4;
4016 else if (txpower >= 44)
4017 ret = 5;
4018 else
4019 ret = 6;
4020
4021 return ret;
4022 }
4023
4024 /* http://bcm-specs.sipsolutions.net/TX_Gain_Radio_Frequency_Power_Amplifier */
4025 static u16 bcm43xx_get_txgain_freq_power_amp(u16 txpower)
4026 {
4027 u16 ret;
4028
4029 assert(txpower <= 63);
4030
4031 if (txpower >= 32)
4032 ret = 0;
4033 else if (txpower >= 25)
4034 ret = 1;
4035 else if (txpower >= 20)
4036 ret = 2;
4037 else if (txpower >= 12)
4038 ret = 3;
4039 else
4040 ret = 4;
4041
4042 return ret;
4043 }
4044
4045 /* http://bcm-specs.sipsolutions.net/TX_Gain_Digital_Analog_Converter */
4046 static u16 bcm43xx_get_txgain_dac(u16 txpower)
4047 {
4048 u16 ret;
4049
4050 assert(txpower <= 63);
4051
4052 if (txpower >= 54)
4053 ret = txpower - 53;
4054 else if (txpower >= 49)
4055 ret = txpower - 42;
4056 else if (txpower >= 44)
4057 ret = txpower - 37;
4058 else if (txpower >= 32)
4059 ret = txpower - 32;
4060 else if (txpower >= 25)
4061 ret = txpower - 20;
4062 else if (txpower >= 20)
4063 ret = txpower - 13;
4064 else if (txpower >= 12)
4065 ret = txpower - 8;
4066 else
4067 ret = txpower;
4068
4069 return ret;
4070 }
4071
4072 void bcm43xx_radio_set_txpower_a(struct bcm43xx_wldev *dev, u16 txpower)
4073 {
4074 struct bcm43xx_phy *phy = &dev->phy;
4075 u16 pamp, base, dac, t;
4076
4077 txpower = limit_value(txpower, 0, 63);
4078
4079 pamp = bcm43xx_get_txgain_freq_power_amp(txpower);
4080 pamp <<= 5;
4081 pamp &= 0x00E0;
4082 bcm43xx_phy_write(dev, 0x0019, pamp);
4083
4084 base = bcm43xx_get_txgain_base_band(txpower);
4085 base &= 0x000F;
4086 bcm43xx_phy_write(dev, 0x0017, base | 0x0020);
4087
4088 t = bcm43xx_ofdmtab_read16(dev, 0x3000, 1);
4089 t &= 0x0007;
4090
4091 dac = bcm43xx_get_txgain_dac(txpower);
4092 dac <<= 3;
4093 dac |= t;
4094
4095 bcm43xx_ofdmtab_write16(dev, 0x3000, 1, dac);
4096
4097 phy->txpwr_offset = txpower;
4098
4099 TODO();
4100 //TODO: FuncPlaceholder (Adjust BB loft cancel)
4101 }
4102
4103 void bcm43xx_radio_set_txpower_bg(struct bcm43xx_wldev *dev,
4104 s16 baseband_attenuation,
4105 s16 radio_attenuation,
4106 s16 _tx_magn)
4107 {
4108 struct bcm43xx_phy *phy = &dev->phy;
4109 u8 tx_bias = phy->lo_control->tx_bias;
4110 u8 tx_magn;
4111
4112 if (baseband_attenuation < 0)
4113 baseband_attenuation = phy->bbatt;
4114 if (radio_attenuation < 0)
4115 radio_attenuation = phy->rfatt;
4116 if (_tx_magn < 0)
4117 _tx_magn = phy->lo_control->tx_magn;
4118 tx_magn = _tx_magn;
4119 phy->bbatt = baseband_attenuation;
4120 phy->rfatt = radio_attenuation;
4121
4122 /* Set Baseband Attenuation on device. */
4123 bcm43xx_phy_set_baseband_attenuation(dev, baseband_attenuation);
4124
4125 /* Set Radio Attenuation on device. */
4126 bcm43xx_shm_write16(dev, BCM43xx_SHM_SHARED,
4127 0x0064, radio_attenuation);
4128 if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) {
4129 bcm43xx_phy_write(dev, 0x0043, radio_attenuation);
4130 } else {
4131 bcm43xx_radio_write16(dev, 0x0043,
4132 (bcm43xx_radio_read16(dev, 0x0043)
4133 & 0xFFF0) | radio_attenuation);
4134 }
4135
4136 if (phy->radio_ver == 0x2050) {//FIXME: It seems like tx_magn and tx_bias are swapped in this func.
4137 if (phy->radio_rev < 6) {
4138 bcm43xx_radio_write16(dev, 0x0043,
4139 (bcm43xx_radio_read16(dev, 0x0043)
4140 & 0xFF8F) | tx_magn);
4141 } else if (phy->radio_rev != 8) {
4142 bcm43xx_radio_write16(dev, 0x0052,
4143 (bcm43xx_radio_read16(dev, 0x0052)
4144 & 0xFF8F) | tx_magn);
4145 } else {
4146 bcm43xx_radio_write16(dev, 0x52,
4147 (bcm43xx_radio_read16(dev, 0x52) & 0xFF00) |
4148 tx_magn | tx_bias);
4149 }
4150 }
4151 if (phy->radio_rev != 8) {
4152 bcm43xx_radio_write16(dev, 0x0052,
4153 (bcm43xx_radio_read16(dev, 0x0052)
4154 & 0xFFF0) | tx_bias);
4155 }
4156 if (phy->type == BCM43xx_PHYTYPE_G)
4157 bcm43xx_lo_g_adjust(dev);
4158 }
4159
4160 u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_wldev *dev)
4161 {
4162 struct bcm43xx_phy *phy = &dev->phy;
4163
4164 if (phy->radio_ver == 0x2050 && phy->radio_rev < 6)
4165 return 0;
4166 return 2;
4167 }
4168
4169 u16 bcm43xx_default_radio_attenuation(struct bcm43xx_wldev *dev)
4170 {
4171 struct ssb_bus *bus = dev->dev->bus;
4172 struct bcm43xx_phy *phy = &dev->phy;
4173 u16 att = 0xFFFF;
4174
4175 if (phy->type == BCM43xx_PHYTYPE_A)
4176 return 0x60;
4177
4178 switch (phy->radio_ver) {
4179 case 0x2053:
4180 switch (phy->radio_rev) {
4181 case 1:
4182 att = 6;
4183 break;
4184 }
4185 break;
4186 case 0x2050:
4187 switch (phy->radio_rev) {
4188 case 0:
4189 att = 5;
4190 break;
4191 case 1:
4192 if (phy->type == BCM43xx_PHYTYPE_G) {
4193 if (bus->board_vendor == SSB_BOARDVENDOR_BCM &&
4194 bus->board_type == SSB_BOARD_BCM4309G &&
4195 bus->board_rev >= 30)
4196 att = 3;
4197 else if (bus->board_vendor == SSB_BOARDVENDOR_BCM &&
4198 bus->board_type == SSB_BOARD_BU4306)
4199 att = 3;
4200 else
4201 att = 1;
4202 } else {
4203 if (bus->board_vendor == SSB_BOARDVENDOR_BCM &&
4204 bus->board_type == SSB_BOARD_BCM4309G &&
4205 bus->board_rev >= 30)
4206 att = 7;
4207 else
4208 att = 6;
4209 }
4210 break;
4211 case 2:
4212 if (phy->type == BCM43xx_PHYTYPE_G) {
4213 if (bus->board_vendor == SSB_BOARDVENDOR_BCM &&
4214 bus->board_type == SSB_BOARD_BCM4309G &&
4215 bus->board_rev >= 30)
4216 att = 3;
4217 else if (bus->board_vendor == SSB_BOARDVENDOR_BCM &&
4218 bus->board_type == SSB_BOARD_BU4306)
4219 att = 5;
4220 else if (bus->chip_id == 0x4320)
4221 att = 4;
4222 else
4223 att = 3;
4224 } else
4225 att = 6;
4226 break;
4227 case 3:
4228 att = 5;
4229 break;
4230 case 4:
4231 case 5:
4232 att = 1;
4233 break;
4234 case 6:
4235 case 7:
4236 att = 5;
4237 break;
4238 case 8:
4239 att = 0x1A;
4240 break;
4241 case 9:
4242 default:
4243 att = 5;
4244 }
4245 }
4246 if (bus->board_vendor == SSB_BOARDVENDOR_BCM &&
4247 bus->board_type == SSB_BOARD_BCM4309G) {
4248 if (bus->board_rev < 0x43)
4249 att = 2;
4250 else if (bus->board_rev < 0x51)
4251 att = 3;
4252 }
4253 if (att == 0xFFFF)
4254 att = 5;
4255
4256 return att;
4257 }
4258
4259 u16 bcm43xx_default_txctl1(struct bcm43xx_wldev *dev)
4260 {
4261 struct bcm43xx_phy *phy = &dev->phy;
4262
4263 if (phy->radio_ver != 0x2050)
4264 return 0;
4265 if (phy->radio_rev == 1)
4266 return 3;
4267 if (phy->radio_rev < 6)
4268 return 2;
4269 if (phy->radio_rev == 8)
4270 return 1;
4271 return 0;
4272 }
4273
4274 void bcm43xx_radio_turn_on(struct bcm43xx_wldev *dev)
4275 {
4276 struct bcm43xx_phy *phy = &dev->phy;
4277 int err;
4278
4279 if (phy->radio_on)
4280 return;
4281
4282 switch (phy->type) {
4283 case BCM43xx_PHYTYPE_A:
4284 bcm43xx_radio_write16(dev, 0x0004, 0x00C0);
4285 bcm43xx_radio_write16(dev, 0x0005, 0x0008);
4286 bcm43xx_phy_write(dev, 0x0010, bcm43xx_phy_read(dev, 0x0010) & 0xFFF7);
4287 bcm43xx_phy_write(dev, 0x0011, bcm43xx_phy_read(dev, 0x0011) & 0xFFF7);
4288 bcm43xx_radio_init2060(dev);
4289 break;
4290 case BCM43xx_PHYTYPE_B:
4291 case BCM43xx_PHYTYPE_G:
4292 bcm43xx_phy_write(dev, 0x0015, 0x8000);
4293 bcm43xx_phy_write(dev, 0x0015, 0xCC00);
4294 bcm43xx_phy_write(dev, 0x0015, (phy->gmode ? 0x00C0 : 0x0000));
4295 err = bcm43xx_radio_selectchannel(dev, BCM43xx_DEFAULT_CHANNEL_BG, 1);
4296 assert(err == 0);
4297 break;
4298 default:
4299 assert(0);
4300 }
4301 phy->radio_on = 1;
4302 dprintk(KERN_INFO PFX "Radio turned on\n");
4303 }
4304
4305 void bcm43xx_radio_turn_off(struct bcm43xx_wldev *dev)
4306 {
4307 struct bcm43xx_phy *phy = &dev->phy;
4308
4309 if (phy->type == BCM43xx_PHYTYPE_A) {
4310 bcm43xx_radio_write16(dev, 0x0004, 0x00FF);
4311 bcm43xx_radio_write16(dev, 0x0005, 0x00FB);
4312 bcm43xx_phy_write(dev, 0x0010, bcm43xx_phy_read(dev, 0x0010) | 0x0008);
4313 bcm43xx_phy_write(dev, 0x0011, bcm43xx_phy_read(dev, 0x0011) | 0x0008);
4314 }
4315 if (phy->type == BCM43xx_PHYTYPE_G && dev->dev->id.revision >= 5) {
4316 bcm43xx_phy_write(dev, 0x0811, bcm43xx_phy_read(dev, 0x0811) | 0x008C);
4317 bcm43xx_phy_write(dev, 0x0812, bcm43xx_phy_read(dev, 0x0812) & 0xFF73);
4318 } else
4319 bcm43xx_phy_write(dev, 0x0015, 0xAA00);
4320 phy->radio_on = 0;
4321 dprintk(KERN_INFO PFX "Radio turned off\n");
4322 }