2 * Copyright (c) 2010 Atheros Communications Inc.
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include "ar9003_phy.h"
19 #include "ar9003_eeprom.h"
21 #define COMP_HDR_LEN 4
22 #define COMP_CKSUM_LEN 2
24 #define AR_CH0_TOP (0x00016288)
25 #define AR_CH0_TOP_XPABIASLVL (0x3)
26 #define AR_CH0_TOP_XPABIASLVL_S (8)
28 #define AR_CH0_THERM (0x00016290)
29 #define AR_CH0_THERM_SPARE (0x3f)
30 #define AR_CH0_THERM_SPARE_S (0)
32 #define AR_SWITCH_TABLE_COM_ALL (0xffff)
33 #define AR_SWITCH_TABLE_COM_ALL_S (0)
35 #define AR_SWITCH_TABLE_COM2_ALL (0xffffff)
36 #define AR_SWITCH_TABLE_COM2_ALL_S (0)
38 #define AR_SWITCH_TABLE_ALL (0xfff)
39 #define AR_SWITCH_TABLE_ALL_S (0)
41 #define LE16(x) __constant_cpu_to_le16(x)
42 #define LE32(x) __constant_cpu_to_le32(x)
44 static const struct ar9300_eeprom ar9300_default
= {
47 .macAddr
= {1, 2, 3, 4, 5, 6},
48 .custData
= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
49 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
51 .regDmn
= { LE16(0), LE16(0x1f) },
52 .txrxMask
= 0x77, /* 4 bits tx and 4 bits rx */
54 .opFlags
= AR9300_OPFLAGS_11G
| AR9300_OPFLAGS_11A
,
58 .blueToothOptions
= 0,
60 .deviceType
= 5, /* takes lower byte in eeprom location */
61 .pwrTableOffset
= AR9300_PWR_TABLE_OFFSET
,
62 .params_for_tuning_caps
= {0, 0},
63 .featureEnable
= 0x0c,
65 * bit0 - enable tx temp comp - disabled
66 * bit1 - enable tx volt comp - disabled
67 * bit2 - enable fastClock - enabled
68 * bit3 - enable doubling - enabled
69 * bit4 - enable internal regulator - disabled
71 .miscConfiguration
= 0, /* bit0 - turn down drivestrength */
72 .eepromWriteEnableGpio
= 3,
75 .rxBandSelectGpio
= 0xff,
80 /* ar9300_modal_eep_header 2g */
81 /* 4 idle,t1,t2,b(4 bits per setting) */
82 .antCtrlCommon
= LE32(0x110),
83 /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
84 .antCtrlCommon2
= LE32(0x22222),
87 * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
88 * rx1, rx12, b (2 bits each)
90 .antCtrlChain
= { LE16(0x150), LE16(0x150), LE16(0x150) },
93 * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db
94 * for ar9280 (0xa20c/b20c 5:0)
96 .xatten1DB
= {0, 0, 0},
99 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
100 * for ar9280 (0xa20c/b20c 16:12
102 .xatten1Margin
= {0, 0, 0},
107 * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
108 * channels in usual fbin coding format
110 .spurChans
= {0, 0, 0, 0, 0},
113 * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
114 * if the register is per chain
116 .noiseFloorThreshCh
= {-1, 0, 0},
117 .ob
= {1, 1, 1},/* 3 chain */
118 .db_stage2
= {1, 1, 1}, /* 3 chain */
119 .db_stage3
= {0, 0, 0},
120 .db_stage4
= {0, 0, 0},
122 .txFrameToDataStart
= 0x0e,
123 .txFrameToPaOn
= 0x0e,
124 .txClip
= 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
126 .switchSettling
= 0x2c,
127 .adcDesiredSize
= -30,
130 .txFrameToXpaOn
= 0xe,
132 .futureModal
= { /* [32] */
133 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
142 /* ar9300_cal_data_per_freq_op_loop 2g */
144 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
145 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
146 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
148 .calTarget_freqbin_Cck
= {
152 .calTarget_freqbin_2G
= {
157 .calTarget_freqbin_2GHT20
= {
162 .calTarget_freqbin_2GHT40
= {
167 .calTargetPowerCck
= {
168 /* 1L-5L,5S,11L,11S */
169 { {36, 36, 36, 36} },
170 { {36, 36, 36, 36} },
172 .calTargetPower2G
= {
174 { {32, 32, 28, 24} },
175 { {32, 32, 28, 24} },
176 { {32, 32, 28, 24} },
178 .calTargetPower2GHT20
= {
179 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
180 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
181 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
183 .calTargetPower2GHT40
= {
184 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
185 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
186 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
189 0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
190 0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
220 /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
221 /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
222 /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
223 /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
227 /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
228 /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
229 /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
234 /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
235 /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
241 /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
242 /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
243 /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
244 /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
248 /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
249 /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
250 /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
254 /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
255 /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
256 /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
261 /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
262 /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
263 /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
268 /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
269 /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
270 /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
271 /* Data[11].ctlEdges[3].bChannel */
276 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
277 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
278 { { {60, 1}, {60, 0}, {60, 0}, {60, 1} } },
280 { { {60, 1}, {60, 0}, {0, 0}, {0, 0} } },
281 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
282 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
284 { { {60, 0}, {60, 1}, {60, 1}, {60, 0} } },
285 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
286 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
288 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
289 { { {60, 0}, {60, 1}, {60, 1}, {60, 1} } },
292 /* 4 idle,t1,t2,b (4 bits per setting) */
293 .antCtrlCommon
= LE32(0x110),
294 /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
295 .antCtrlCommon2
= LE32(0x22222),
296 /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
298 LE16(0x000), LE16(0x000), LE16(0x000),
300 /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
301 .xatten1DB
= {0, 0, 0},
304 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
305 * for merlin (0xa20c/b20c 16:12
307 .xatten1Margin
= {0, 0, 0},
310 /* spurChans spur channels in usual fbin coding format */
311 .spurChans
= {0, 0, 0, 0, 0},
312 /* noiseFloorThreshCh Check if the register is per chain */
313 .noiseFloorThreshCh
= {-1, 0, 0},
314 .ob
= {3, 3, 3}, /* 3 chain */
315 .db_stage2
= {3, 3, 3}, /* 3 chain */
316 .db_stage3
= {3, 3, 3}, /* doesn't exist for 2G */
317 .db_stage4
= {3, 3, 3}, /* don't exist for 2G */
319 .txFrameToDataStart
= 0x0e,
320 .txFrameToPaOn
= 0x0e,
321 .txClip
= 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
323 .switchSettling
= 0x2d,
324 .adcDesiredSize
= -30,
327 .txFrameToXpaOn
= 0xe,
330 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
331 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
377 .calTarget_freqbin_5G
= {
387 .calTarget_freqbin_5GHT20
= {
397 .calTarget_freqbin_5GHT40
= {
407 .calTargetPower5G
= {
409 { {20, 20, 20, 10} },
410 { {20, 20, 20, 10} },
411 { {20, 20, 20, 10} },
412 { {20, 20, 20, 10} },
413 { {20, 20, 20, 10} },
414 { {20, 20, 20, 10} },
415 { {20, 20, 20, 10} },
416 { {20, 20, 20, 10} },
418 .calTargetPower5GHT20
= {
420 * 0_8_16,1-3_9-11_17-19,
421 * 4,5,6,7,12,13,14,15,20,21,22,23
423 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
424 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
425 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
426 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
427 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
428 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
429 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
430 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
432 .calTargetPower5GHT40
= {
434 * 0_8_16,1-3_9-11_17-19,
435 * 4,5,6,7,12,13,14,15,20,21,22,23
437 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
438 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
439 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
440 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
441 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
442 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
443 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
444 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
447 0x10, 0x16, 0x18, 0x40, 0x46,
448 0x48, 0x30, 0x36, 0x38
452 /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
453 /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
454 /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
455 /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
456 /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
457 /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
458 /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
459 /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
462 /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
463 /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
464 /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
465 /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
466 /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
467 /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
468 /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
469 /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
473 /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
474 /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
475 /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
476 /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
477 /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
478 /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
479 /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
480 /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
484 /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
485 /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
486 /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
487 /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
488 /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
489 /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
490 /* Data[3].ctlEdges[6].bChannel */ 0xFF,
491 /* Data[3].ctlEdges[7].bChannel */ 0xFF,
495 /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
496 /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
497 /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
498 /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
499 /* Data[4].ctlEdges[4].bChannel */ 0xFF,
500 /* Data[4].ctlEdges[5].bChannel */ 0xFF,
501 /* Data[4].ctlEdges[6].bChannel */ 0xFF,
502 /* Data[4].ctlEdges[7].bChannel */ 0xFF,
506 /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
507 /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
508 /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
509 /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
510 /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
511 /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
512 /* Data[5].ctlEdges[6].bChannel */ 0xFF,
513 /* Data[5].ctlEdges[7].bChannel */ 0xFF
517 /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
518 /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
519 /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
520 /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
521 /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
522 /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
523 /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
524 /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
528 /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
529 /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
530 /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
531 /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
532 /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
533 /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
534 /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
535 /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
539 /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
540 /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
541 /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
542 /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
543 /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
544 /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
545 /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
546 /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
552 {60, 1}, {60, 1}, {60, 1}, {60, 1},
553 {60, 1}, {60, 1}, {60, 1}, {60, 0},
558 {60, 1}, {60, 1}, {60, 1}, {60, 1},
559 {60, 1}, {60, 1}, {60, 1}, {60, 0},
564 {60, 0}, {60, 1}, {60, 0}, {60, 1},
565 {60, 1}, {60, 1}, {60, 1}, {60, 1},
570 {60, 0}, {60, 1}, {60, 1}, {60, 0},
571 {60, 1}, {60, 0}, {60, 0}, {60, 0},
576 {60, 1}, {60, 1}, {60, 1}, {60, 0},
577 {60, 0}, {60, 0}, {60, 0}, {60, 0},
582 {60, 1}, {60, 1}, {60, 1}, {60, 1},
583 {60, 1}, {60, 0}, {60, 0}, {60, 0},
588 {60, 1}, {60, 1}, {60, 1}, {60, 1},
589 {60, 1}, {60, 1}, {60, 1}, {60, 1},
594 {60, 1}, {60, 1}, {60, 0}, {60, 1},
595 {60, 1}, {60, 1}, {60, 1}, {60, 0},
600 {60, 1}, {60, 0}, {60, 1}, {60, 1},
601 {60, 1}, {60, 1}, {60, 0}, {60, 1},
607 static int ath9k_hw_ar9300_check_eeprom(struct ath_hw
*ah
)
612 static u32
ath9k_hw_ar9300_get_eeprom(struct ath_hw
*ah
,
613 enum eeprom_param param
)
615 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
616 struct ar9300_base_eep_hdr
*pBase
= &eep
->baseEepHeader
;
620 return eep
->macAddr
[0] << 8 | eep
->macAddr
[1];
622 return eep
->macAddr
[2] << 8 | eep
->macAddr
[3];
624 return eep
->macAddr
[4] << 8 | eep
->macAddr
[5];
626 return le16_to_cpu(pBase
->regDmn
[0]);
628 return le16_to_cpu(pBase
->regDmn
[1]);
630 return pBase
->deviceCap
;
632 return pBase
->opCapFlags
.opFlags
;
634 return pBase
->rfSilent
;
636 return (pBase
->txrxMask
>> 4) & 0xf;
638 return pBase
->txrxMask
& 0xf;
639 case EEP_DRIVE_STRENGTH
:
640 #define AR9300_EEP_BASE_DRIV_STRENGTH 0x1
641 return pBase
->miscConfiguration
& AR9300_EEP_BASE_DRIV_STRENGTH
;
642 case EEP_INTERNAL_REGULATOR
:
643 /* Bit 4 is internal regulator flag */
644 return (pBase
->featureEnable
& 0x10) >> 4;
646 return le32_to_cpu(pBase
->swreg
);
652 static bool ar9300_eeprom_read_byte(struct ath_common
*common
, int address
,
657 if (unlikely(!ath9k_hw_nvram_read(common
, address
/ 2, &val
)))
660 *buffer
= (val
>> (8 * (address
% 2))) & 0xff;
664 static bool ar9300_eeprom_read_word(struct ath_common
*common
, int address
,
669 if (unlikely(!ath9k_hw_nvram_read(common
, address
/ 2, &val
)))
672 buffer
[0] = val
>> 8;
673 buffer
[1] = val
& 0xff;
678 static bool ar9300_read_eeprom(struct ath_hw
*ah
, int address
, u8
*buffer
,
681 struct ath_common
*common
= ath9k_hw_common(ah
);
684 if ((address
< 0) || ((address
+ count
) / 2 > AR9300_EEPROM_SIZE
- 1)) {
685 ath_print(common
, ATH_DBG_EEPROM
,
686 "eeprom address not in range\n");
691 * Since we're reading the bytes in reverse order from a little-endian
692 * word stream, an even address means we only use the lower half of
693 * the 16-bit word at that address
695 if (address
% 2 == 0) {
696 if (!ar9300_eeprom_read_byte(common
, address
--, buffer
++))
702 for (i
= 0; i
< count
/ 2; i
++) {
703 if (!ar9300_eeprom_read_word(common
, address
, buffer
))
711 if (!ar9300_eeprom_read_byte(common
, address
, buffer
))
717 ath_print(common
, ATH_DBG_EEPROM
,
718 "unable to read eeprom region at offset %d\n", address
);
722 static void ar9300_comp_hdr_unpack(u8
*best
, int *code
, int *reference
,
723 int *length
, int *major
, int *minor
)
725 unsigned long value
[4];
731 *code
= ((value
[0] >> 5) & 0x0007);
732 *reference
= (value
[0] & 0x001f) | ((value
[1] >> 2) & 0x0020);
733 *length
= ((value
[1] << 4) & 0x07f0) | ((value
[2] >> 4) & 0x000f);
734 *major
= (value
[2] & 0x000f);
735 *minor
= (value
[3] & 0x00ff);
738 static u16
ar9300_comp_cksum(u8
*data
, int dsize
)
740 int it
, checksum
= 0;
742 for (it
= 0; it
< dsize
; it
++) {
743 checksum
+= data
[it
];
750 static bool ar9300_uncompress_block(struct ath_hw
*ah
,
760 struct ath_common
*common
= ath9k_hw_common(ah
);
764 for (it
= 0; it
< size
; it
+= (length
+2)) {
768 length
= block
[it
+1];
771 if (length
> 0 && spot
>= 0 && spot
+length
< mdataSize
) {
772 ath_print(common
, ATH_DBG_EEPROM
,
773 "Restore at %d: spot=%d "
774 "offset=%d length=%d\n",
775 it
, spot
, offset
, length
);
776 memcpy(&mptr
[spot
], &block
[it
+2], length
);
778 } else if (length
> 0) {
779 ath_print(common
, ATH_DBG_EEPROM
,
780 "Bad restore at %d: spot=%d "
781 "offset=%d length=%d\n",
782 it
, spot
, offset
, length
);
789 static int ar9300_compress_decision(struct ath_hw
*ah
,
794 u8
*word
, int length
, int mdata_size
)
796 struct ath_common
*common
= ath9k_hw_common(ah
);
801 if (length
!= mdata_size
) {
802 ath_print(common
, ATH_DBG_EEPROM
,
803 "EEPROM structure size mismatch"
804 "memory=%d eeprom=%d\n", mdata_size
, length
);
807 memcpy(mptr
, (u8
*) (word
+ COMP_HDR_LEN
), length
);
808 ath_print(common
, ATH_DBG_EEPROM
, "restored eeprom %d:"
809 " uncompressed, length %d\n", it
, length
);
812 if (reference
== 0) {
815 if (reference
!= 2) {
816 ath_print(common
, ATH_DBG_EEPROM
,
817 "cant find reference eeprom"
818 "struct %d\n", reference
);
821 memcpy(mptr
, &ar9300_default
, mdata_size
);
823 ath_print(common
, ATH_DBG_EEPROM
,
824 "restore eeprom %d: block, reference %d,"
825 " length %d\n", it
, reference
, length
);
826 ar9300_uncompress_block(ah
, mptr
, mdata_size
,
827 (u8
*) (word
+ COMP_HDR_LEN
), length
);
830 ath_print(common
, ATH_DBG_EEPROM
, "unknown compression"
838 * Read the configuration data from the eeprom.
839 * The data can be put in any specified memory buffer.
841 * Returns -1 on error.
842 * Returns address of next memory location on success.
844 static int ar9300_eeprom_restore_internal(struct ath_hw
*ah
,
845 u8
*mptr
, int mdata_size
)
852 int reference
, length
, major
, minor
;
855 u16 checksum
, mchecksum
;
856 struct ath_common
*common
= ath9k_hw_common(ah
);
858 word
= kzalloc(2048, GFP_KERNEL
);
862 memcpy(mptr
, &ar9300_default
, mdata_size
);
864 cptr
= AR9300_BASE_ADDR
;
865 for (it
= 0; it
< MSTATE
; it
++) {
866 if (!ar9300_read_eeprom(ah
, cptr
, word
, COMP_HDR_LEN
))
869 if ((word
[0] == 0 && word
[1] == 0 && word
[2] == 0 &&
870 word
[3] == 0) || (word
[0] == 0xff && word
[1] == 0xff
871 && word
[2] == 0xff && word
[3] == 0xff))
874 ar9300_comp_hdr_unpack(word
, &code
, &reference
,
875 &length
, &major
, &minor
);
876 ath_print(common
, ATH_DBG_EEPROM
,
877 "Found block at %x: code=%d ref=%d"
878 "length=%d major=%d minor=%d\n", cptr
, code
,
879 reference
, length
, major
, minor
);
880 if (length
>= 1024) {
881 ath_print(common
, ATH_DBG_EEPROM
,
882 "Skipping bad header\n");
883 cptr
-= COMP_HDR_LEN
;
888 ar9300_read_eeprom(ah
, cptr
, word
,
889 COMP_HDR_LEN
+ osize
+ COMP_CKSUM_LEN
);
890 checksum
= ar9300_comp_cksum(&word
[COMP_HDR_LEN
], length
);
891 mchecksum
= word
[COMP_HDR_LEN
+ osize
] |
892 (word
[COMP_HDR_LEN
+ osize
+ 1] << 8);
893 ath_print(common
, ATH_DBG_EEPROM
,
894 "checksum %x %x\n", checksum
, mchecksum
);
895 if (checksum
== mchecksum
) {
896 ar9300_compress_decision(ah
, it
, code
, reference
, mptr
,
897 word
, length
, mdata_size
);
899 ath_print(common
, ATH_DBG_EEPROM
,
900 "skipping block with bad checksum\n");
902 cptr
-= (COMP_HDR_LEN
+ osize
+ COMP_CKSUM_LEN
);
914 * Restore the configuration structure by reading the eeprom.
915 * This function destroys any existing in-memory structure
918 static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw
*ah
)
920 u8
*mptr
= (u8
*) &ah
->eeprom
.ar9300_eep
;
922 if (ar9300_eeprom_restore_internal(ah
, mptr
,
923 sizeof(struct ar9300_eeprom
)) < 0)
929 /* XXX: review hardware docs */
930 static int ath9k_hw_ar9300_get_eeprom_ver(struct ath_hw
*ah
)
932 return ah
->eeprom
.ar9300_eep
.eepromVersion
;
935 /* XXX: could be read from the eepromVersion, not sure yet */
936 static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw
*ah
)
941 static u8
ath9k_hw_ar9300_get_num_ant_config(struct ath_hw
*ah
,
942 enum ieee80211_band freq_band
)
947 static u16
ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw
*ah
,
948 struct ath9k_channel
*chan
)
953 static s32
ar9003_hw_xpa_bias_level_get(struct ath_hw
*ah
, bool is2ghz
)
955 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
958 return eep
->modalHeader2G
.xpaBiasLvl
;
960 return eep
->modalHeader5G
.xpaBiasLvl
;
963 static void ar9003_hw_xpa_bias_level_apply(struct ath_hw
*ah
, bool is2ghz
)
965 int bias
= ar9003_hw_xpa_bias_level_get(ah
, is2ghz
);
966 REG_RMW_FIELD(ah
, AR_CH0_TOP
, AR_CH0_TOP_XPABIASLVL
, (bias
& 0x3));
967 REG_RMW_FIELD(ah
, AR_CH0_THERM
, AR_CH0_THERM_SPARE
,
968 ((bias
>> 2) & 0x3));
971 static u32
ar9003_hw_ant_ctrl_common_get(struct ath_hw
*ah
, bool is2ghz
)
973 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
977 val
= eep
->modalHeader2G
.antCtrlCommon
;
979 val
= eep
->modalHeader5G
.antCtrlCommon
;
980 return le32_to_cpu(val
);
983 static u32
ar9003_hw_ant_ctrl_common_2_get(struct ath_hw
*ah
, bool is2ghz
)
985 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
989 val
= eep
->modalHeader2G
.antCtrlCommon2
;
991 val
= eep
->modalHeader5G
.antCtrlCommon2
;
992 return le32_to_cpu(val
);
995 static u16
ar9003_hw_ant_ctrl_chain_get(struct ath_hw
*ah
,
999 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1002 if (chain
>= 0 && chain
< AR9300_MAX_CHAINS
) {
1004 val
= eep
->modalHeader2G
.antCtrlChain
[chain
];
1006 val
= eep
->modalHeader5G
.antCtrlChain
[chain
];
1009 return le16_to_cpu(val
);
1012 static void ar9003_hw_ant_ctrl_apply(struct ath_hw
*ah
, bool is2ghz
)
1014 u32 value
= ar9003_hw_ant_ctrl_common_get(ah
, is2ghz
);
1015 REG_RMW_FIELD(ah
, AR_PHY_SWITCH_COM
, AR_SWITCH_TABLE_COM_ALL
, value
);
1017 value
= ar9003_hw_ant_ctrl_common_2_get(ah
, is2ghz
);
1018 REG_RMW_FIELD(ah
, AR_PHY_SWITCH_COM_2
, AR_SWITCH_TABLE_COM2_ALL
, value
);
1020 value
= ar9003_hw_ant_ctrl_chain_get(ah
, 0, is2ghz
);
1021 REG_RMW_FIELD(ah
, AR_PHY_SWITCH_CHAIN_0
, AR_SWITCH_TABLE_ALL
, value
);
1023 value
= ar9003_hw_ant_ctrl_chain_get(ah
, 1, is2ghz
);
1024 REG_RMW_FIELD(ah
, AR_PHY_SWITCH_CHAIN_1
, AR_SWITCH_TABLE_ALL
, value
);
1026 value
= ar9003_hw_ant_ctrl_chain_get(ah
, 2, is2ghz
);
1027 REG_RMW_FIELD(ah
, AR_PHY_SWITCH_CHAIN_2
, AR_SWITCH_TABLE_ALL
, value
);
1030 static void ar9003_hw_drive_strength_apply(struct ath_hw
*ah
)
1035 drive_strength
= ath9k_hw_ar9300_get_eeprom(ah
, EEP_DRIVE_STRENGTH
);
1037 if (!drive_strength
)
1040 reg
= REG_READ(ah
, AR_PHY_65NM_CH0_BIAS1
);
1048 REG_WRITE(ah
, AR_PHY_65NM_CH0_BIAS1
, reg
);
1050 reg
= REG_READ(ah
, AR_PHY_65NM_CH0_BIAS2
);
1061 REG_WRITE(ah
, AR_PHY_65NM_CH0_BIAS2
, reg
);
1063 reg
= REG_READ(ah
, AR_PHY_65NM_CH0_BIAS4
);
1068 REG_WRITE(ah
, AR_PHY_65NM_CH0_BIAS4
, reg
);
1071 static void ar9003_hw_internal_regulator_apply(struct ath_hw
*ah
)
1073 int internal_regulator
=
1074 ath9k_hw_ar9300_get_eeprom(ah
, EEP_INTERNAL_REGULATOR
);
1076 if (internal_regulator
) {
1077 /* Internal regulator is ON. Write swreg register. */
1078 int swreg
= ath9k_hw_ar9300_get_eeprom(ah
, EEP_SWREG
);
1079 REG_WRITE(ah
, AR_RTC_REG_CONTROL1
,
1080 REG_READ(ah
, AR_RTC_REG_CONTROL1
) &
1081 (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM
));
1082 REG_WRITE(ah
, AR_RTC_REG_CONTROL0
, swreg
);
1083 /* Set REG_CONTROL1.SWREG_PROGRAM */
1084 REG_WRITE(ah
, AR_RTC_REG_CONTROL1
,
1086 AR_RTC_REG_CONTROL1
) |
1087 AR_RTC_REG_CONTROL1_SWREG_PROGRAM
);
1089 REG_WRITE(ah
, AR_RTC_SLEEP_CLK
,
1092 AR_RTC_FORCE_SWREG_PRD
));
1096 static void ath9k_hw_ar9300_set_board_values(struct ath_hw
*ah
,
1097 struct ath9k_channel
*chan
)
1099 ar9003_hw_xpa_bias_level_apply(ah
, IS_CHAN_2GHZ(chan
));
1100 ar9003_hw_ant_ctrl_apply(ah
, IS_CHAN_2GHZ(chan
));
1101 ar9003_hw_drive_strength_apply(ah
);
1102 ar9003_hw_internal_regulator_apply(ah
);
1105 static void ath9k_hw_ar9300_set_addac(struct ath_hw
*ah
,
1106 struct ath9k_channel
*chan
)
1111 * Returns the interpolated y value corresponding to the specified x value
1112 * from the np ordered pairs of data (px,py).
1113 * The pairs do not have to be in any order.
1114 * If the specified x value is less than any of the px,
1115 * the returned y value is equal to the py for the lowest px.
1116 * If the specified x value is greater than any of the px,
1117 * the returned y value is equal to the py for the highest px.
1119 static int ar9003_hw_power_interpolate(int32_t x
,
1120 int32_t *px
, int32_t *py
, u_int16_t np
)
1123 int lx
= 0, ly
= 0, lhave
= 0;
1124 int hx
= 0, hy
= 0, hhave
= 0;
1131 /* identify best lower and higher x calibration measurement */
1132 for (ip
= 0; ip
< np
; ip
++) {
1135 /* this measurement is higher than our desired x */
1137 if (!hhave
|| dx
> (x
- hx
)) {
1138 /* new best higher x measurement */
1144 /* this measurement is lower than our desired x */
1146 if (!lhave
|| dx
< (x
- lx
)) {
1147 /* new best lower x measurement */
1155 /* the low x is good */
1157 /* so is the high x */
1159 /* they're the same, so just pick one */
1162 else /* interpolate */
1163 y
= ly
+ (((x
- lx
) * (hy
- ly
)) / (hx
- lx
));
1164 } else /* only low is good, use it */
1166 } else if (hhave
) /* only high is good, use it */
1168 else /* nothing is good,this should never happen unless np=0, ???? */
1173 static u8
ar9003_hw_eeprom_get_tgt_pwr(struct ath_hw
*ah
,
1174 u16 rateIndex
, u16 freq
, bool is2GHz
)
1177 s32 targetPowerArray
[AR9300_NUM_5G_20_TARGET_POWERS
];
1178 s32 freqArray
[AR9300_NUM_5G_20_TARGET_POWERS
];
1179 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1180 struct cal_tgt_pow_legacy
*pEepromTargetPwr
;
1184 numPiers
= AR9300_NUM_2G_20_TARGET_POWERS
;
1185 pEepromTargetPwr
= eep
->calTargetPower2G
;
1186 pFreqBin
= eep
->calTarget_freqbin_2G
;
1188 numPiers
= AR9300_NUM_5G_20_TARGET_POWERS
;
1189 pEepromTargetPwr
= eep
->calTargetPower5G
;
1190 pFreqBin
= eep
->calTarget_freqbin_5G
;
1194 * create array of channels and targetpower from
1195 * targetpower piers stored on eeprom
1197 for (i
= 0; i
< numPiers
; i
++) {
1198 freqArray
[i
] = FBIN2FREQ(pFreqBin
[i
], is2GHz
);
1199 targetPowerArray
[i
] = pEepromTargetPwr
[i
].tPow2x
[rateIndex
];
1202 /* interpolate to get target power for given frequency */
1203 return (u8
) ar9003_hw_power_interpolate((s32
) freq
,
1205 targetPowerArray
, numPiers
);
1208 static u8
ar9003_hw_eeprom_get_ht20_tgt_pwr(struct ath_hw
*ah
,
1210 u16 freq
, bool is2GHz
)
1213 s32 targetPowerArray
[AR9300_NUM_5G_20_TARGET_POWERS
];
1214 s32 freqArray
[AR9300_NUM_5G_20_TARGET_POWERS
];
1215 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1216 struct cal_tgt_pow_ht
*pEepromTargetPwr
;
1220 numPiers
= AR9300_NUM_2G_20_TARGET_POWERS
;
1221 pEepromTargetPwr
= eep
->calTargetPower2GHT20
;
1222 pFreqBin
= eep
->calTarget_freqbin_2GHT20
;
1224 numPiers
= AR9300_NUM_5G_20_TARGET_POWERS
;
1225 pEepromTargetPwr
= eep
->calTargetPower5GHT20
;
1226 pFreqBin
= eep
->calTarget_freqbin_5GHT20
;
1230 * create array of channels and targetpower
1231 * from targetpower piers stored on eeprom
1233 for (i
= 0; i
< numPiers
; i
++) {
1234 freqArray
[i
] = FBIN2FREQ(pFreqBin
[i
], is2GHz
);
1235 targetPowerArray
[i
] = pEepromTargetPwr
[i
].tPow2x
[rateIndex
];
1238 /* interpolate to get target power for given frequency */
1239 return (u8
) ar9003_hw_power_interpolate((s32
) freq
,
1241 targetPowerArray
, numPiers
);
1244 static u8
ar9003_hw_eeprom_get_ht40_tgt_pwr(struct ath_hw
*ah
,
1246 u16 freq
, bool is2GHz
)
1249 s32 targetPowerArray
[AR9300_NUM_5G_40_TARGET_POWERS
];
1250 s32 freqArray
[AR9300_NUM_5G_40_TARGET_POWERS
];
1251 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1252 struct cal_tgt_pow_ht
*pEepromTargetPwr
;
1256 numPiers
= AR9300_NUM_2G_40_TARGET_POWERS
;
1257 pEepromTargetPwr
= eep
->calTargetPower2GHT40
;
1258 pFreqBin
= eep
->calTarget_freqbin_2GHT40
;
1260 numPiers
= AR9300_NUM_5G_40_TARGET_POWERS
;
1261 pEepromTargetPwr
= eep
->calTargetPower5GHT40
;
1262 pFreqBin
= eep
->calTarget_freqbin_5GHT40
;
1266 * create array of channels and targetpower from
1267 * targetpower piers stored on eeprom
1269 for (i
= 0; i
< numPiers
; i
++) {
1270 freqArray
[i
] = FBIN2FREQ(pFreqBin
[i
], is2GHz
);
1271 targetPowerArray
[i
] = pEepromTargetPwr
[i
].tPow2x
[rateIndex
];
1274 /* interpolate to get target power for given frequency */
1275 return (u8
) ar9003_hw_power_interpolate((s32
) freq
,
1277 targetPowerArray
, numPiers
);
1280 static u8
ar9003_hw_eeprom_get_cck_tgt_pwr(struct ath_hw
*ah
,
1281 u16 rateIndex
, u16 freq
)
1283 u16 numPiers
= AR9300_NUM_2G_CCK_TARGET_POWERS
, i
;
1284 s32 targetPowerArray
[AR9300_NUM_2G_CCK_TARGET_POWERS
];
1285 s32 freqArray
[AR9300_NUM_2G_CCK_TARGET_POWERS
];
1286 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1287 struct cal_tgt_pow_legacy
*pEepromTargetPwr
= eep
->calTargetPowerCck
;
1288 u8
*pFreqBin
= eep
->calTarget_freqbin_Cck
;
1291 * create array of channels and targetpower from
1292 * targetpower piers stored on eeprom
1294 for (i
= 0; i
< numPiers
; i
++) {
1295 freqArray
[i
] = FBIN2FREQ(pFreqBin
[i
], 1);
1296 targetPowerArray
[i
] = pEepromTargetPwr
[i
].tPow2x
[rateIndex
];
1299 /* interpolate to get target power for given frequency */
1300 return (u8
) ar9003_hw_power_interpolate((s32
) freq
,
1302 targetPowerArray
, numPiers
);
1305 /* Set tx power registers to array of values passed in */
1306 static int ar9003_hw_tx_power_regwrite(struct ath_hw
*ah
, u8
* pPwrArray
)
1308 #define POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
1309 /* make sure forced gain is not set */
1310 REG_WRITE(ah
, 0xa458, 0);
1312 /* Write the OFDM power per rate set */
1314 /* 6 (LSB), 9, 12, 18 (MSB) */
1315 REG_WRITE(ah
, 0xa3c0,
1316 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_6_24
], 24) |
1317 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_6_24
], 16) |
1318 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_6_24
], 8) |
1319 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_6_24
], 0));
1321 /* 24 (LSB), 36, 48, 54 (MSB) */
1322 REG_WRITE(ah
, 0xa3c4,
1323 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_54
], 24) |
1324 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_48
], 16) |
1325 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_36
], 8) |
1326 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_6_24
], 0));
1328 /* Write the CCK power per rate set */
1330 /* 1L (LSB), reserved, 2L, 2S (MSB) */
1331 REG_WRITE(ah
, 0xa3c8,
1332 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_1L_5L
], 24) |
1333 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_1L_5L
], 16) |
1334 /* POW_SM(txPowerTimes2, 8) | this is reserved for AR9003 */
1335 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_1L_5L
], 0));
1337 /* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */
1338 REG_WRITE(ah
, 0xa3cc,
1339 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_11S
], 24) |
1340 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_11L
], 16) |
1341 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_5S
], 8) |
1342 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_1L_5L
], 0)
1345 /* Write the HT20 power per rate set */
1347 /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */
1348 REG_WRITE(ah
, 0xa3d0,
1349 POW_SM(pPwrArray
[ALL_TARGET_HT20_5
], 24) |
1350 POW_SM(pPwrArray
[ALL_TARGET_HT20_4
], 16) |
1351 POW_SM(pPwrArray
[ALL_TARGET_HT20_1_3_9_11_17_19
], 8) |
1352 POW_SM(pPwrArray
[ALL_TARGET_HT20_0_8_16
], 0)
1355 /* 6 (LSB), 7, 12, 13 (MSB) */
1356 REG_WRITE(ah
, 0xa3d4,
1357 POW_SM(pPwrArray
[ALL_TARGET_HT20_13
], 24) |
1358 POW_SM(pPwrArray
[ALL_TARGET_HT20_12
], 16) |
1359 POW_SM(pPwrArray
[ALL_TARGET_HT20_7
], 8) |
1360 POW_SM(pPwrArray
[ALL_TARGET_HT20_6
], 0)
1363 /* 14 (LSB), 15, 20, 21 */
1364 REG_WRITE(ah
, 0xa3e4,
1365 POW_SM(pPwrArray
[ALL_TARGET_HT20_21
], 24) |
1366 POW_SM(pPwrArray
[ALL_TARGET_HT20_20
], 16) |
1367 POW_SM(pPwrArray
[ALL_TARGET_HT20_15
], 8) |
1368 POW_SM(pPwrArray
[ALL_TARGET_HT20_14
], 0)
1371 /* Mixed HT20 and HT40 rates */
1373 /* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */
1374 REG_WRITE(ah
, 0xa3e8,
1375 POW_SM(pPwrArray
[ALL_TARGET_HT40_23
], 24) |
1376 POW_SM(pPwrArray
[ALL_TARGET_HT40_22
], 16) |
1377 POW_SM(pPwrArray
[ALL_TARGET_HT20_23
], 8) |
1378 POW_SM(pPwrArray
[ALL_TARGET_HT20_22
], 0)
1382 * Write the HT40 power per rate set
1383 * correct PAR difference between HT40 and HT20/LEGACY
1384 * 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB)
1386 REG_WRITE(ah
, 0xa3d8,
1387 POW_SM(pPwrArray
[ALL_TARGET_HT40_5
], 24) |
1388 POW_SM(pPwrArray
[ALL_TARGET_HT40_4
], 16) |
1389 POW_SM(pPwrArray
[ALL_TARGET_HT40_1_3_9_11_17_19
], 8) |
1390 POW_SM(pPwrArray
[ALL_TARGET_HT40_0_8_16
], 0)
1393 /* 6 (LSB), 7, 12, 13 (MSB) */
1394 REG_WRITE(ah
, 0xa3dc,
1395 POW_SM(pPwrArray
[ALL_TARGET_HT40_13
], 24) |
1396 POW_SM(pPwrArray
[ALL_TARGET_HT40_12
], 16) |
1397 POW_SM(pPwrArray
[ALL_TARGET_HT40_7
], 8) |
1398 POW_SM(pPwrArray
[ALL_TARGET_HT40_6
], 0)
1401 /* 14 (LSB), 15, 20, 21 */
1402 REG_WRITE(ah
, 0xa3ec,
1403 POW_SM(pPwrArray
[ALL_TARGET_HT40_21
], 24) |
1404 POW_SM(pPwrArray
[ALL_TARGET_HT40_20
], 16) |
1405 POW_SM(pPwrArray
[ALL_TARGET_HT40_15
], 8) |
1406 POW_SM(pPwrArray
[ALL_TARGET_HT40_14
], 0)
1413 static void ar9003_hw_set_target_power_eeprom(struct ath_hw
*ah
, u16 freq
)
1415 u8 targetPowerValT2
[ar9300RateSize
];
1416 /* XXX: hard code for now, need to get from eeprom struct */
1417 u8 ht40PowerIncForPdadc
= 0;
1418 bool is2GHz
= false;
1420 struct ath_common
*common
= ath9k_hw_common(ah
);
1425 targetPowerValT2
[ALL_TARGET_LEGACY_6_24
] =
1426 ar9003_hw_eeprom_get_tgt_pwr(ah
, LEGACY_TARGET_RATE_6_24
, freq
,
1428 targetPowerValT2
[ALL_TARGET_LEGACY_36
] =
1429 ar9003_hw_eeprom_get_tgt_pwr(ah
, LEGACY_TARGET_RATE_36
, freq
,
1431 targetPowerValT2
[ALL_TARGET_LEGACY_48
] =
1432 ar9003_hw_eeprom_get_tgt_pwr(ah
, LEGACY_TARGET_RATE_48
, freq
,
1434 targetPowerValT2
[ALL_TARGET_LEGACY_54
] =
1435 ar9003_hw_eeprom_get_tgt_pwr(ah
, LEGACY_TARGET_RATE_54
, freq
,
1437 targetPowerValT2
[ALL_TARGET_LEGACY_1L_5L
] =
1438 ar9003_hw_eeprom_get_cck_tgt_pwr(ah
, LEGACY_TARGET_RATE_1L_5L
,
1440 targetPowerValT2
[ALL_TARGET_LEGACY_5S
] =
1441 ar9003_hw_eeprom_get_cck_tgt_pwr(ah
, LEGACY_TARGET_RATE_5S
, freq
);
1442 targetPowerValT2
[ALL_TARGET_LEGACY_11L
] =
1443 ar9003_hw_eeprom_get_cck_tgt_pwr(ah
, LEGACY_TARGET_RATE_11L
, freq
);
1444 targetPowerValT2
[ALL_TARGET_LEGACY_11S
] =
1445 ar9003_hw_eeprom_get_cck_tgt_pwr(ah
, LEGACY_TARGET_RATE_11S
, freq
);
1446 targetPowerValT2
[ALL_TARGET_HT20_0_8_16
] =
1447 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_0_8_16
, freq
,
1449 targetPowerValT2
[ALL_TARGET_HT20_1_3_9_11_17_19
] =
1450 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_1_3_9_11_17_19
,
1452 targetPowerValT2
[ALL_TARGET_HT20_4
] =
1453 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_4
, freq
,
1455 targetPowerValT2
[ALL_TARGET_HT20_5
] =
1456 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_5
, freq
,
1458 targetPowerValT2
[ALL_TARGET_HT20_6
] =
1459 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_6
, freq
,
1461 targetPowerValT2
[ALL_TARGET_HT20_7
] =
1462 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_7
, freq
,
1464 targetPowerValT2
[ALL_TARGET_HT20_12
] =
1465 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_12
, freq
,
1467 targetPowerValT2
[ALL_TARGET_HT20_13
] =
1468 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_13
, freq
,
1470 targetPowerValT2
[ALL_TARGET_HT20_14
] =
1471 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_14
, freq
,
1473 targetPowerValT2
[ALL_TARGET_HT20_15
] =
1474 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_15
, freq
,
1476 targetPowerValT2
[ALL_TARGET_HT20_20
] =
1477 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_20
, freq
,
1479 targetPowerValT2
[ALL_TARGET_HT20_21
] =
1480 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_21
, freq
,
1482 targetPowerValT2
[ALL_TARGET_HT20_22
] =
1483 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_22
, freq
,
1485 targetPowerValT2
[ALL_TARGET_HT20_23
] =
1486 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_23
, freq
,
1488 targetPowerValT2
[ALL_TARGET_HT40_0_8_16
] =
1489 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_0_8_16
, freq
,
1490 is2GHz
) + ht40PowerIncForPdadc
;
1491 targetPowerValT2
[ALL_TARGET_HT40_1_3_9_11_17_19
] =
1492 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_1_3_9_11_17_19
,
1494 is2GHz
) + ht40PowerIncForPdadc
;
1495 targetPowerValT2
[ALL_TARGET_HT40_4
] =
1496 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_4
, freq
,
1497 is2GHz
) + ht40PowerIncForPdadc
;
1498 targetPowerValT2
[ALL_TARGET_HT40_5
] =
1499 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_5
, freq
,
1500 is2GHz
) + ht40PowerIncForPdadc
;
1501 targetPowerValT2
[ALL_TARGET_HT40_6
] =
1502 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_6
, freq
,
1503 is2GHz
) + ht40PowerIncForPdadc
;
1504 targetPowerValT2
[ALL_TARGET_HT40_7
] =
1505 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_7
, freq
,
1506 is2GHz
) + ht40PowerIncForPdadc
;
1507 targetPowerValT2
[ALL_TARGET_HT40_12
] =
1508 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_12
, freq
,
1509 is2GHz
) + ht40PowerIncForPdadc
;
1510 targetPowerValT2
[ALL_TARGET_HT40_13
] =
1511 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_13
, freq
,
1512 is2GHz
) + ht40PowerIncForPdadc
;
1513 targetPowerValT2
[ALL_TARGET_HT40_14
] =
1514 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_14
, freq
,
1515 is2GHz
) + ht40PowerIncForPdadc
;
1516 targetPowerValT2
[ALL_TARGET_HT40_15
] =
1517 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_15
, freq
,
1518 is2GHz
) + ht40PowerIncForPdadc
;
1519 targetPowerValT2
[ALL_TARGET_HT40_20
] =
1520 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_20
, freq
,
1521 is2GHz
) + ht40PowerIncForPdadc
;
1522 targetPowerValT2
[ALL_TARGET_HT40_21
] =
1523 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_21
, freq
,
1524 is2GHz
) + ht40PowerIncForPdadc
;
1525 targetPowerValT2
[ALL_TARGET_HT40_22
] =
1526 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_22
, freq
,
1527 is2GHz
) + ht40PowerIncForPdadc
;
1528 targetPowerValT2
[ALL_TARGET_HT40_23
] =
1529 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_23
, freq
,
1530 is2GHz
) + ht40PowerIncForPdadc
;
1532 while (i
< ar9300RateSize
) {
1533 ath_print(common
, ATH_DBG_EEPROM
,
1534 "TPC[%02d] 0x%08x ", i
, targetPowerValT2
[i
]);
1537 ath_print(common
, ATH_DBG_EEPROM
,
1538 "TPC[%02d] 0x%08x ", i
, targetPowerValT2
[i
]);
1541 ath_print(common
, ATH_DBG_EEPROM
,
1542 "TPC[%02d] 0x%08x ", i
, targetPowerValT2
[i
]);
1545 ath_print(common
, ATH_DBG_EEPROM
,
1546 "TPC[%02d] 0x%08x\n", i
, targetPowerValT2
[i
]);
1550 /* Write target power array to registers */
1551 ar9003_hw_tx_power_regwrite(ah
, targetPowerValT2
);
1554 static int ar9003_hw_cal_pier_get(struct ath_hw
*ah
,
1560 int *ptemperature
, int *pvoltage
)
1563 struct ar9300_cal_data_per_freq_op_loop
*pCalPierStruct
;
1565 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1566 struct ath_common
*common
= ath9k_hw_common(ah
);
1568 if (ichain
>= AR9300_MAX_CHAINS
) {
1569 ath_print(common
, ATH_DBG_EEPROM
,
1570 "Invalid chain index, must be less than %d\n",
1575 if (mode
) { /* 5GHz */
1576 if (ipier
>= AR9300_NUM_5G_CAL_PIERS
) {
1577 ath_print(common
, ATH_DBG_EEPROM
,
1578 "Invalid 5GHz cal pier index, must "
1579 "be less than %d\n",
1580 AR9300_NUM_5G_CAL_PIERS
);
1583 pCalPier
= &(eep
->calFreqPier5G
[ipier
]);
1584 pCalPierStruct
= &(eep
->calPierData5G
[ichain
][ipier
]);
1587 if (ipier
>= AR9300_NUM_2G_CAL_PIERS
) {
1588 ath_print(common
, ATH_DBG_EEPROM
,
1589 "Invalid 2GHz cal pier index, must "
1590 "be less than %d\n", AR9300_NUM_2G_CAL_PIERS
);
1594 pCalPier
= &(eep
->calFreqPier2G
[ipier
]);
1595 pCalPierStruct
= &(eep
->calPierData2G
[ichain
][ipier
]);
1599 *pfrequency
= FBIN2FREQ(*pCalPier
, is2GHz
);
1600 *pcorrection
= pCalPierStruct
->refPower
;
1601 *ptemperature
= pCalPierStruct
->tempMeas
;
1602 *pvoltage
= pCalPierStruct
->voltMeas
;
1607 static int ar9003_hw_power_control_override(struct ath_hw
*ah
,
1610 int *voltage
, int *temperature
)
1613 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1615 REG_RMW(ah
, AR_PHY_TPC_11_B0
,
1616 (correction
[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S
),
1617 AR_PHY_TPC_OLPC_GAIN_DELTA
);
1618 REG_RMW(ah
, AR_PHY_TPC_11_B1
,
1619 (correction
[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S
),
1620 AR_PHY_TPC_OLPC_GAIN_DELTA
);
1621 REG_RMW(ah
, AR_PHY_TPC_11_B2
,
1622 (correction
[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S
),
1623 AR_PHY_TPC_OLPC_GAIN_DELTA
);
1625 /* enable open loop power control on chip */
1626 REG_RMW(ah
, AR_PHY_TPC_6_B0
,
1627 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S
),
1628 AR_PHY_TPC_6_ERROR_EST_MODE
);
1629 REG_RMW(ah
, AR_PHY_TPC_6_B1
,
1630 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S
),
1631 AR_PHY_TPC_6_ERROR_EST_MODE
);
1632 REG_RMW(ah
, AR_PHY_TPC_6_B2
,
1633 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S
),
1634 AR_PHY_TPC_6_ERROR_EST_MODE
);
1637 * enable temperature compensation
1638 * Need to use register names
1640 if (frequency
< 4000)
1641 tempSlope
= eep
->modalHeader2G
.tempSlope
;
1643 tempSlope
= eep
->modalHeader5G
.tempSlope
;
1645 REG_RMW_FIELD(ah
, AR_PHY_TPC_19
, AR_PHY_TPC_19_ALPHA_THERM
, tempSlope
);
1646 REG_RMW_FIELD(ah
, AR_PHY_TPC_18
, AR_PHY_TPC_18_THERM_CAL_VALUE
,
1652 /* Apply the recorded correction values. */
1653 static int ar9003_hw_calibration_apply(struct ath_hw
*ah
, int frequency
)
1655 int ichain
, ipier
, npier
;
1657 int lfrequency
[AR9300_MAX_CHAINS
],
1658 lcorrection
[AR9300_MAX_CHAINS
],
1659 ltemperature
[AR9300_MAX_CHAINS
], lvoltage
[AR9300_MAX_CHAINS
];
1660 int hfrequency
[AR9300_MAX_CHAINS
],
1661 hcorrection
[AR9300_MAX_CHAINS
],
1662 htemperature
[AR9300_MAX_CHAINS
], hvoltage
[AR9300_MAX_CHAINS
];
1664 int correction
[AR9300_MAX_CHAINS
],
1665 voltage
[AR9300_MAX_CHAINS
], temperature
[AR9300_MAX_CHAINS
];
1666 int pfrequency
, pcorrection
, ptemperature
, pvoltage
;
1667 struct ath_common
*common
= ath9k_hw_common(ah
);
1669 mode
= (frequency
>= 4000);
1671 npier
= AR9300_NUM_5G_CAL_PIERS
;
1673 npier
= AR9300_NUM_2G_CAL_PIERS
;
1675 for (ichain
= 0; ichain
< AR9300_MAX_CHAINS
; ichain
++) {
1676 lfrequency
[ichain
] = 0;
1677 hfrequency
[ichain
] = 100000;
1679 /* identify best lower and higher frequency calibration measurement */
1680 for (ichain
= 0; ichain
< AR9300_MAX_CHAINS
; ichain
++) {
1681 for (ipier
= 0; ipier
< npier
; ipier
++) {
1682 if (!ar9003_hw_cal_pier_get(ah
, mode
, ipier
, ichain
,
1683 &pfrequency
, &pcorrection
,
1684 &ptemperature
, &pvoltage
)) {
1685 fdiff
= frequency
- pfrequency
;
1688 * this measurement is higher than
1689 * our desired frequency
1692 if (hfrequency
[ichain
] <= 0 ||
1693 hfrequency
[ichain
] >= 100000 ||
1695 (frequency
- hfrequency
[ichain
])) {
1698 * frequency measurement
1700 hfrequency
[ichain
] = pfrequency
;
1701 hcorrection
[ichain
] =
1703 htemperature
[ichain
] =
1705 hvoltage
[ichain
] = pvoltage
;
1709 if (lfrequency
[ichain
] <= 0
1711 (frequency
- lfrequency
[ichain
])) {
1714 * frequency measurement
1716 lfrequency
[ichain
] = pfrequency
;
1717 lcorrection
[ichain
] =
1719 ltemperature
[ichain
] =
1721 lvoltage
[ichain
] = pvoltage
;
1729 for (ichain
= 0; ichain
< AR9300_MAX_CHAINS
; ichain
++) {
1730 ath_print(common
, ATH_DBG_EEPROM
,
1731 "ch=%d f=%d low=%d %d h=%d %d\n",
1732 ichain
, frequency
, lfrequency
[ichain
],
1733 lcorrection
[ichain
], hfrequency
[ichain
],
1734 hcorrection
[ichain
]);
1735 /* they're the same, so just pick one */
1736 if (hfrequency
[ichain
] == lfrequency
[ichain
]) {
1737 correction
[ichain
] = lcorrection
[ichain
];
1738 voltage
[ichain
] = lvoltage
[ichain
];
1739 temperature
[ichain
] = ltemperature
[ichain
];
1741 /* the low frequency is good */
1742 else if (frequency
- lfrequency
[ichain
] < 1000) {
1743 /* so is the high frequency, interpolate */
1744 if (hfrequency
[ichain
] - frequency
< 1000) {
1746 correction
[ichain
] = lcorrection
[ichain
] +
1747 (((frequency
- lfrequency
[ichain
]) *
1748 (hcorrection
[ichain
] -
1749 lcorrection
[ichain
])) /
1750 (hfrequency
[ichain
] - lfrequency
[ichain
]));
1752 temperature
[ichain
] = ltemperature
[ichain
] +
1753 (((frequency
- lfrequency
[ichain
]) *
1754 (htemperature
[ichain
] -
1755 ltemperature
[ichain
])) /
1756 (hfrequency
[ichain
] - lfrequency
[ichain
]));
1761 lfrequency
[ichain
]) * (hvoltage
[ichain
] -
1763 / (hfrequency
[ichain
] -
1764 lfrequency
[ichain
]));
1766 /* only low is good, use it */
1768 correction
[ichain
] = lcorrection
[ichain
];
1769 temperature
[ichain
] = ltemperature
[ichain
];
1770 voltage
[ichain
] = lvoltage
[ichain
];
1773 /* only high is good, use it */
1774 else if (hfrequency
[ichain
] - frequency
< 1000) {
1775 correction
[ichain
] = hcorrection
[ichain
];
1776 temperature
[ichain
] = htemperature
[ichain
];
1777 voltage
[ichain
] = hvoltage
[ichain
];
1778 } else { /* nothing is good, presume 0???? */
1779 correction
[ichain
] = 0;
1780 temperature
[ichain
] = 0;
1781 voltage
[ichain
] = 0;
1785 ar9003_hw_power_control_override(ah
, frequency
, correction
, voltage
,
1788 ath_print(common
, ATH_DBG_EEPROM
,
1789 "for frequency=%d, calibration correction = %d %d %d\n",
1790 frequency
, correction
[0], correction
[1], correction
[2]);
1795 static void ath9k_hw_ar9300_set_txpower(struct ath_hw
*ah
,
1796 struct ath9k_channel
*chan
, u16 cfgCtl
,
1797 u8 twiceAntennaReduction
,
1798 u8 twiceMaxRegulatoryPower
,
1801 ah
->txpower_limit
= powerLimit
;
1802 ar9003_hw_set_target_power_eeprom(ah
, chan
->channel
);
1803 ar9003_hw_calibration_apply(ah
, chan
->channel
);
1806 static u16
ath9k_hw_ar9300_get_spur_channel(struct ath_hw
*ah
,
1812 s32
ar9003_hw_get_tx_gain_idx(struct ath_hw
*ah
)
1814 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1816 return (eep
->baseEepHeader
.txrxgain
>> 4) & 0xf; /* bits 7:4 */
1819 s32
ar9003_hw_get_rx_gain_idx(struct ath_hw
*ah
)
1821 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1823 return (eep
->baseEepHeader
.txrxgain
) & 0xf; /* bits 3:0 */
1826 const struct eeprom_ops eep_ar9300_ops
= {
1827 .check_eeprom
= ath9k_hw_ar9300_check_eeprom
,
1828 .get_eeprom
= ath9k_hw_ar9300_get_eeprom
,
1829 .fill_eeprom
= ath9k_hw_ar9300_fill_eeprom
,
1830 .get_eeprom_ver
= ath9k_hw_ar9300_get_eeprom_ver
,
1831 .get_eeprom_rev
= ath9k_hw_ar9300_get_eeprom_rev
,
1832 .get_num_ant_config
= ath9k_hw_ar9300_get_num_ant_config
,
1833 .get_eeprom_antenna_cfg
= ath9k_hw_ar9300_get_eeprom_antenna_cfg
,
1834 .set_board_values
= ath9k_hw_ar9300_set_board_values
,
1835 .set_addac
= ath9k_hw_ar9300_set_addac
,
1836 .set_txpower
= ath9k_hw_ar9300_set_txpower
,
1837 .get_spur_channel
= ath9k_hw_ar9300_get_spur_channel