blob: 0bafa3b17035db8d5767da2632da343dd1ae70c7 [file] [log] [blame]
Rafał Miłecki1d738e62011-07-07 15:25:27 +02001/*
2
3 Broadcom B43 wireless driver
4 IEEE 802.11n LCN-PHY support
5
Rafał Miłecki108f4f32011-09-03 21:01:02 +02006 Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com>
7
Rafał Miłecki1d738e62011-07-07 15:25:27 +02008 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
21 Boston, MA 02110-1301, USA.
22
Rafał Miłeckib5347062011-09-16 12:33:59 +020023 This file incorporates work covered by the following copyright and
24 permission notice:
25
26 Copyright (c) 2010 Broadcom Corporation
27
28 Permission to use, copy, modify, and/or distribute this software for any
29 purpose with or without fee is hereby granted, provided that the above
30 copyright notice and this permission notice appear in all copies.
Rafał Miłecki1d738e62011-07-07 15:25:27 +020031*/
32
33#include <linux/slab.h>
34
35#include "b43.h"
36#include "phy_lcn.h"
37#include "tables_phy_lcn.h"
38#include "main.h"
39
Rafał Miłecki1b0a69c2011-09-16 12:34:02 +020040struct lcn_tx_gains {
41 u16 gm_gain;
42 u16 pga_gain;
43 u16 pad_gain;
44 u16 dac_gain;
45};
46
Rafał Miłecki0c5644b92011-09-16 12:34:00 +020047struct lcn_tx_iir_filter {
48 u8 type;
49 u16 values[16];
50};
51
Rafał Miłecki29818082011-09-16 16:36:32 +020052enum lcn_sense_type {
53 B43_SENSE_TEMP,
54 B43_SENSE_VBAT,
55};
56
Rafał Miłeckiac78a522011-09-16 12:34:01 +020057/* In theory it's PHY common function, move if needed */
58/* brcms_b_switch_macfreq */
59static void b43_phy_switch_macfreq(struct b43_wldev *dev, u8 spurmode)
60{
61 if (dev->dev->chip_id == 43224 || dev->dev->chip_id == 43225) {
62 switch (spurmode) {
63 case 2: /* 126 Mhz */
64 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x2082);
65 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
66 break;
67 case 1: /* 123 Mhz */
68 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x5341);
69 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
70 break;
71 default: /* 120 Mhz */
72 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x8889);
73 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
74 break;
75 }
76 } else if (dev->phy.type == B43_PHYTYPE_LCN) {
77 switch (spurmode) {
78 case 1: /* 82 Mhz */
79 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x7CE0);
80 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
81 break;
82 default: /* 80 Mhz */
83 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0xCCCD);
84 b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
85 break;
86 }
87 }
88}
89
Rafał Miłecki1d738e62011-07-07 15:25:27 +020090/**************************************************
Rafał Miłeckidc713fb2011-08-15 18:50:56 +020091 * Radio 2064.
92 **************************************************/
93
Rafał Miłeckibce4dc42011-08-31 23:36:20 +020094/* wlc_lcnphy_radio_2064_channel_tune_4313 */
Rafał Miłecki39f7d332011-08-28 14:59:58 +020095static void b43_radio_2064_channel_setup(struct b43_wldev *dev)
96{
97 u16 save[2];
98
99 b43_radio_set(dev, 0x09d, 0x4);
100 b43_radio_write(dev, 0x09e, 0xf);
101
Rafał Miłeckicf577fc2011-08-31 23:36:21 +0200102 /* Channel specific values in theory, in practice always the same */
Rafał Miłecki39f7d332011-08-28 14:59:58 +0200103 b43_radio_write(dev, 0x02a, 0xb);
104 b43_radio_maskset(dev, 0x030, ~0x3, 0xa);
105 b43_radio_maskset(dev, 0x091, ~0x3, 0);
106 b43_radio_maskset(dev, 0x038, ~0xf, 0x7);
107 b43_radio_maskset(dev, 0x030, ~0xc, 0x8);
108 b43_radio_maskset(dev, 0x05e, ~0xf, 0x8);
109 b43_radio_maskset(dev, 0x05e, ~0xf0, 0x80);
110 b43_radio_write(dev, 0x06c, 0x80);
111
112 save[0] = b43_radio_read(dev, 0x044);
113 save[1] = b43_radio_read(dev, 0x12b);
114
115 b43_radio_set(dev, 0x044, 0x7);
116 b43_radio_set(dev, 0x12b, 0xe);
117
118 /* TODO */
119
120 b43_radio_write(dev, 0x040, 0xfb);
121
122 b43_radio_write(dev, 0x041, 0x9a);
123 b43_radio_write(dev, 0x042, 0xa3);
124 b43_radio_write(dev, 0x043, 0x0c);
125
126 /* TODO */
127
128 b43_radio_set(dev, 0x044, 0x0c);
129 udelay(1);
130
131 b43_radio_write(dev, 0x044, save[0]);
132 b43_radio_write(dev, 0x12b, save[1]);
133
Rafał Miłeckicf577fc2011-08-31 23:36:21 +0200134 if (dev->phy.rev == 1) {
135 /* brcmsmac uses outdated 0x3 for 0x038 */
136 b43_radio_write(dev, 0x038, 0x0);
137 b43_radio_write(dev, 0x091, 0x7);
138 }
Rafał Miłecki39f7d332011-08-28 14:59:58 +0200139}
140
Rafał Miłeckibce4dc42011-08-31 23:36:20 +0200141/* wlc_radio_2064_init */
Rafał Miłeckidc713fb2011-08-15 18:50:56 +0200142static void b43_radio_2064_init(struct b43_wldev *dev)
143{
Rafał Miłeckicf577fc2011-08-31 23:36:21 +0200144 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
145 b43_radio_write(dev, 0x09c, 0x0020);
146 b43_radio_write(dev, 0x105, 0x0008);
147 } else {
148 /* TODO */
149 }
Rafał Miłeckidc713fb2011-08-15 18:50:56 +0200150 b43_radio_write(dev, 0x032, 0x0062);
151 b43_radio_write(dev, 0x033, 0x0019);
152 b43_radio_write(dev, 0x090, 0x0010);
153 b43_radio_write(dev, 0x010, 0x0000);
Rafał Miłeckicf577fc2011-08-31 23:36:21 +0200154 if (dev->phy.rev == 1) {
155 b43_radio_write(dev, 0x060, 0x007f);
156 b43_radio_write(dev, 0x061, 0x0072);
157 b43_radio_write(dev, 0x062, 0x007f);
158 }
Rafał Miłeckidc713fb2011-08-15 18:50:56 +0200159 b43_radio_write(dev, 0x01d, 0x0002);
160 b43_radio_write(dev, 0x01e, 0x0006);
161
162 b43_phy_write(dev, 0x4ea, 0x4688);
163 b43_phy_maskset(dev, 0x4eb, ~0x7, 0x2);
164 b43_phy_mask(dev, 0x4eb, ~0x01c0);
Rafał Miłeckibd3bf692011-08-28 14:28:44 +0200165 b43_phy_maskset(dev, 0x46a, 0xff00, 0x19);
Rafał Miłeckidc713fb2011-08-15 18:50:56 +0200166
167 b43_lcntab_write(dev, B43_LCNTAB16(0x00, 0x55), 0);
168
169 b43_radio_mask(dev, 0x05b, (u16) ~0xff02);
170 b43_radio_set(dev, 0x004, 0x40);
171 b43_radio_set(dev, 0x120, 0x10);
172 b43_radio_set(dev, 0x078, 0x80);
173 b43_radio_set(dev, 0x129, 0x2);
174 b43_radio_set(dev, 0x057, 0x1);
175 b43_radio_set(dev, 0x05b, 0x2);
176
177 /* TODO: wait for some bit to be set */
178 b43_radio_read(dev, 0x05c);
179
180 b43_radio_mask(dev, 0x05b, (u16) ~0xff02);
181 b43_radio_mask(dev, 0x057, (u16) ~0xff01);
182
183 b43_phy_write(dev, 0x933, 0x2d6b);
184 b43_phy_write(dev, 0x934, 0x2d6b);
185 b43_phy_write(dev, 0x935, 0x2d6b);
186 b43_phy_write(dev, 0x936, 0x2d6b);
187 b43_phy_write(dev, 0x937, 0x016b);
188
189 b43_radio_mask(dev, 0x057, (u16) ~0xff02);
190 b43_radio_write(dev, 0x0c2, 0x006f);
191}
192
193/**************************************************
Rafał Miłecki78bc2462011-08-15 18:50:55 +0200194 * Various PHY ops
195 **************************************************/
196
Rafał Miłeckibce4dc42011-08-31 23:36:20 +0200197/* wlc_lcnphy_toggle_afe_pwdn */
Rafał Miłecki78bc2462011-08-15 18:50:55 +0200198static void b43_phy_lcn_afe_set_unset(struct b43_wldev *dev)
199{
200 u16 afe_ctl2 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL2);
201 u16 afe_ctl1 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL1);
202
203 b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2 | 0x1);
204 b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1 | 0x1);
205
206 b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2 & ~0x1);
207 b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1 & ~0x1);
208
209 b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2);
210 b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1);
211}
212
Rafał Miłecki1b0a69c2011-09-16 12:34:02 +0200213/* wlc_lcnphy_get_pa_gain */
214static u16 b43_phy_lcn_get_pa_gain(struct b43_wldev *dev)
215{
216 return (b43_phy_read(dev, 0x4fb) & 0x7f00) >> 8;
217}
218
219/* wlc_lcnphy_set_dac_gain */
220static void b43_phy_lcn_set_dac_gain(struct b43_wldev *dev, u16 dac_gain)
221{
222 u16 dac_ctrl;
223
224 dac_ctrl = b43_phy_read(dev, 0x439);
225 dac_ctrl = dac_ctrl & 0xc7f;
226 dac_ctrl = dac_ctrl | (dac_gain << 7);
227 b43_phy_maskset(dev, 0x439, ~0xfff, dac_ctrl);
228}
229
230/* wlc_lcnphy_set_bbmult */
231static void b43_phy_lcn_set_bbmult(struct b43_wldev *dev, u8 m0)
232{
233 b43_lcntab_write(dev, B43_LCNTAB16(0x00, 0x57), m0 << 8);
234}
235
Rafał Miłeckibce4dc42011-08-31 23:36:20 +0200236/* wlc_lcnphy_clear_tx_power_offsets */
237static void b43_phy_lcn_clear_tx_power_offsets(struct b43_wldev *dev)
Rafał Miłecki78bc2462011-08-15 18:50:55 +0200238{
239 u8 i;
240
Rafał Miłeckicf577fc2011-08-31 23:36:21 +0200241 if (1) { /* FIXME */
242 b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x340);
243 for (i = 0; i < 30; i++) {
244 b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0);
245 b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0);
246 }
Rafał Miłecki78bc2462011-08-15 18:50:55 +0200247 }
248
249 b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x80);
250 for (i = 0; i < 64; i++) {
251 b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0);
252 b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0);
253 }
254}
255
Rafał Miłeckibce4dc42011-08-31 23:36:20 +0200256/* wlc_lcnphy_rev0_baseband_init */
257static void b43_phy_lcn_rev0_baseband_init(struct b43_wldev *dev)
Rafał Miłeckibd3bf692011-08-28 14:28:44 +0200258{
259 b43_radio_write(dev, 0x11c, 0);
260
261 b43_phy_write(dev, 0x43b, 0);
262 b43_phy_write(dev, 0x43c, 0);
263 b43_phy_write(dev, 0x44c, 0);
264 b43_phy_write(dev, 0x4e6, 0);
265 b43_phy_write(dev, 0x4f9, 0);
266 b43_phy_write(dev, 0x4b0, 0);
267 b43_phy_write(dev, 0x938, 0);
268 b43_phy_write(dev, 0x4b0, 0);
269 b43_phy_write(dev, 0x44e, 0);
270
271 b43_phy_set(dev, 0x567, 0x03);
272
273 b43_phy_set(dev, 0x44a, 0x44);
274 b43_phy_write(dev, 0x44a, 0x80);
275
Rafał Miłeckicf577fc2011-08-31 23:36:21 +0200276 if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM))
277 ; /* TODO */
Rafał Miłeckibd3bf692011-08-28 14:28:44 +0200278 b43_phy_maskset(dev, 0x634, ~0xff, 0xc);
Rafał Miłeckicf577fc2011-08-31 23:36:21 +0200279 if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM) {
280 b43_phy_maskset(dev, 0x634, ~0xff, 0xa);
281 b43_phy_write(dev, 0x910, 0x1);
282 }
Rafał Miłeckibd3bf692011-08-28 14:28:44 +0200283
284 b43_phy_write(dev, 0x910, 0x1);
285
286 b43_phy_maskset(dev, 0x448, ~0x300, 0x100);
287 b43_phy_maskset(dev, 0x608, ~0xff, 0x17);
288 b43_phy_maskset(dev, 0x604, ~0x7ff, 0x3ea);
Rafał Miłeckibce4dc42011-08-31 23:36:20 +0200289}
Rafał Miłeckibd3bf692011-08-28 14:28:44 +0200290
Rafał Miłeckibce4dc42011-08-31 23:36:20 +0200291/* wlc_lcnphy_bu_tweaks */
292static void b43_phy_lcn_bu_tweaks(struct b43_wldev *dev)
293{
Rafał Miłeckibd3bf692011-08-28 14:28:44 +0200294 b43_phy_set(dev, 0x805, 0x1);
295
296 b43_phy_maskset(dev, 0x42f, ~0x7, 0x3);
297 b43_phy_maskset(dev, 0x030, ~0x7, 0x3);
298
299 b43_phy_write(dev, 0x414, 0x1e10);
300 b43_phy_write(dev, 0x415, 0x0640);
301
302 b43_phy_maskset(dev, 0x4df, (u16) ~0xff00, 0xf700);
303
304 b43_phy_set(dev, 0x44a, 0x44);
305 b43_phy_write(dev, 0x44a, 0x80);
306
307 b43_phy_maskset(dev, 0x434, ~0xff, 0xfd);
308 b43_phy_maskset(dev, 0x420, ~0xff, 0x10);
309
Rafał Miłeckicf577fc2011-08-31 23:36:21 +0200310 if (dev->dev->bus_sprom->board_rev >= 0x1204)
311 b43_radio_set(dev, 0x09b, 0xf0);
Rafał Miłeckibd3bf692011-08-28 14:28:44 +0200312
313 b43_phy_write(dev, 0x7d6, 0x0902);
314
Rafał Miłeckibbb55742011-09-16 12:34:03 +0200315 b43_phy_maskset(dev, 0x429, ~0xf, 0x9);
316 b43_phy_maskset(dev, 0x429, ~(0x3f << 4), 0xe << 4);
Rafał Miłeckibce4dc42011-08-31 23:36:20 +0200317
318 if (dev->phy.rev == 1) {
Rafał Miłeckibbb55742011-09-16 12:34:03 +0200319 b43_phy_maskset(dev, 0x423, ~0xff, 0x46);
320 b43_phy_maskset(dev, 0x411, ~0xff, 1);
321 b43_phy_set(dev, 0x434, 0xff); /* FIXME: update to wl */
322
323 /* TODO: wl operates on PHY 0x416, brcmsmac is outdated here */
324
325 b43_phy_maskset(dev, 0x656, ~0xf, 2);
326 b43_phy_set(dev, 0x44d, 4);
327
328 b43_radio_set(dev, 0x0f7, 0x4);
329 b43_radio_mask(dev, 0x0f1, ~0x3);
330 b43_radio_maskset(dev, 0x0f2, ~0xf8, 0x90);
331 b43_radio_maskset(dev, 0x0f3, ~0x3, 0x2);
332 b43_radio_maskset(dev, 0x0f3, ~0xf0, 0xa0);
333
334 b43_radio_set(dev, 0x11f, 0x2);
Rafał Miłeckibce4dc42011-08-31 23:36:20 +0200335
336 b43_phy_lcn_clear_tx_power_offsets(dev);
Rafał Miłeckibbb55742011-09-16 12:34:03 +0200337
338 /* TODO: something more? */
Rafał Miłeckibce4dc42011-08-31 23:36:20 +0200339 }
Rafał Miłeckibd3bf692011-08-28 14:28:44 +0200340}
341
Rafał Miłeckibce4dc42011-08-31 23:36:20 +0200342/* wlc_lcnphy_vbat_temp_sense_setup */
Rafał Miłecki29818082011-09-16 16:36:32 +0200343static void b43_phy_lcn_sense_setup(struct b43_wldev *dev,
344 enum lcn_sense_type sense_type)
Rafał Miłecki765b07e2011-08-28 19:59:28 +0200345{
Rafał Miłecki29818082011-09-16 16:36:32 +0200346 u8 auxpga_vmidcourse, auxpga_vmidfine, auxpga_gain;
347 u16 auxpga_vmid;
348 u8 tx_pwr_idx;
Rafał Miłecki765b07e2011-08-28 19:59:28 +0200349 u8 i;
350
351 u16 save_radio_regs[6][2] = {
352 { 0x007, 0 }, { 0x0ff, 0 }, { 0x11f, 0 }, { 0x005, 0 },
353 { 0x025, 0 }, { 0x112, 0 },
354 };
355 u16 save_phy_regs[14][2] = {
356 { 0x503, 0 }, { 0x4a4, 0 }, { 0x4d0, 0 }, { 0x4d9, 0 },
357 { 0x4da, 0 }, { 0x4a6, 0 }, { 0x938, 0 }, { 0x939, 0 },
358 { 0x4d8, 0 }, { 0x4d0, 0 }, { 0x4d7, 0 }, { 0x4a5, 0 },
359 { 0x40d, 0 }, { 0x4a2, 0 },
360 };
361 u16 save_radio_4a4;
362
Rafał Miłecki29818082011-09-16 16:36:32 +0200363 msleep(1);
364
365 /* Save */
Rafał Miłecki765b07e2011-08-28 19:59:28 +0200366 for (i = 0; i < 6; i++)
367 save_radio_regs[i][1] = b43_radio_read(dev,
368 save_radio_regs[i][0]);
369 for (i = 0; i < 14; i++)
370 save_phy_regs[i][1] = b43_phy_read(dev, save_phy_regs[i][0]);
Rafał Miłecki29818082011-09-16 16:36:32 +0200371 b43_mac_suspend(dev);
Rafał Miłecki765b07e2011-08-28 19:59:28 +0200372 save_radio_4a4 = b43_radio_read(dev, 0x4a4);
Rafał Miłecki29818082011-09-16 16:36:32 +0200373 /* wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); */
374 tx_pwr_idx = dev->phy.lcn->tx_pwr_curr_idx;
Rafał Miłecki765b07e2011-08-28 19:59:28 +0200375
Rafał Miłecki29818082011-09-16 16:36:32 +0200376 /* Setup */
377 /* TODO: wlc_lcnphy_set_tx_pwr_by_index(pi, 127); */
378 b43_radio_set(dev, 0x007, 0x1);
379 b43_radio_set(dev, 0x0ff, 0x10);
380 b43_radio_set(dev, 0x11f, 0x4);
Rafał Miłecki765b07e2011-08-28 19:59:28 +0200381
Rafał Miłecki29818082011-09-16 16:36:32 +0200382 b43_phy_mask(dev, 0x503, ~0x1);
383 b43_phy_mask(dev, 0x503, ~0x4);
384 b43_phy_mask(dev, 0x4a4, ~0x4000);
385 b43_phy_mask(dev, 0x4a4, (u16) ~0x8000);
386 b43_phy_mask(dev, 0x4d0, ~0x20);
387 b43_phy_set(dev, 0x4a5, 0xff);
388 b43_phy_maskset(dev, 0x4a5, ~0x7000, 0x5000);
389 b43_phy_mask(dev, 0x4a5, ~0x700);
390 b43_phy_maskset(dev, 0x40d, ~0xff, 64);
391 b43_phy_maskset(dev, 0x40d, ~0x700, 0x600);
392 b43_phy_maskset(dev, 0x4a2, ~0xff, 64);
393 b43_phy_maskset(dev, 0x4a2, ~0x700, 0x600);
394 b43_phy_maskset(dev, 0x4d9, ~0x70, 0x20);
395 b43_phy_maskset(dev, 0x4d9, ~0x700, 0x300);
396 b43_phy_maskset(dev, 0x4d9, ~0x7000, 0x1000);
397 b43_phy_mask(dev, 0x4da, ~0x1000);
398 b43_phy_set(dev, 0x4da, 0x2000);
399 b43_phy_set(dev, 0x4a6, 0x8000);
400
401 b43_radio_write(dev, 0x025, 0xc);
402 b43_radio_set(dev, 0x005, 0x8);
403 b43_phy_set(dev, 0x938, 0x4);
404 b43_phy_set(dev, 0x939, 0x4);
405 b43_phy_set(dev, 0x4a4, 0x1000);
406
407 /* FIXME: don't hardcode */
408 b43_lcntab_write(dev, B43_LCNTAB16(0x8, 0x6), 0x640);
409
410 switch (sense_type) {
411 case B43_SENSE_TEMP:
412 b43_phy_set(dev, 0x4d7, 0x8);
413 b43_phy_maskset(dev, 0x4d7, ~0x7000, 0x1000);
414 auxpga_vmidcourse = 8;
415 auxpga_vmidfine = 0x4;
416 auxpga_gain = 2;
417 b43_radio_set(dev, 0x082, 0x20);
418 break;
419 case B43_SENSE_VBAT:
420 b43_phy_set(dev, 0x4d7, 0x8);
421 b43_phy_maskset(dev, 0x4d7, ~0x7000, 0x3000);
422 auxpga_vmidcourse = 7;
423 auxpga_vmidfine = 0xa;
424 auxpga_gain = 2;
425 break;
426 }
427 auxpga_vmid = (0x200 | (auxpga_vmidcourse << 4) | auxpga_vmidfine);
428
429 b43_phy_set(dev, 0x4d8, 0x1);
430 b43_phy_maskset(dev, 0x4d8, ~(0x3ff << 2), auxpga_vmid << 2);
431 b43_phy_set(dev, 0x4d8, 0x2);
432 b43_phy_maskset(dev, 0x4d8, ~(0x7 << 12), auxpga_gain << 12);
433 b43_phy_set(dev, 0x4d0, 0x20);
434 b43_radio_write(dev, 0x112, 0x6);
435
Rafał Miłecki177c3732011-09-21 21:44:15 +0200436 b43_dummy_transmission(dev, true, false);
Rafał Miłecki29818082011-09-16 16:36:32 +0200437 /* Wait if not done */
438 if (!(b43_phy_read(dev, 0x476) & 0x8000))
439 udelay(10);
440
441 /* Restore */
Rafał Miłecki765b07e2011-08-28 19:59:28 +0200442 for (i = 0; i < 6; i++)
443 b43_radio_write(dev, save_radio_regs[i][0],
444 save_radio_regs[i][1]);
445 for (i = 0; i < 14; i++)
446 b43_phy_write(dev, save_phy_regs[i][0], save_phy_regs[i][1]);
Rafał Miłecki29818082011-09-16 16:36:32 +0200447 /* TODO: wlc_lcnphy_set_tx_pwr_by_index(tx_pwr_idx) */
Rafał Miłecki765b07e2011-08-28 19:59:28 +0200448 b43_radio_write(dev, 0x4a4, save_radio_4a4);
Rafał Miłecki29818082011-09-16 16:36:32 +0200449
450 b43_mac_enable(dev);
451
452 msleep(1);
Rafał Miłecki765b07e2011-08-28 19:59:28 +0200453}
454
Rafał Miłecki0c5644b92011-09-16 12:34:00 +0200455static bool b43_phy_lcn_load_tx_iir_cck_filter(struct b43_wldev *dev,
456 u8 filter_type)
457{
458 int i, j;
459 u16 phy_regs[] = { 0x910, 0x91e, 0x91f, 0x924, 0x925, 0x926, 0x920,
460 0x921, 0x927, 0x928, 0x929, 0x922, 0x923, 0x930,
461 0x931, 0x932 };
462 /* Table is from brcmsmac, values for type 25 were outdated, probably
463 * others need updating too */
464 struct lcn_tx_iir_filter tx_iir_filters_cck[] = {
465 { 0, { 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778,
466 1582, 64, 128, 64 } },
467 { 1, { 1, 402, 1847, 259, 59, 259, 671, 1794, 68, 54, 68, 608,
468 1863, 93, 167, 93 } },
469 { 2, { 1, 415, 1874, 64, 128, 64, 792, 1656, 192, 384, 192,
470 778, 1582, 64, 128, 64 } },
471 { 3, { 1, 302, 1841, 129, 258, 129, 658, 1720, 205, 410, 205,
472 754, 1760, 170, 340, 170 } },
473 { 20, { 1, 360, 1884, 242, 1734, 242, 752, 1720, 205, 1845, 205,
474 767, 1760, 256, 185, 256 } },
475 { 21, { 1, 360, 1884, 149, 1874, 149, 752, 1720, 205, 1883, 205,
476 767, 1760, 256, 273, 256 } },
477 { 22, { 1, 360, 1884, 98, 1948, 98, 752, 1720, 205, 1924, 205,
478 767, 1760, 256, 352, 256 } },
479 { 23, { 1, 350, 1884, 116, 1966, 116, 752, 1720, 205, 2008, 205,
480 767, 1760, 128, 233, 128 } },
481 { 24, { 1, 325, 1884, 32, 40, 32, 756, 1720, 256, 471, 256, 766,
482 1760, 256, 1881, 256 } },
483 { 25, { 1, 299, 1884, 51, 64, 51, 736, 1720, 256, 471, 256, 765,
484 1760, 262, 1878, 262 } },
485 /* brcmsmac version { 25, { 1, 299, 1884, 51, 64, 51, 736, 1720,
486 * 256, 471, 256, 765, 1760, 256, 1881, 256 } }, */
487 { 26, { 1, 277, 1943, 39, 117, 88, 637, 1838, 64, 192, 144, 614,
488 1864, 128, 384, 288 } },
489 { 27, { 1, 245, 1943, 49, 147, 110, 626, 1838, 256, 768, 576,
490 613, 1864, 128, 384, 288 } },
491 { 30, { 1, 302, 1841, 61, 122, 61, 658, 1720, 205, 410, 205,
492 754, 1760, 170, 340, 170 } },
493 };
494
495 for (i = 0; i < ARRAY_SIZE(tx_iir_filters_cck); i++) {
496 if (tx_iir_filters_cck[i].type == filter_type) {
497 for (j = 0; j < 16; j++)
498 b43_phy_write(dev, phy_regs[j],
499 tx_iir_filters_cck[i].values[j]);
500 return true;
501 }
502 }
503
504 return false;
505}
506
507static bool b43_phy_lcn_load_tx_iir_ofdm_filter(struct b43_wldev *dev,
508 u8 filter_type)
509{
510 int i, j;
511 u16 phy_regs[] = { 0x90f, 0x900, 0x901, 0x906, 0x907, 0x908, 0x902,
512 0x903, 0x909, 0x90a, 0x90b, 0x904, 0x905, 0x90c,
513 0x90d, 0x90e };
514 struct lcn_tx_iir_filter tx_iir_filters_ofdm[] = {
515 { 0, { 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0,
516 0x0, 0x278, 0xfea0, 0x80, 0x100, 0x80 } },
517 { 1, { 0, 374, 0xFF79, 16, 32, 16, 799, 0xFE74, 50, 32, 50, 750,
518 0xFE2B, 212, 0xFFCE, 212 } },
519 { 2, { 0, 375, 0xFF16, 37, 76, 37, 799, 0xFE74, 32, 20, 32, 748,
520 0xFEF2, 128, 0xFFE2, 128 } },
521 };
522
523 for (i = 0; i < ARRAY_SIZE(tx_iir_filters_ofdm); i++) {
524 if (tx_iir_filters_ofdm[i].type == filter_type) {
525 for (j = 0; j < 16; j++)
526 b43_phy_write(dev, phy_regs[j],
527 tx_iir_filters_ofdm[i].values[j]);
528 return true;
529 }
530 }
531
532 return false;
533}
534
Rafał Miłecki1b0a69c2011-09-16 12:34:02 +0200535/* wlc_lcnphy_set_tx_gain_override */
536static void b43_phy_lcn_set_tx_gain_override(struct b43_wldev *dev, bool enable)
537{
538 b43_phy_maskset(dev, 0x4b0, ~(0x1 << 7), enable << 7);
539 b43_phy_maskset(dev, 0x4b0, ~(0x1 << 14), enable << 14);
540 b43_phy_maskset(dev, 0x43b, ~(0x1 << 6), enable << 6);
541}
542
543/* wlc_lcnphy_set_tx_gain */
544static void b43_phy_lcn_set_tx_gain(struct b43_wldev *dev,
545 struct lcn_tx_gains *target_gains)
546{
547 u16 pa_gain = b43_phy_lcn_get_pa_gain(dev);
548
549 b43_phy_write(dev, 0x4b5,
550 (target_gains->gm_gain | (target_gains->pga_gain << 8)));
551 b43_phy_maskset(dev, 0x4fb, ~0x7fff,
552 (target_gains->pad_gain | (pa_gain << 8)));
553 b43_phy_write(dev, 0x4fc,
554 (target_gains->gm_gain | (target_gains->pga_gain << 8)));
555 b43_phy_maskset(dev, 0x4fd, ~0x7fff,
556 (target_gains->pad_gain | (pa_gain << 8)));
557
558 b43_phy_lcn_set_dac_gain(dev, target_gains->dac_gain);
559 b43_phy_lcn_set_tx_gain_override(dev, true);
560}
561
562/* wlc_lcnphy_tx_pwr_ctrl_init */
563static void b43_phy_lcn_tx_pwr_ctl_init(struct b43_wldev *dev)
564{
565 struct lcn_tx_gains tx_gains;
566 u8 bbmult;
567
568 b43_mac_suspend(dev);
569
570 if (!dev->phy.lcn->hw_pwr_ctl_capable) {
571 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
572 tx_gains.gm_gain = 4;
573 tx_gains.pga_gain = 12;
574 tx_gains.pad_gain = 12;
575 tx_gains.dac_gain = 0;
576 bbmult = 150;
577 } else {
578 tx_gains.gm_gain = 7;
579 tx_gains.pga_gain = 15;
580 tx_gains.pad_gain = 14;
581 tx_gains.dac_gain = 0;
582 bbmult = 150;
583 }
584 b43_phy_lcn_set_tx_gain(dev, &tx_gains);
585 b43_phy_lcn_set_bbmult(dev, bbmult);
Rafał Miłecki29818082011-09-16 16:36:32 +0200586 b43_phy_lcn_sense_setup(dev, B43_SENSE_TEMP);
Rafał Miłecki1b0a69c2011-09-16 12:34:02 +0200587 } else {
588 b43err(dev->wl, "TX power control not supported for this HW\n");
589 }
590
591 b43_mac_enable(dev);
592}
593
Rafał Miłeckiac78a522011-09-16 12:34:01 +0200594/* wlc_lcnphy_txrx_spur_avoidance_mode */
595static void b43_phy_lcn_txrx_spur_avoidance_mode(struct b43_wldev *dev,
596 bool enable)
597{
598 if (enable) {
599 b43_phy_write(dev, 0x942, 0x7);
600 b43_phy_write(dev, 0x93b, ((1 << 13) + 23));
601 b43_phy_write(dev, 0x93c, ((1 << 13) + 1989));
602
603 b43_phy_write(dev, 0x44a, 0x084);
604 b43_phy_write(dev, 0x44a, 0x080);
605 b43_phy_write(dev, 0x6d3, 0x2222);
606 b43_phy_write(dev, 0x6d3, 0x2220);
607 } else {
608 b43_phy_write(dev, 0x942, 0x0);
609 b43_phy_write(dev, 0x93b, ((0 << 13) + 23));
610 b43_phy_write(dev, 0x93c, ((0 << 13) + 1989));
611 }
612 b43_phy_switch_macfreq(dev, enable);
613}
614
Rafał Miłecki78bc2462011-08-15 18:50:55 +0200615/**************************************************
Rafał Miłecki39f7d332011-08-28 14:59:58 +0200616 * Channel switching ops.
617 **************************************************/
618
Rafał Miłeckib5347062011-09-16 12:33:59 +0200619/* wlc_lcnphy_set_chanspec_tweaks */
620static void b43_phy_lcn_set_channel_tweaks(struct b43_wldev *dev, int channel)
621{
622 struct bcma_drv_cc *cc = &dev->dev->bdev->bus->drv_cc;
623
624 b43_phy_maskset(dev, 0x448, ~0x300, (channel == 14) ? 0x200 : 0x100);
625
626 if (channel == 1 || channel == 2 || channel == 3 || channel == 4 ||
627 channel == 9 || channel == 10 || channel == 11 || channel == 12) {
628 bcma_chipco_pll_write(cc, 0x2, 0x03000c04);
629 bcma_chipco_pll_maskset(cc, 0x3, 0x00ffffff, 0x0);
630 bcma_chipco_pll_write(cc, 0x4, 0x200005c0);
631
632 bcma_cc_set32(cc, BCMA_CC_PMU_CTL, 0x400);
633
634 b43_phy_write(dev, 0x942, 0);
635
Rafał Miłeckiac78a522011-09-16 12:34:01 +0200636 b43_phy_lcn_txrx_spur_avoidance_mode(dev, false);
Rafał Miłeckib5347062011-09-16 12:33:59 +0200637 b43_phy_maskset(dev, 0x424, (u16) ~0xff00, 0x1b00);
638 b43_phy_write(dev, 0x425, 0x5907);
639 } else {
640 bcma_chipco_pll_write(cc, 0x2, 0x03140c04);
641 bcma_chipco_pll_maskset(cc, 0x3, 0x00ffffff, 0x333333);
642 bcma_chipco_pll_write(cc, 0x4, 0x202c2820);
643
644 bcma_cc_set32(cc, BCMA_CC_PMU_CTL, 0x400);
645
646 b43_phy_write(dev, 0x942, 0);
647
Rafał Miłeckiac78a522011-09-16 12:34:01 +0200648 b43_phy_lcn_txrx_spur_avoidance_mode(dev, true);
Rafał Miłeckib5347062011-09-16 12:33:59 +0200649 b43_phy_maskset(dev, 0x424, (u16) ~0xff00, 0x1f00);
650 b43_phy_write(dev, 0x425, 0x590a);
651 }
652
653 b43_phy_set(dev, 0x44a, 0x44);
654 b43_phy_write(dev, 0x44a, 0x80);
655}
656
657/* wlc_phy_chanspec_set_lcnphy */
Rafał Miłecki39f7d332011-08-28 14:59:58 +0200658static int b43_phy_lcn_set_channel(struct b43_wldev *dev,
659 struct ieee80211_channel *channel,
660 enum nl80211_channel_type channel_type)
661{
Rafał Miłecki0c5644b92011-09-16 12:34:00 +0200662 static const u16 sfo_cfg[14][2] = {
663 {965, 1087}, {967, 1085}, {969, 1082}, {971, 1080}, {973, 1078},
664 {975, 1076}, {977, 1073}, {979, 1071}, {981, 1069}, {983, 1067},
665 {985, 1065}, {987, 1063}, {989, 1060}, {994, 1055},
666 };
667
Rafał Miłeckib5347062011-09-16 12:33:59 +0200668 b43_phy_lcn_set_channel_tweaks(dev, channel->hw_value);
Rafał Miłecki39f7d332011-08-28 14:59:58 +0200669
670 b43_phy_set(dev, 0x44a, 0x44);
671 b43_phy_write(dev, 0x44a, 0x80);
672
673 b43_radio_2064_channel_setup(dev);
674 mdelay(1);
675
676 b43_phy_lcn_afe_set_unset(dev);
677
Rafał Miłecki0c5644b92011-09-16 12:34:00 +0200678 b43_phy_write(dev, 0x657, sfo_cfg[channel->hw_value - 1][0]);
679 b43_phy_write(dev, 0x658, sfo_cfg[channel->hw_value - 1][1]);
680
681 if (channel->hw_value == 14) {
682 b43_phy_maskset(dev, 0x448, ~(0x3 << 8), (2) << 8);
683 b43_phy_lcn_load_tx_iir_cck_filter(dev, 3);
684 } else {
685 b43_phy_maskset(dev, 0x448, ~(0x3 << 8), (1) << 8);
686 /* brcmsmac uses filter_type 2, we follow wl with 25 */
687 b43_phy_lcn_load_tx_iir_cck_filter(dev, 25);
688 }
689 /* brcmsmac uses filter_type 2, we follow wl with 0 */
690 b43_phy_lcn_load_tx_iir_ofdm_filter(dev, 0);
691
692 b43_phy_maskset(dev, 0x4eb, ~(0x7 << 3), 0x1 << 3);
Rafał Miłecki39f7d332011-08-28 14:59:58 +0200693
694 return 0;
695}
696
697/**************************************************
Rafał Miłeckif9286682011-08-14 23:27:28 +0200698 * Basic PHY ops.
699 **************************************************/
700
701static int b43_phy_lcn_op_allocate(struct b43_wldev *dev)
702{
703 struct b43_phy_lcn *phy_lcn;
704
705 phy_lcn = kzalloc(sizeof(*phy_lcn), GFP_KERNEL);
706 if (!phy_lcn)
707 return -ENOMEM;
708 dev->phy.lcn = phy_lcn;
709
710 return 0;
711}
712
713static void b43_phy_lcn_op_free(struct b43_wldev *dev)
714{
715 struct b43_phy *phy = &dev->phy;
716 struct b43_phy_lcn *phy_lcn = phy->lcn;
717
718 kfree(phy_lcn);
719 phy->lcn = NULL;
720}
721
722static void b43_phy_lcn_op_prepare_structs(struct b43_wldev *dev)
723{
724 struct b43_phy *phy = &dev->phy;
725 struct b43_phy_lcn *phy_lcn = phy->lcn;
726
727 memset(phy_lcn, 0, sizeof(*phy_lcn));
728}
729
Rafał Miłeckibce4dc42011-08-31 23:36:20 +0200730/* wlc_phy_init_lcnphy */
Rafał Miłecki78bc2462011-08-15 18:50:55 +0200731static int b43_phy_lcn_op_init(struct b43_wldev *dev)
732{
Rafał Miłeckib5347062011-09-16 12:33:59 +0200733 struct bcma_drv_cc *cc = &dev->dev->bdev->bus->drv_cc;
734
Rafał Miłecki78bc2462011-08-15 18:50:55 +0200735 b43_phy_set(dev, 0x44a, 0x80);
736 b43_phy_mask(dev, 0x44a, 0x7f);
737 b43_phy_set(dev, 0x6d1, 0x80);
738 b43_phy_write(dev, 0x6d0, 0x7);
739
740 b43_phy_lcn_afe_set_unset(dev);
741
742 b43_phy_write(dev, 0x60a, 0xa0);
743 b43_phy_write(dev, 0x46a, 0x19);
744 b43_phy_maskset(dev, 0x663, 0xFF00, 0x64);
745
746 b43_phy_lcn_tables_init(dev);
Rafał Miłecki78bc2462011-08-15 18:50:55 +0200747
Rafał Miłeckibce4dc42011-08-31 23:36:20 +0200748 b43_phy_lcn_rev0_baseband_init(dev);
749 b43_phy_lcn_bu_tweaks(dev);
Rafał Miłecki78bc2462011-08-15 18:50:55 +0200750
Rafał Miłeckidc713fb2011-08-15 18:50:56 +0200751 if (dev->phy.radio_ver == 0x2064)
752 b43_radio_2064_init(dev);
753 else
754 B43_WARN_ON(1);
755
Rafał Miłecki1b0a69c2011-09-16 12:34:02 +0200756 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
757 b43_phy_lcn_tx_pwr_ctl_init(dev);
Rafał Miłecki765b07e2011-08-28 19:59:28 +0200758
Rafał Miłeckib5347062011-09-16 12:33:59 +0200759 b43_switch_channel(dev, dev->phy.channel);
760
761 bcma_chipco_regctl_maskset(cc, 0, 0xf, 0x9);
762 bcma_chipco_chipctl_maskset(cc, 0, 0, 0x03cddddd);
763
764 /* TODO */
765
766 b43_phy_set(dev, 0x448, 0x4000);
767 udelay(100);
768 b43_phy_mask(dev, 0x448, ~0x4000);
769
770 /* TODO */
771
Rafał Miłecki78bc2462011-08-15 18:50:55 +0200772 return 0;
773}
774
Rafał Miłeckiba356b52011-08-14 23:27:29 +0200775static void b43_phy_lcn_op_software_rfkill(struct b43_wldev *dev,
776 bool blocked)
777{
778 if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
779 b43err(dev->wl, "MAC not suspended\n");
780
781 if (blocked) {
782 b43_phy_mask(dev, B43_PHY_LCN_RF_CTL2, ~0x7c00);
783 b43_phy_set(dev, B43_PHY_LCN_RF_CTL1, 0x1f00);
784
785 b43_phy_mask(dev, B43_PHY_LCN_RF_CTL5, ~0x7f00);
786 b43_phy_mask(dev, B43_PHY_LCN_RF_CTL4, ~0x2);
787 b43_phy_set(dev, B43_PHY_LCN_RF_CTL3, 0x808);
788
789 b43_phy_mask(dev, B43_PHY_LCN_RF_CTL7, ~0x8);
790 b43_phy_set(dev, B43_PHY_LCN_RF_CTL6, 0x8);
791 } else {
Rafał Miłecki78bc2462011-08-15 18:50:55 +0200792 b43_phy_mask(dev, B43_PHY_LCN_RF_CTL1, ~0x1f00);
793 b43_phy_mask(dev, B43_PHY_LCN_RF_CTL3, ~0x808);
794 b43_phy_mask(dev, B43_PHY_LCN_RF_CTL6, ~0x8);
Rafał Miłeckiba356b52011-08-14 23:27:29 +0200795 }
796}
797
Rafał Miłecki7ed88522011-08-14 23:27:30 +0200798static void b43_phy_lcn_op_switch_analog(struct b43_wldev *dev, bool on)
799{
800 if (on) {
801 b43_phy_mask(dev, B43_PHY_LCN_AFE_CTL1, ~0x7);
802 } else {
803 b43_phy_set(dev, B43_PHY_LCN_AFE_CTL2, 0x7);
804 b43_phy_set(dev, B43_PHY_LCN_AFE_CTL1, 0x7);
805 }
806}
807
Rafał Miłecki39f7d332011-08-28 14:59:58 +0200808static int b43_phy_lcn_op_switch_channel(struct b43_wldev *dev,
809 unsigned int new_channel)
810{
Karl Beldan675a0b02013-03-25 16:26:57 +0100811 struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;
812 enum nl80211_channel_type channel_type =
813 cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef);
Rafał Miłecki39f7d332011-08-28 14:59:58 +0200814
815 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
816 if ((new_channel < 1) || (new_channel > 14))
817 return -EINVAL;
818 } else {
819 return -EINVAL;
820 }
821
822 return b43_phy_lcn_set_channel(dev, channel, channel_type);
823}
824
Rafał Miłeckif9286682011-08-14 23:27:28 +0200825static unsigned int b43_phy_lcn_op_get_default_chan(struct b43_wldev *dev)
826{
827 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
828 return 1;
829 return 36;
830}
831
832static enum b43_txpwr_result
833b43_phy_lcn_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi)
834{
835 return B43_TXPWR_RES_DONE;
836}
837
838static void b43_phy_lcn_op_adjust_txpower(struct b43_wldev *dev)
839{
840}
841
842/**************************************************
Rafał Miłeckif533d0f2011-08-28 14:28:43 +0200843 * R/W ops.
844 **************************************************/
845
846static u16 b43_phy_lcn_op_read(struct b43_wldev *dev, u16 reg)
847{
848 b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
849 return b43_read16(dev, B43_MMIO_PHY_DATA);
850}
851
852static void b43_phy_lcn_op_write(struct b43_wldev *dev, u16 reg, u16 value)
853{
854 b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
855 b43_write16(dev, B43_MMIO_PHY_DATA, value);
856}
857
858static void b43_phy_lcn_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
859 u16 set)
860{
861 b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
862 b43_write16(dev, B43_MMIO_PHY_DATA,
863 (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
864}
865
866static u16 b43_phy_lcn_op_radio_read(struct b43_wldev *dev, u16 reg)
867{
868 /* LCN-PHY needs 0x200 for read access */
869 reg |= 0x200;
870
871 b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
872 return b43_read16(dev, B43_MMIO_RADIO24_DATA);
873}
874
875static void b43_phy_lcn_op_radio_write(struct b43_wldev *dev, u16 reg,
876 u16 value)
877{
878 b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
879 b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
880}
881
882/**************************************************
Rafał Miłecki1d738e62011-07-07 15:25:27 +0200883 * PHY ops struct.
884 **************************************************/
885
886const struct b43_phy_operations b43_phyops_lcn = {
Rafał Miłecki1d738e62011-07-07 15:25:27 +0200887 .allocate = b43_phy_lcn_op_allocate,
888 .free = b43_phy_lcn_op_free,
889 .prepare_structs = b43_phy_lcn_op_prepare_structs,
890 .init = b43_phy_lcn_op_init,
891 .phy_read = b43_phy_lcn_op_read,
892 .phy_write = b43_phy_lcn_op_write,
893 .phy_maskset = b43_phy_lcn_op_maskset,
894 .radio_read = b43_phy_lcn_op_radio_read,
895 .radio_write = b43_phy_lcn_op_radio_write,
896 .software_rfkill = b43_phy_lcn_op_software_rfkill,
897 .switch_analog = b43_phy_lcn_op_switch_analog,
898 .switch_channel = b43_phy_lcn_op_switch_channel,
899 .get_default_chan = b43_phy_lcn_op_get_default_chan,
900 .recalc_txpower = b43_phy_lcn_op_recalc_txpower,
901 .adjust_txpower = b43_phy_lcn_op_adjust_txpower,
Rafał Miłecki1d738e62011-07-07 15:25:27 +0200902};