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 /* Local defines to distinguish between extension and control CTL's */
45 #define EXT_ADDITIVE (0x8000)
46 #define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE)
47 #define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE)
48 #define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE)
49 #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
50 #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */
51 #define PWRINCR_3_TO_1_CHAIN 9 /* 10*log(3)*2 */
52 #define PWRINCR_3_TO_2_CHAIN 3 /* floor(10*log(3/2)*2) */
53 #define PWRINCR_2_TO_1_CHAIN 6 /* 10*log(2)*2 */
55 #define SUB_NUM_CTL_MODES_AT_5G_40 2 /* excluding HT40, EXT-OFDM */
56 #define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */
58 #define CTL(_tpower, _flag) ((_tpower) | ((_flag) << 6))
60 static const struct ar9300_eeprom ar9300_default
= {
63 .macAddr
= {1, 2, 3, 4, 5, 6},
64 .custData
= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
65 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
67 .regDmn
= { LE16(0), LE16(0x1f) },
68 .txrxMask
= 0x77, /* 4 bits tx and 4 bits rx */
70 .opFlags
= AR9300_OPFLAGS_11G
| AR9300_OPFLAGS_11A
,
74 .blueToothOptions
= 0,
76 .deviceType
= 5, /* takes lower byte in eeprom location */
77 .pwrTableOffset
= AR9300_PWR_TABLE_OFFSET
,
78 .params_for_tuning_caps
= {0, 0},
79 .featureEnable
= 0x0c,
81 * bit0 - enable tx temp comp - disabled
82 * bit1 - enable tx volt comp - disabled
83 * bit2 - enable fastClock - enabled
84 * bit3 - enable doubling - enabled
85 * bit4 - enable internal regulator - disabled
86 * bit5 - enable pa predistortion - disabled
88 .miscConfiguration
= 0, /* bit0 - turn down drivestrength */
89 .eepromWriteEnableGpio
= 3,
92 .rxBandSelectGpio
= 0xff,
97 /* ar9300_modal_eep_header 2g */
98 /* 4 idle,t1,t2,b(4 bits per setting) */
99 .antCtrlCommon
= LE32(0x110),
100 /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
101 .antCtrlCommon2
= LE32(0x22222),
104 * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
105 * rx1, rx12, b (2 bits each)
107 .antCtrlChain
= { LE16(0x150), LE16(0x150), LE16(0x150) },
110 * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db
111 * for ar9280 (0xa20c/b20c 5:0)
113 .xatten1DB
= {0, 0, 0},
116 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
117 * for ar9280 (0xa20c/b20c 16:12
119 .xatten1Margin
= {0, 0, 0},
124 * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
125 * channels in usual fbin coding format
127 .spurChans
= {0, 0, 0, 0, 0},
130 * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
131 * if the register is per chain
133 .noiseFloorThreshCh
= {-1, 0, 0},
134 .ob
= {1, 1, 1},/* 3 chain */
135 .db_stage2
= {1, 1, 1}, /* 3 chain */
136 .db_stage3
= {0, 0, 0},
137 .db_stage4
= {0, 0, 0},
139 .txFrameToDataStart
= 0x0e,
140 .txFrameToPaOn
= 0x0e,
141 .txClip
= 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
143 .switchSettling
= 0x2c,
144 .adcDesiredSize
= -30,
147 .txFrameToXpaOn
= 0xe,
149 .papdRateMaskHt20
= LE32(0x80c080),
150 .papdRateMaskHt40
= LE32(0x80c080),
152 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
153 0, 0, 0, 0, 0, 0, 0, 0
161 /* ar9300_cal_data_per_freq_op_loop 2g */
163 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
164 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
165 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
167 .calTarget_freqbin_Cck
= {
171 .calTarget_freqbin_2G
= {
176 .calTarget_freqbin_2GHT20
= {
181 .calTarget_freqbin_2GHT40
= {
186 .calTargetPowerCck
= {
187 /* 1L-5L,5S,11L,11S */
188 { {36, 36, 36, 36} },
189 { {36, 36, 36, 36} },
191 .calTargetPower2G
= {
193 { {32, 32, 28, 24} },
194 { {32, 32, 28, 24} },
195 { {32, 32, 28, 24} },
197 .calTargetPower2GHT20
= {
198 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
199 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
200 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
202 .calTargetPower2GHT40
= {
203 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
204 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
205 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
208 0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
209 0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
239 /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
240 /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
241 /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
242 /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
246 /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
247 /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
248 /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
253 /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
254 /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
260 /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
261 /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
262 /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
263 /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
267 /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
268 /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
269 /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
273 /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
274 /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
275 /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
280 /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
281 /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
282 /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
287 /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
288 /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
289 /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
290 /* Data[11].ctlEdges[3].bChannel */
295 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
296 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
297 { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
299 { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
300 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
301 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
303 { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
304 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
305 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
307 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
308 { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
309 { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
312 /* 4 idle,t1,t2,b (4 bits per setting) */
313 .antCtrlCommon
= LE32(0x110),
314 /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
315 .antCtrlCommon2
= LE32(0x22222),
316 /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
318 LE16(0x000), LE16(0x000), LE16(0x000),
320 /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
321 .xatten1DB
= {0, 0, 0},
324 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
325 * for merlin (0xa20c/b20c 16:12
327 .xatten1Margin
= {0, 0, 0},
330 /* spurChans spur channels in usual fbin coding format */
331 .spurChans
= {0, 0, 0, 0, 0},
332 /* noiseFloorThreshCh Check if the register is per chain */
333 .noiseFloorThreshCh
= {-1, 0, 0},
334 .ob
= {3, 3, 3}, /* 3 chain */
335 .db_stage2
= {3, 3, 3}, /* 3 chain */
336 .db_stage3
= {3, 3, 3}, /* doesn't exist for 2G */
337 .db_stage4
= {3, 3, 3}, /* don't exist for 2G */
339 .txFrameToDataStart
= 0x0e,
340 .txFrameToPaOn
= 0x0e,
341 .txClip
= 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
343 .switchSettling
= 0x2d,
344 .adcDesiredSize
= -30,
347 .txFrameToXpaOn
= 0xe,
349 .papdRateMaskHt20
= LE32(0xf0e0e0),
350 .papdRateMaskHt40
= LE32(0xf0e0e0),
352 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
353 0, 0, 0, 0, 0, 0, 0, 0
399 .calTarget_freqbin_5G
= {
409 .calTarget_freqbin_5GHT20
= {
419 .calTarget_freqbin_5GHT40
= {
429 .calTargetPower5G
= {
431 { {20, 20, 20, 10} },
432 { {20, 20, 20, 10} },
433 { {20, 20, 20, 10} },
434 { {20, 20, 20, 10} },
435 { {20, 20, 20, 10} },
436 { {20, 20, 20, 10} },
437 { {20, 20, 20, 10} },
438 { {20, 20, 20, 10} },
440 .calTargetPower5GHT20
= {
442 * 0_8_16,1-3_9-11_17-19,
443 * 4,5,6,7,12,13,14,15,20,21,22,23
445 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
446 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
447 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
448 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
449 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
450 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
451 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
452 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
454 .calTargetPower5GHT40
= {
456 * 0_8_16,1-3_9-11_17-19,
457 * 4,5,6,7,12,13,14,15,20,21,22,23
459 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
460 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
461 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
462 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
463 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
464 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
465 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
466 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
469 0x10, 0x16, 0x18, 0x40, 0x46,
470 0x48, 0x30, 0x36, 0x38
474 /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
475 /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
476 /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
477 /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
478 /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
479 /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
480 /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
481 /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
484 /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
485 /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
486 /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
487 /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
488 /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
489 /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
490 /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
491 /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
495 /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
496 /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
497 /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
498 /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
499 /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
500 /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
501 /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
502 /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
506 /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
507 /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
508 /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
509 /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
510 /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
511 /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
512 /* Data[3].ctlEdges[6].bChannel */ 0xFF,
513 /* Data[3].ctlEdges[7].bChannel */ 0xFF,
517 /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
518 /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
519 /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
520 /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
521 /* Data[4].ctlEdges[4].bChannel */ 0xFF,
522 /* Data[4].ctlEdges[5].bChannel */ 0xFF,
523 /* Data[4].ctlEdges[6].bChannel */ 0xFF,
524 /* Data[4].ctlEdges[7].bChannel */ 0xFF,
528 /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
529 /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
530 /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
531 /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
532 /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
533 /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
534 /* Data[5].ctlEdges[6].bChannel */ 0xFF,
535 /* Data[5].ctlEdges[7].bChannel */ 0xFF
539 /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
540 /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
541 /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
542 /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
543 /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
544 /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
545 /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
546 /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
550 /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
551 /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
552 /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
553 /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
554 /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
555 /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
556 /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
557 /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
561 /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
562 /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
563 /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
564 /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
565 /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
566 /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
567 /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
568 /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
574 CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
575 CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
580 CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
581 CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
586 CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
587 CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
592 CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
593 CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
598 CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
599 CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
604 CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
605 CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
610 CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
611 CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
616 CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
617 CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
622 CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
623 CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
629 static u16
ath9k_hw_fbin2freq(u8 fbin
, bool is2GHz
)
631 if (fbin
== AR9300_BCHAN_UNUSED
)
634 return (u16
) ((is2GHz
) ? (2300 + fbin
) : (4800 + 5 * fbin
));
637 static int ath9k_hw_ar9300_check_eeprom(struct ath_hw
*ah
)
642 static u32
ath9k_hw_ar9300_get_eeprom(struct ath_hw
*ah
,
643 enum eeprom_param param
)
645 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
646 struct ar9300_base_eep_hdr
*pBase
= &eep
->baseEepHeader
;
650 return eep
->macAddr
[0] << 8 | eep
->macAddr
[1];
652 return eep
->macAddr
[2] << 8 | eep
->macAddr
[3];
654 return eep
->macAddr
[4] << 8 | eep
->macAddr
[5];
656 return le16_to_cpu(pBase
->regDmn
[0]);
658 return le16_to_cpu(pBase
->regDmn
[1]);
660 return pBase
->deviceCap
;
662 return pBase
->opCapFlags
.opFlags
;
664 return pBase
->rfSilent
;
666 return (pBase
->txrxMask
>> 4) & 0xf;
668 return pBase
->txrxMask
& 0xf;
669 case EEP_DRIVE_STRENGTH
:
670 #define AR9300_EEP_BASE_DRIV_STRENGTH 0x1
671 return pBase
->miscConfiguration
& AR9300_EEP_BASE_DRIV_STRENGTH
;
672 case EEP_INTERNAL_REGULATOR
:
673 /* Bit 4 is internal regulator flag */
674 return (pBase
->featureEnable
& 0x10) >> 4;
676 return le32_to_cpu(pBase
->swreg
);
678 return !!(pBase
->featureEnable
& BIT(5));
684 static bool ar9300_eeprom_read_byte(struct ath_common
*common
, int address
,
689 if (unlikely(!ath9k_hw_nvram_read(common
, address
/ 2, &val
)))
692 *buffer
= (val
>> (8 * (address
% 2))) & 0xff;
696 static bool ar9300_eeprom_read_word(struct ath_common
*common
, int address
,
701 if (unlikely(!ath9k_hw_nvram_read(common
, address
/ 2, &val
)))
704 buffer
[0] = val
>> 8;
705 buffer
[1] = val
& 0xff;
710 static bool ar9300_read_eeprom(struct ath_hw
*ah
, int address
, u8
*buffer
,
713 struct ath_common
*common
= ath9k_hw_common(ah
);
716 if ((address
< 0) || ((address
+ count
) / 2 > AR9300_EEPROM_SIZE
- 1)) {
717 ath_print(common
, ATH_DBG_EEPROM
,
718 "eeprom address not in range\n");
723 * Since we're reading the bytes in reverse order from a little-endian
724 * word stream, an even address means we only use the lower half of
725 * the 16-bit word at that address
727 if (address
% 2 == 0) {
728 if (!ar9300_eeprom_read_byte(common
, address
--, buffer
++))
734 for (i
= 0; i
< count
/ 2; i
++) {
735 if (!ar9300_eeprom_read_word(common
, address
, buffer
))
743 if (!ar9300_eeprom_read_byte(common
, address
, buffer
))
749 ath_print(common
, ATH_DBG_EEPROM
,
750 "unable to read eeprom region at offset %d\n", address
);
754 static void ar9300_comp_hdr_unpack(u8
*best
, int *code
, int *reference
,
755 int *length
, int *major
, int *minor
)
757 unsigned long value
[4];
763 *code
= ((value
[0] >> 5) & 0x0007);
764 *reference
= (value
[0] & 0x001f) | ((value
[1] >> 2) & 0x0020);
765 *length
= ((value
[1] << 4) & 0x07f0) | ((value
[2] >> 4) & 0x000f);
766 *major
= (value
[2] & 0x000f);
767 *minor
= (value
[3] & 0x00ff);
770 static u16
ar9300_comp_cksum(u8
*data
, int dsize
)
772 int it
, checksum
= 0;
774 for (it
= 0; it
< dsize
; it
++) {
775 checksum
+= data
[it
];
782 static bool ar9300_uncompress_block(struct ath_hw
*ah
,
792 struct ath_common
*common
= ath9k_hw_common(ah
);
796 for (it
= 0; it
< size
; it
+= (length
+2)) {
800 length
= block
[it
+1];
803 if (length
> 0 && spot
>= 0 && spot
+length
<= mdataSize
) {
804 ath_print(common
, ATH_DBG_EEPROM
,
805 "Restore at %d: spot=%d "
806 "offset=%d length=%d\n",
807 it
, spot
, offset
, length
);
808 memcpy(&mptr
[spot
], &block
[it
+2], length
);
810 } else if (length
> 0) {
811 ath_print(common
, ATH_DBG_EEPROM
,
812 "Bad restore at %d: spot=%d "
813 "offset=%d length=%d\n",
814 it
, spot
, offset
, length
);
821 static int ar9300_compress_decision(struct ath_hw
*ah
,
826 u8
*word
, int length
, int mdata_size
)
828 struct ath_common
*common
= ath9k_hw_common(ah
);
833 if (length
!= mdata_size
) {
834 ath_print(common
, ATH_DBG_EEPROM
,
835 "EEPROM structure size mismatch"
836 "memory=%d eeprom=%d\n", mdata_size
, length
);
839 memcpy(mptr
, (u8
*) (word
+ COMP_HDR_LEN
), length
);
840 ath_print(common
, ATH_DBG_EEPROM
, "restored eeprom %d:"
841 " uncompressed, length %d\n", it
, length
);
844 if (reference
== 0) {
847 if (reference
!= 2) {
848 ath_print(common
, ATH_DBG_EEPROM
,
849 "cant find reference eeprom"
850 "struct %d\n", reference
);
853 memcpy(mptr
, &ar9300_default
, mdata_size
);
855 ath_print(common
, ATH_DBG_EEPROM
,
856 "restore eeprom %d: block, reference %d,"
857 " length %d\n", it
, reference
, length
);
858 ar9300_uncompress_block(ah
, mptr
, mdata_size
,
859 (u8
*) (word
+ COMP_HDR_LEN
), length
);
862 ath_print(common
, ATH_DBG_EEPROM
, "unknown compression"
870 * Read the configuration data from the eeprom.
871 * The data can be put in any specified memory buffer.
873 * Returns -1 on error.
874 * Returns address of next memory location on success.
876 static int ar9300_eeprom_restore_internal(struct ath_hw
*ah
,
877 u8
*mptr
, int mdata_size
)
884 int reference
, length
, major
, minor
;
887 u16 checksum
, mchecksum
;
888 struct ath_common
*common
= ath9k_hw_common(ah
);
890 word
= kzalloc(2048, GFP_KERNEL
);
894 memcpy(mptr
, &ar9300_default
, mdata_size
);
896 cptr
= AR9300_BASE_ADDR
;
897 for (it
= 0; it
< MSTATE
; it
++) {
898 if (!ar9300_read_eeprom(ah
, cptr
, word
, COMP_HDR_LEN
))
901 if ((word
[0] == 0 && word
[1] == 0 && word
[2] == 0 &&
902 word
[3] == 0) || (word
[0] == 0xff && word
[1] == 0xff
903 && word
[2] == 0xff && word
[3] == 0xff))
906 ar9300_comp_hdr_unpack(word
, &code
, &reference
,
907 &length
, &major
, &minor
);
908 ath_print(common
, ATH_DBG_EEPROM
,
909 "Found block at %x: code=%d ref=%d"
910 "length=%d major=%d minor=%d\n", cptr
, code
,
911 reference
, length
, major
, minor
);
912 if (length
>= 1024) {
913 ath_print(common
, ATH_DBG_EEPROM
,
914 "Skipping bad header\n");
915 cptr
-= COMP_HDR_LEN
;
920 ar9300_read_eeprom(ah
, cptr
, word
,
921 COMP_HDR_LEN
+ osize
+ COMP_CKSUM_LEN
);
922 checksum
= ar9300_comp_cksum(&word
[COMP_HDR_LEN
], length
);
923 mchecksum
= word
[COMP_HDR_LEN
+ osize
] |
924 (word
[COMP_HDR_LEN
+ osize
+ 1] << 8);
925 ath_print(common
, ATH_DBG_EEPROM
,
926 "checksum %x %x\n", checksum
, mchecksum
);
927 if (checksum
== mchecksum
) {
928 ar9300_compress_decision(ah
, it
, code
, reference
, mptr
,
929 word
, length
, mdata_size
);
931 ath_print(common
, ATH_DBG_EEPROM
,
932 "skipping block with bad checksum\n");
934 cptr
-= (COMP_HDR_LEN
+ osize
+ COMP_CKSUM_LEN
);
946 * Restore the configuration structure by reading the eeprom.
947 * This function destroys any existing in-memory structure
950 static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw
*ah
)
952 u8
*mptr
= (u8
*) &ah
->eeprom
.ar9300_eep
;
954 if (ar9300_eeprom_restore_internal(ah
, mptr
,
955 sizeof(struct ar9300_eeprom
)) < 0)
961 /* XXX: review hardware docs */
962 static int ath9k_hw_ar9300_get_eeprom_ver(struct ath_hw
*ah
)
964 return ah
->eeprom
.ar9300_eep
.eepromVersion
;
967 /* XXX: could be read from the eepromVersion, not sure yet */
968 static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw
*ah
)
973 static u8
ath9k_hw_ar9300_get_num_ant_config(struct ath_hw
*ah
,
974 enum ath9k_hal_freq_band freq_band
)
979 static u32
ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw
*ah
,
980 struct ath9k_channel
*chan
)
985 static s32
ar9003_hw_xpa_bias_level_get(struct ath_hw
*ah
, bool is2ghz
)
987 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
990 return eep
->modalHeader2G
.xpaBiasLvl
;
992 return eep
->modalHeader5G
.xpaBiasLvl
;
995 static void ar9003_hw_xpa_bias_level_apply(struct ath_hw
*ah
, bool is2ghz
)
997 int bias
= ar9003_hw_xpa_bias_level_get(ah
, is2ghz
);
998 REG_RMW_FIELD(ah
, AR_CH0_TOP
, AR_CH0_TOP_XPABIASLVL
, (bias
& 0x3));
999 REG_RMW_FIELD(ah
, AR_CH0_THERM
, AR_CH0_THERM_SPARE
,
1000 ((bias
>> 2) & 0x3));
1003 static u32
ar9003_hw_ant_ctrl_common_get(struct ath_hw
*ah
, bool is2ghz
)
1005 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1009 val
= eep
->modalHeader2G
.antCtrlCommon
;
1011 val
= eep
->modalHeader5G
.antCtrlCommon
;
1012 return le32_to_cpu(val
);
1015 static u32
ar9003_hw_ant_ctrl_common_2_get(struct ath_hw
*ah
, bool is2ghz
)
1017 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1021 val
= eep
->modalHeader2G
.antCtrlCommon2
;
1023 val
= eep
->modalHeader5G
.antCtrlCommon2
;
1024 return le32_to_cpu(val
);
1027 static u16
ar9003_hw_ant_ctrl_chain_get(struct ath_hw
*ah
,
1031 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1034 if (chain
>= 0 && chain
< AR9300_MAX_CHAINS
) {
1036 val
= eep
->modalHeader2G
.antCtrlChain
[chain
];
1038 val
= eep
->modalHeader5G
.antCtrlChain
[chain
];
1041 return le16_to_cpu(val
);
1044 static void ar9003_hw_ant_ctrl_apply(struct ath_hw
*ah
, bool is2ghz
)
1046 u32 value
= ar9003_hw_ant_ctrl_common_get(ah
, is2ghz
);
1047 REG_RMW_FIELD(ah
, AR_PHY_SWITCH_COM
, AR_SWITCH_TABLE_COM_ALL
, value
);
1049 value
= ar9003_hw_ant_ctrl_common_2_get(ah
, is2ghz
);
1050 REG_RMW_FIELD(ah
, AR_PHY_SWITCH_COM_2
, AR_SWITCH_TABLE_COM2_ALL
, value
);
1052 value
= ar9003_hw_ant_ctrl_chain_get(ah
, 0, is2ghz
);
1053 REG_RMW_FIELD(ah
, AR_PHY_SWITCH_CHAIN_0
, AR_SWITCH_TABLE_ALL
, value
);
1055 value
= ar9003_hw_ant_ctrl_chain_get(ah
, 1, is2ghz
);
1056 REG_RMW_FIELD(ah
, AR_PHY_SWITCH_CHAIN_1
, AR_SWITCH_TABLE_ALL
, value
);
1058 value
= ar9003_hw_ant_ctrl_chain_get(ah
, 2, is2ghz
);
1059 REG_RMW_FIELD(ah
, AR_PHY_SWITCH_CHAIN_2
, AR_SWITCH_TABLE_ALL
, value
);
1062 static void ar9003_hw_drive_strength_apply(struct ath_hw
*ah
)
1067 drive_strength
= ath9k_hw_ar9300_get_eeprom(ah
, EEP_DRIVE_STRENGTH
);
1069 if (!drive_strength
)
1072 reg
= REG_READ(ah
, AR_PHY_65NM_CH0_BIAS1
);
1080 REG_WRITE(ah
, AR_PHY_65NM_CH0_BIAS1
, reg
);
1082 reg
= REG_READ(ah
, AR_PHY_65NM_CH0_BIAS2
);
1093 REG_WRITE(ah
, AR_PHY_65NM_CH0_BIAS2
, reg
);
1095 reg
= REG_READ(ah
, AR_PHY_65NM_CH0_BIAS4
);
1100 REG_WRITE(ah
, AR_PHY_65NM_CH0_BIAS4
, reg
);
1103 static void ar9003_hw_internal_regulator_apply(struct ath_hw
*ah
)
1105 int internal_regulator
=
1106 ath9k_hw_ar9300_get_eeprom(ah
, EEP_INTERNAL_REGULATOR
);
1108 if (internal_regulator
) {
1109 /* Internal regulator is ON. Write swreg register. */
1110 int swreg
= ath9k_hw_ar9300_get_eeprom(ah
, EEP_SWREG
);
1111 REG_WRITE(ah
, AR_RTC_REG_CONTROL1
,
1112 REG_READ(ah
, AR_RTC_REG_CONTROL1
) &
1113 (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM
));
1114 REG_WRITE(ah
, AR_RTC_REG_CONTROL0
, swreg
);
1115 /* Set REG_CONTROL1.SWREG_PROGRAM */
1116 REG_WRITE(ah
, AR_RTC_REG_CONTROL1
,
1118 AR_RTC_REG_CONTROL1
) |
1119 AR_RTC_REG_CONTROL1_SWREG_PROGRAM
);
1121 REG_WRITE(ah
, AR_RTC_SLEEP_CLK
,
1124 AR_RTC_FORCE_SWREG_PRD
));
1128 static void ath9k_hw_ar9300_set_board_values(struct ath_hw
*ah
,
1129 struct ath9k_channel
*chan
)
1131 ar9003_hw_xpa_bias_level_apply(ah
, IS_CHAN_2GHZ(chan
));
1132 ar9003_hw_ant_ctrl_apply(ah
, IS_CHAN_2GHZ(chan
));
1133 ar9003_hw_drive_strength_apply(ah
);
1134 ar9003_hw_internal_regulator_apply(ah
);
1137 static void ath9k_hw_ar9300_set_addac(struct ath_hw
*ah
,
1138 struct ath9k_channel
*chan
)
1143 * Returns the interpolated y value corresponding to the specified x value
1144 * from the np ordered pairs of data (px,py).
1145 * The pairs do not have to be in any order.
1146 * If the specified x value is less than any of the px,
1147 * the returned y value is equal to the py for the lowest px.
1148 * If the specified x value is greater than any of the px,
1149 * the returned y value is equal to the py for the highest px.
1151 static int ar9003_hw_power_interpolate(int32_t x
,
1152 int32_t *px
, int32_t *py
, u_int16_t np
)
1155 int lx
= 0, ly
= 0, lhave
= 0;
1156 int hx
= 0, hy
= 0, hhave
= 0;
1163 /* identify best lower and higher x calibration measurement */
1164 for (ip
= 0; ip
< np
; ip
++) {
1167 /* this measurement is higher than our desired x */
1169 if (!hhave
|| dx
> (x
- hx
)) {
1170 /* new best higher x measurement */
1176 /* this measurement is lower than our desired x */
1178 if (!lhave
|| dx
< (x
- lx
)) {
1179 /* new best lower x measurement */
1187 /* the low x is good */
1189 /* so is the high x */
1191 /* they're the same, so just pick one */
1194 else /* interpolate */
1195 y
= ly
+ (((x
- lx
) * (hy
- ly
)) / (hx
- lx
));
1196 } else /* only low is good, use it */
1198 } else if (hhave
) /* only high is good, use it */
1200 else /* nothing is good,this should never happen unless np=0, ???? */
1205 static u8
ar9003_hw_eeprom_get_tgt_pwr(struct ath_hw
*ah
,
1206 u16 rateIndex
, u16 freq
, bool is2GHz
)
1209 s32 targetPowerArray
[AR9300_NUM_5G_20_TARGET_POWERS
];
1210 s32 freqArray
[AR9300_NUM_5G_20_TARGET_POWERS
];
1211 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1212 struct cal_tgt_pow_legacy
*pEepromTargetPwr
;
1216 numPiers
= AR9300_NUM_2G_20_TARGET_POWERS
;
1217 pEepromTargetPwr
= eep
->calTargetPower2G
;
1218 pFreqBin
= eep
->calTarget_freqbin_2G
;
1220 numPiers
= AR9300_NUM_5G_20_TARGET_POWERS
;
1221 pEepromTargetPwr
= eep
->calTargetPower5G
;
1222 pFreqBin
= eep
->calTarget_freqbin_5G
;
1226 * create array of channels and targetpower from
1227 * targetpower piers stored on eeprom
1229 for (i
= 0; i
< numPiers
; i
++) {
1230 freqArray
[i
] = FBIN2FREQ(pFreqBin
[i
], is2GHz
);
1231 targetPowerArray
[i
] = pEepromTargetPwr
[i
].tPow2x
[rateIndex
];
1234 /* interpolate to get target power for given frequency */
1235 return (u8
) ar9003_hw_power_interpolate((s32
) freq
,
1237 targetPowerArray
, numPiers
);
1240 static u8
ar9003_hw_eeprom_get_ht20_tgt_pwr(struct ath_hw
*ah
,
1242 u16 freq
, bool is2GHz
)
1245 s32 targetPowerArray
[AR9300_NUM_5G_20_TARGET_POWERS
];
1246 s32 freqArray
[AR9300_NUM_5G_20_TARGET_POWERS
];
1247 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1248 struct cal_tgt_pow_ht
*pEepromTargetPwr
;
1252 numPiers
= AR9300_NUM_2G_20_TARGET_POWERS
;
1253 pEepromTargetPwr
= eep
->calTargetPower2GHT20
;
1254 pFreqBin
= eep
->calTarget_freqbin_2GHT20
;
1256 numPiers
= AR9300_NUM_5G_20_TARGET_POWERS
;
1257 pEepromTargetPwr
= eep
->calTargetPower5GHT20
;
1258 pFreqBin
= eep
->calTarget_freqbin_5GHT20
;
1262 * create array of channels and targetpower
1263 * from targetpower piers stored on eeprom
1265 for (i
= 0; i
< numPiers
; i
++) {
1266 freqArray
[i
] = FBIN2FREQ(pFreqBin
[i
], is2GHz
);
1267 targetPowerArray
[i
] = pEepromTargetPwr
[i
].tPow2x
[rateIndex
];
1270 /* interpolate to get target power for given frequency */
1271 return (u8
) ar9003_hw_power_interpolate((s32
) freq
,
1273 targetPowerArray
, numPiers
);
1276 static u8
ar9003_hw_eeprom_get_ht40_tgt_pwr(struct ath_hw
*ah
,
1278 u16 freq
, bool is2GHz
)
1281 s32 targetPowerArray
[AR9300_NUM_5G_40_TARGET_POWERS
];
1282 s32 freqArray
[AR9300_NUM_5G_40_TARGET_POWERS
];
1283 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1284 struct cal_tgt_pow_ht
*pEepromTargetPwr
;
1288 numPiers
= AR9300_NUM_2G_40_TARGET_POWERS
;
1289 pEepromTargetPwr
= eep
->calTargetPower2GHT40
;
1290 pFreqBin
= eep
->calTarget_freqbin_2GHT40
;
1292 numPiers
= AR9300_NUM_5G_40_TARGET_POWERS
;
1293 pEepromTargetPwr
= eep
->calTargetPower5GHT40
;
1294 pFreqBin
= eep
->calTarget_freqbin_5GHT40
;
1298 * create array of channels and targetpower from
1299 * targetpower piers stored on eeprom
1301 for (i
= 0; i
< numPiers
; i
++) {
1302 freqArray
[i
] = FBIN2FREQ(pFreqBin
[i
], is2GHz
);
1303 targetPowerArray
[i
] = pEepromTargetPwr
[i
].tPow2x
[rateIndex
];
1306 /* interpolate to get target power for given frequency */
1307 return (u8
) ar9003_hw_power_interpolate((s32
) freq
,
1309 targetPowerArray
, numPiers
);
1312 static u8
ar9003_hw_eeprom_get_cck_tgt_pwr(struct ath_hw
*ah
,
1313 u16 rateIndex
, u16 freq
)
1315 u16 numPiers
= AR9300_NUM_2G_CCK_TARGET_POWERS
, i
;
1316 s32 targetPowerArray
[AR9300_NUM_2G_CCK_TARGET_POWERS
];
1317 s32 freqArray
[AR9300_NUM_2G_CCK_TARGET_POWERS
];
1318 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1319 struct cal_tgt_pow_legacy
*pEepromTargetPwr
= eep
->calTargetPowerCck
;
1320 u8
*pFreqBin
= eep
->calTarget_freqbin_Cck
;
1323 * create array of channels and targetpower from
1324 * targetpower piers stored on eeprom
1326 for (i
= 0; i
< numPiers
; i
++) {
1327 freqArray
[i
] = FBIN2FREQ(pFreqBin
[i
], 1);
1328 targetPowerArray
[i
] = pEepromTargetPwr
[i
].tPow2x
[rateIndex
];
1331 /* interpolate to get target power for given frequency */
1332 return (u8
) ar9003_hw_power_interpolate((s32
) freq
,
1334 targetPowerArray
, numPiers
);
1337 /* Set tx power registers to array of values passed in */
1338 static int ar9003_hw_tx_power_regwrite(struct ath_hw
*ah
, u8
* pPwrArray
)
1340 #define POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
1341 /* make sure forced gain is not set */
1342 REG_WRITE(ah
, 0xa458, 0);
1344 /* Write the OFDM power per rate set */
1346 /* 6 (LSB), 9, 12, 18 (MSB) */
1347 REG_WRITE(ah
, 0xa3c0,
1348 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_6_24
], 24) |
1349 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_6_24
], 16) |
1350 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_6_24
], 8) |
1351 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_6_24
], 0));
1353 /* 24 (LSB), 36, 48, 54 (MSB) */
1354 REG_WRITE(ah
, 0xa3c4,
1355 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_54
], 24) |
1356 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_48
], 16) |
1357 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_36
], 8) |
1358 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_6_24
], 0));
1360 /* Write the CCK power per rate set */
1362 /* 1L (LSB), reserved, 2L, 2S (MSB) */
1363 REG_WRITE(ah
, 0xa3c8,
1364 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_1L_5L
], 24) |
1365 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_1L_5L
], 16) |
1366 /* POW_SM(txPowerTimes2, 8) | this is reserved for AR9003 */
1367 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_1L_5L
], 0));
1369 /* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */
1370 REG_WRITE(ah
, 0xa3cc,
1371 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_11S
], 24) |
1372 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_11L
], 16) |
1373 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_5S
], 8) |
1374 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_1L_5L
], 0)
1377 /* Write the HT20 power per rate set */
1379 /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */
1380 REG_WRITE(ah
, 0xa3d0,
1381 POW_SM(pPwrArray
[ALL_TARGET_HT20_5
], 24) |
1382 POW_SM(pPwrArray
[ALL_TARGET_HT20_4
], 16) |
1383 POW_SM(pPwrArray
[ALL_TARGET_HT20_1_3_9_11_17_19
], 8) |
1384 POW_SM(pPwrArray
[ALL_TARGET_HT20_0_8_16
], 0)
1387 /* 6 (LSB), 7, 12, 13 (MSB) */
1388 REG_WRITE(ah
, 0xa3d4,
1389 POW_SM(pPwrArray
[ALL_TARGET_HT20_13
], 24) |
1390 POW_SM(pPwrArray
[ALL_TARGET_HT20_12
], 16) |
1391 POW_SM(pPwrArray
[ALL_TARGET_HT20_7
], 8) |
1392 POW_SM(pPwrArray
[ALL_TARGET_HT20_6
], 0)
1395 /* 14 (LSB), 15, 20, 21 */
1396 REG_WRITE(ah
, 0xa3e4,
1397 POW_SM(pPwrArray
[ALL_TARGET_HT20_21
], 24) |
1398 POW_SM(pPwrArray
[ALL_TARGET_HT20_20
], 16) |
1399 POW_SM(pPwrArray
[ALL_TARGET_HT20_15
], 8) |
1400 POW_SM(pPwrArray
[ALL_TARGET_HT20_14
], 0)
1403 /* Mixed HT20 and HT40 rates */
1405 /* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */
1406 REG_WRITE(ah
, 0xa3e8,
1407 POW_SM(pPwrArray
[ALL_TARGET_HT40_23
], 24) |
1408 POW_SM(pPwrArray
[ALL_TARGET_HT40_22
], 16) |
1409 POW_SM(pPwrArray
[ALL_TARGET_HT20_23
], 8) |
1410 POW_SM(pPwrArray
[ALL_TARGET_HT20_22
], 0)
1414 * Write the HT40 power per rate set
1415 * correct PAR difference between HT40 and HT20/LEGACY
1416 * 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB)
1418 REG_WRITE(ah
, 0xa3d8,
1419 POW_SM(pPwrArray
[ALL_TARGET_HT40_5
], 24) |
1420 POW_SM(pPwrArray
[ALL_TARGET_HT40_4
], 16) |
1421 POW_SM(pPwrArray
[ALL_TARGET_HT40_1_3_9_11_17_19
], 8) |
1422 POW_SM(pPwrArray
[ALL_TARGET_HT40_0_8_16
], 0)
1425 /* 6 (LSB), 7, 12, 13 (MSB) */
1426 REG_WRITE(ah
, 0xa3dc,
1427 POW_SM(pPwrArray
[ALL_TARGET_HT40_13
], 24) |
1428 POW_SM(pPwrArray
[ALL_TARGET_HT40_12
], 16) |
1429 POW_SM(pPwrArray
[ALL_TARGET_HT40_7
], 8) |
1430 POW_SM(pPwrArray
[ALL_TARGET_HT40_6
], 0)
1433 /* 14 (LSB), 15, 20, 21 */
1434 REG_WRITE(ah
, 0xa3ec,
1435 POW_SM(pPwrArray
[ALL_TARGET_HT40_21
], 24) |
1436 POW_SM(pPwrArray
[ALL_TARGET_HT40_20
], 16) |
1437 POW_SM(pPwrArray
[ALL_TARGET_HT40_15
], 8) |
1438 POW_SM(pPwrArray
[ALL_TARGET_HT40_14
], 0)
1445 static void ar9003_hw_set_target_power_eeprom(struct ath_hw
*ah
, u16 freq
,
1446 u8
*targetPowerValT2
)
1448 /* XXX: hard code for now, need to get from eeprom struct */
1449 u8 ht40PowerIncForPdadc
= 0;
1450 bool is2GHz
= false;
1452 struct ath_common
*common
= ath9k_hw_common(ah
);
1457 targetPowerValT2
[ALL_TARGET_LEGACY_6_24
] =
1458 ar9003_hw_eeprom_get_tgt_pwr(ah
, LEGACY_TARGET_RATE_6_24
, freq
,
1460 targetPowerValT2
[ALL_TARGET_LEGACY_36
] =
1461 ar9003_hw_eeprom_get_tgt_pwr(ah
, LEGACY_TARGET_RATE_36
, freq
,
1463 targetPowerValT2
[ALL_TARGET_LEGACY_48
] =
1464 ar9003_hw_eeprom_get_tgt_pwr(ah
, LEGACY_TARGET_RATE_48
, freq
,
1466 targetPowerValT2
[ALL_TARGET_LEGACY_54
] =
1467 ar9003_hw_eeprom_get_tgt_pwr(ah
, LEGACY_TARGET_RATE_54
, freq
,
1469 targetPowerValT2
[ALL_TARGET_LEGACY_1L_5L
] =
1470 ar9003_hw_eeprom_get_cck_tgt_pwr(ah
, LEGACY_TARGET_RATE_1L_5L
,
1472 targetPowerValT2
[ALL_TARGET_LEGACY_5S
] =
1473 ar9003_hw_eeprom_get_cck_tgt_pwr(ah
, LEGACY_TARGET_RATE_5S
, freq
);
1474 targetPowerValT2
[ALL_TARGET_LEGACY_11L
] =
1475 ar9003_hw_eeprom_get_cck_tgt_pwr(ah
, LEGACY_TARGET_RATE_11L
, freq
);
1476 targetPowerValT2
[ALL_TARGET_LEGACY_11S
] =
1477 ar9003_hw_eeprom_get_cck_tgt_pwr(ah
, LEGACY_TARGET_RATE_11S
, freq
);
1478 targetPowerValT2
[ALL_TARGET_HT20_0_8_16
] =
1479 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_0_8_16
, freq
,
1481 targetPowerValT2
[ALL_TARGET_HT20_1_3_9_11_17_19
] =
1482 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_1_3_9_11_17_19
,
1484 targetPowerValT2
[ALL_TARGET_HT20_4
] =
1485 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_4
, freq
,
1487 targetPowerValT2
[ALL_TARGET_HT20_5
] =
1488 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_5
, freq
,
1490 targetPowerValT2
[ALL_TARGET_HT20_6
] =
1491 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_6
, freq
,
1493 targetPowerValT2
[ALL_TARGET_HT20_7
] =
1494 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_7
, freq
,
1496 targetPowerValT2
[ALL_TARGET_HT20_12
] =
1497 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_12
, freq
,
1499 targetPowerValT2
[ALL_TARGET_HT20_13
] =
1500 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_13
, freq
,
1502 targetPowerValT2
[ALL_TARGET_HT20_14
] =
1503 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_14
, freq
,
1505 targetPowerValT2
[ALL_TARGET_HT20_15
] =
1506 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_15
, freq
,
1508 targetPowerValT2
[ALL_TARGET_HT20_20
] =
1509 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_20
, freq
,
1511 targetPowerValT2
[ALL_TARGET_HT20_21
] =
1512 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_21
, freq
,
1514 targetPowerValT2
[ALL_TARGET_HT20_22
] =
1515 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_22
, freq
,
1517 targetPowerValT2
[ALL_TARGET_HT20_23
] =
1518 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_23
, freq
,
1520 targetPowerValT2
[ALL_TARGET_HT40_0_8_16
] =
1521 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_0_8_16
, freq
,
1522 is2GHz
) + ht40PowerIncForPdadc
;
1523 targetPowerValT2
[ALL_TARGET_HT40_1_3_9_11_17_19
] =
1524 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_1_3_9_11_17_19
,
1526 is2GHz
) + ht40PowerIncForPdadc
;
1527 targetPowerValT2
[ALL_TARGET_HT40_4
] =
1528 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_4
, freq
,
1529 is2GHz
) + ht40PowerIncForPdadc
;
1530 targetPowerValT2
[ALL_TARGET_HT40_5
] =
1531 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_5
, freq
,
1532 is2GHz
) + ht40PowerIncForPdadc
;
1533 targetPowerValT2
[ALL_TARGET_HT40_6
] =
1534 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_6
, freq
,
1535 is2GHz
) + ht40PowerIncForPdadc
;
1536 targetPowerValT2
[ALL_TARGET_HT40_7
] =
1537 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_7
, freq
,
1538 is2GHz
) + ht40PowerIncForPdadc
;
1539 targetPowerValT2
[ALL_TARGET_HT40_12
] =
1540 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_12
, freq
,
1541 is2GHz
) + ht40PowerIncForPdadc
;
1542 targetPowerValT2
[ALL_TARGET_HT40_13
] =
1543 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_13
, freq
,
1544 is2GHz
) + ht40PowerIncForPdadc
;
1545 targetPowerValT2
[ALL_TARGET_HT40_14
] =
1546 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_14
, freq
,
1547 is2GHz
) + ht40PowerIncForPdadc
;
1548 targetPowerValT2
[ALL_TARGET_HT40_15
] =
1549 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_15
, freq
,
1550 is2GHz
) + ht40PowerIncForPdadc
;
1551 targetPowerValT2
[ALL_TARGET_HT40_20
] =
1552 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_20
, freq
,
1553 is2GHz
) + ht40PowerIncForPdadc
;
1554 targetPowerValT2
[ALL_TARGET_HT40_21
] =
1555 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_21
, freq
,
1556 is2GHz
) + ht40PowerIncForPdadc
;
1557 targetPowerValT2
[ALL_TARGET_HT40_22
] =
1558 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_22
, freq
,
1559 is2GHz
) + ht40PowerIncForPdadc
;
1560 targetPowerValT2
[ALL_TARGET_HT40_23
] =
1561 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_23
, freq
,
1562 is2GHz
) + ht40PowerIncForPdadc
;
1564 while (i
< ar9300RateSize
) {
1565 ath_print(common
, ATH_DBG_EEPROM
,
1566 "TPC[%02d] 0x%08x ", i
, targetPowerValT2
[i
]);
1569 ath_print(common
, ATH_DBG_EEPROM
,
1570 "TPC[%02d] 0x%08x ", i
, targetPowerValT2
[i
]);
1573 ath_print(common
, ATH_DBG_EEPROM
,
1574 "TPC[%02d] 0x%08x ", i
, targetPowerValT2
[i
]);
1577 ath_print(common
, ATH_DBG_EEPROM
,
1578 "TPC[%02d] 0x%08x\n", i
, targetPowerValT2
[i
]);
1583 static int ar9003_hw_cal_pier_get(struct ath_hw
*ah
,
1589 int *ptemperature
, int *pvoltage
)
1592 struct ar9300_cal_data_per_freq_op_loop
*pCalPierStruct
;
1594 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1595 struct ath_common
*common
= ath9k_hw_common(ah
);
1597 if (ichain
>= AR9300_MAX_CHAINS
) {
1598 ath_print(common
, ATH_DBG_EEPROM
,
1599 "Invalid chain index, must be less than %d\n",
1604 if (mode
) { /* 5GHz */
1605 if (ipier
>= AR9300_NUM_5G_CAL_PIERS
) {
1606 ath_print(common
, ATH_DBG_EEPROM
,
1607 "Invalid 5GHz cal pier index, must "
1608 "be less than %d\n",
1609 AR9300_NUM_5G_CAL_PIERS
);
1612 pCalPier
= &(eep
->calFreqPier5G
[ipier
]);
1613 pCalPierStruct
= &(eep
->calPierData5G
[ichain
][ipier
]);
1616 if (ipier
>= AR9300_NUM_2G_CAL_PIERS
) {
1617 ath_print(common
, ATH_DBG_EEPROM
,
1618 "Invalid 2GHz cal pier index, must "
1619 "be less than %d\n", AR9300_NUM_2G_CAL_PIERS
);
1623 pCalPier
= &(eep
->calFreqPier2G
[ipier
]);
1624 pCalPierStruct
= &(eep
->calPierData2G
[ichain
][ipier
]);
1628 *pfrequency
= FBIN2FREQ(*pCalPier
, is2GHz
);
1629 *pcorrection
= pCalPierStruct
->refPower
;
1630 *ptemperature
= pCalPierStruct
->tempMeas
;
1631 *pvoltage
= pCalPierStruct
->voltMeas
;
1636 static int ar9003_hw_power_control_override(struct ath_hw
*ah
,
1639 int *voltage
, int *temperature
)
1642 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1644 REG_RMW(ah
, AR_PHY_TPC_11_B0
,
1645 (correction
[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S
),
1646 AR_PHY_TPC_OLPC_GAIN_DELTA
);
1647 REG_RMW(ah
, AR_PHY_TPC_11_B1
,
1648 (correction
[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S
),
1649 AR_PHY_TPC_OLPC_GAIN_DELTA
);
1650 REG_RMW(ah
, AR_PHY_TPC_11_B2
,
1651 (correction
[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S
),
1652 AR_PHY_TPC_OLPC_GAIN_DELTA
);
1654 /* enable open loop power control on chip */
1655 REG_RMW(ah
, AR_PHY_TPC_6_B0
,
1656 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S
),
1657 AR_PHY_TPC_6_ERROR_EST_MODE
);
1658 REG_RMW(ah
, AR_PHY_TPC_6_B1
,
1659 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S
),
1660 AR_PHY_TPC_6_ERROR_EST_MODE
);
1661 REG_RMW(ah
, AR_PHY_TPC_6_B2
,
1662 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S
),
1663 AR_PHY_TPC_6_ERROR_EST_MODE
);
1666 * enable temperature compensation
1667 * Need to use register names
1669 if (frequency
< 4000)
1670 tempSlope
= eep
->modalHeader2G
.tempSlope
;
1672 tempSlope
= eep
->modalHeader5G
.tempSlope
;
1674 REG_RMW_FIELD(ah
, AR_PHY_TPC_19
, AR_PHY_TPC_19_ALPHA_THERM
, tempSlope
);
1675 REG_RMW_FIELD(ah
, AR_PHY_TPC_18
, AR_PHY_TPC_18_THERM_CAL_VALUE
,
1681 /* Apply the recorded correction values. */
1682 static int ar9003_hw_calibration_apply(struct ath_hw
*ah
, int frequency
)
1684 int ichain
, ipier
, npier
;
1686 int lfrequency
[AR9300_MAX_CHAINS
],
1687 lcorrection
[AR9300_MAX_CHAINS
],
1688 ltemperature
[AR9300_MAX_CHAINS
], lvoltage
[AR9300_MAX_CHAINS
];
1689 int hfrequency
[AR9300_MAX_CHAINS
],
1690 hcorrection
[AR9300_MAX_CHAINS
],
1691 htemperature
[AR9300_MAX_CHAINS
], hvoltage
[AR9300_MAX_CHAINS
];
1693 int correction
[AR9300_MAX_CHAINS
],
1694 voltage
[AR9300_MAX_CHAINS
], temperature
[AR9300_MAX_CHAINS
];
1695 int pfrequency
, pcorrection
, ptemperature
, pvoltage
;
1696 struct ath_common
*common
= ath9k_hw_common(ah
);
1698 mode
= (frequency
>= 4000);
1700 npier
= AR9300_NUM_5G_CAL_PIERS
;
1702 npier
= AR9300_NUM_2G_CAL_PIERS
;
1704 for (ichain
= 0; ichain
< AR9300_MAX_CHAINS
; ichain
++) {
1705 lfrequency
[ichain
] = 0;
1706 hfrequency
[ichain
] = 100000;
1708 /* identify best lower and higher frequency calibration measurement */
1709 for (ichain
= 0; ichain
< AR9300_MAX_CHAINS
; ichain
++) {
1710 for (ipier
= 0; ipier
< npier
; ipier
++) {
1711 if (!ar9003_hw_cal_pier_get(ah
, mode
, ipier
, ichain
,
1712 &pfrequency
, &pcorrection
,
1713 &ptemperature
, &pvoltage
)) {
1714 fdiff
= frequency
- pfrequency
;
1717 * this measurement is higher than
1718 * our desired frequency
1721 if (hfrequency
[ichain
] <= 0 ||
1722 hfrequency
[ichain
] >= 100000 ||
1724 (frequency
- hfrequency
[ichain
])) {
1727 * frequency measurement
1729 hfrequency
[ichain
] = pfrequency
;
1730 hcorrection
[ichain
] =
1732 htemperature
[ichain
] =
1734 hvoltage
[ichain
] = pvoltage
;
1738 if (lfrequency
[ichain
] <= 0
1740 (frequency
- lfrequency
[ichain
])) {
1743 * frequency measurement
1745 lfrequency
[ichain
] = pfrequency
;
1746 lcorrection
[ichain
] =
1748 ltemperature
[ichain
] =
1750 lvoltage
[ichain
] = pvoltage
;
1758 for (ichain
= 0; ichain
< AR9300_MAX_CHAINS
; ichain
++) {
1759 ath_print(common
, ATH_DBG_EEPROM
,
1760 "ch=%d f=%d low=%d %d h=%d %d\n",
1761 ichain
, frequency
, lfrequency
[ichain
],
1762 lcorrection
[ichain
], hfrequency
[ichain
],
1763 hcorrection
[ichain
]);
1764 /* they're the same, so just pick one */
1765 if (hfrequency
[ichain
] == lfrequency
[ichain
]) {
1766 correction
[ichain
] = lcorrection
[ichain
];
1767 voltage
[ichain
] = lvoltage
[ichain
];
1768 temperature
[ichain
] = ltemperature
[ichain
];
1770 /* the low frequency is good */
1771 else if (frequency
- lfrequency
[ichain
] < 1000) {
1772 /* so is the high frequency, interpolate */
1773 if (hfrequency
[ichain
] - frequency
< 1000) {
1775 correction
[ichain
] = lcorrection
[ichain
] +
1776 (((frequency
- lfrequency
[ichain
]) *
1777 (hcorrection
[ichain
] -
1778 lcorrection
[ichain
])) /
1779 (hfrequency
[ichain
] - lfrequency
[ichain
]));
1781 temperature
[ichain
] = ltemperature
[ichain
] +
1782 (((frequency
- lfrequency
[ichain
]) *
1783 (htemperature
[ichain
] -
1784 ltemperature
[ichain
])) /
1785 (hfrequency
[ichain
] - lfrequency
[ichain
]));
1790 lfrequency
[ichain
]) * (hvoltage
[ichain
] -
1792 / (hfrequency
[ichain
] -
1793 lfrequency
[ichain
]));
1795 /* only low is good, use it */
1797 correction
[ichain
] = lcorrection
[ichain
];
1798 temperature
[ichain
] = ltemperature
[ichain
];
1799 voltage
[ichain
] = lvoltage
[ichain
];
1802 /* only high is good, use it */
1803 else if (hfrequency
[ichain
] - frequency
< 1000) {
1804 correction
[ichain
] = hcorrection
[ichain
];
1805 temperature
[ichain
] = htemperature
[ichain
];
1806 voltage
[ichain
] = hvoltage
[ichain
];
1807 } else { /* nothing is good, presume 0???? */
1808 correction
[ichain
] = 0;
1809 temperature
[ichain
] = 0;
1810 voltage
[ichain
] = 0;
1814 ar9003_hw_power_control_override(ah
, frequency
, correction
, voltage
,
1817 ath_print(common
, ATH_DBG_EEPROM
,
1818 "for frequency=%d, calibration correction = %d %d %d\n",
1819 frequency
, correction
[0], correction
[1], correction
[2]);
1824 static u16
ar9003_hw_get_direct_edge_power(struct ar9300_eeprom
*eep
,
1829 struct cal_ctl_data_2g
*ctl_2g
= eep
->ctlPowerData_2G
;
1830 struct cal_ctl_data_5g
*ctl_5g
= eep
->ctlPowerData_5G
;
1833 return CTL_EDGE_TPOWER(ctl_2g
[idx
].ctlEdges
[edge
]);
1835 return CTL_EDGE_TPOWER(ctl_5g
[idx
].ctlEdges
[edge
]);
1838 static u16
ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom
*eep
,
1844 struct cal_ctl_data_2g
*ctl_2g
= eep
->ctlPowerData_2G
;
1845 struct cal_ctl_data_5g
*ctl_5g
= eep
->ctlPowerData_5G
;
1847 u8
*ctl_freqbin
= is2GHz
?
1848 &eep
->ctl_freqbin_2G
[idx
][0] :
1849 &eep
->ctl_freqbin_5G
[idx
][0];
1852 if (ath9k_hw_fbin2freq(ctl_freqbin
[edge
- 1], 1) < freq
&&
1853 CTL_EDGE_FLAGS(ctl_2g
[idx
].ctlEdges
[edge
- 1]))
1854 return CTL_EDGE_TPOWER(ctl_2g
[idx
].ctlEdges
[edge
- 1]);
1856 if (ath9k_hw_fbin2freq(ctl_freqbin
[edge
- 1], 0) < freq
&&
1857 CTL_EDGE_FLAGS(ctl_5g
[idx
].ctlEdges
[edge
- 1]))
1858 return CTL_EDGE_TPOWER(ctl_5g
[idx
].ctlEdges
[edge
- 1]);
1861 return AR9300_MAX_RATE_POWER
;
1865 * Find the maximum conformance test limit for the given channel and CTL info
1867 static u16
ar9003_hw_get_max_edge_power(struct ar9300_eeprom
*eep
,
1868 u16 freq
, int idx
, bool is2GHz
)
1870 u16 twiceMaxEdgePower
= AR9300_MAX_RATE_POWER
;
1871 u8
*ctl_freqbin
= is2GHz
?
1872 &eep
->ctl_freqbin_2G
[idx
][0] :
1873 &eep
->ctl_freqbin_5G
[idx
][0];
1874 u16 num_edges
= is2GHz
?
1875 AR9300_NUM_BAND_EDGES_2G
: AR9300_NUM_BAND_EDGES_5G
;
1878 /* Get the edge power */
1880 (edge
< num_edges
) && (ctl_freqbin
[edge
] != AR9300_BCHAN_UNUSED
);
1883 * If there's an exact channel match or an inband flag set
1884 * on the lower channel use the given rdEdgePower
1886 if (freq
== ath9k_hw_fbin2freq(ctl_freqbin
[edge
], is2GHz
)) {
1888 ar9003_hw_get_direct_edge_power(eep
, idx
,
1891 } else if ((edge
> 0) &&
1892 (freq
< ath9k_hw_fbin2freq(ctl_freqbin
[edge
],
1895 ar9003_hw_get_indirect_edge_power(eep
, idx
,
1899 * Leave loop - no more affecting edges possible in
1900 * this monotonic increasing list
1905 return twiceMaxEdgePower
;
1908 static void ar9003_hw_set_power_per_rate_table(struct ath_hw
*ah
,
1909 struct ath9k_channel
*chan
,
1910 u8
*pPwrArray
, u16 cfgCtl
,
1911 u8 twiceAntennaReduction
,
1912 u8 twiceMaxRegulatoryPower
,
1915 struct ath_regulatory
*regulatory
= ath9k_hw_regulatory(ah
);
1916 struct ath_common
*common
= ath9k_hw_common(ah
);
1917 struct ar9300_eeprom
*pEepData
= &ah
->eeprom
.ar9300_eep
;
1918 u16 twiceMaxEdgePower
= AR9300_MAX_RATE_POWER
;
1919 static const u16 tpScaleReductionTable
[5] = {
1920 0, 3, 6, 9, AR9300_MAX_RATE_POWER
1923 int16_t twiceLargestAntenna
;
1924 u16 scaledPower
= 0, minCtlPower
, maxRegAllowedPower
;
1925 u16 ctlModesFor11a
[] = {
1926 CTL_11A
, CTL_5GHT20
, CTL_11A_EXT
, CTL_5GHT40
1928 u16 ctlModesFor11g
[] = {
1929 CTL_11B
, CTL_11G
, CTL_2GHT20
, CTL_11B_EXT
,
1930 CTL_11G_EXT
, CTL_2GHT40
1932 u16 numCtlModes
, *pCtlMode
, ctlMode
, freq
;
1933 struct chan_centers centers
;
1936 u16 twiceMinEdgePower
;
1937 bool is2ghz
= IS_CHAN_2GHZ(chan
);
1939 ath9k_hw_get_channel_centers(ah
, chan
, ¢ers
);
1941 /* Compute TxPower reduction due to Antenna Gain */
1943 twiceLargestAntenna
= pEepData
->modalHeader2G
.antennaGain
;
1945 twiceLargestAntenna
= pEepData
->modalHeader5G
.antennaGain
;
1947 twiceLargestAntenna
= (int16_t)min((twiceAntennaReduction
) -
1948 twiceLargestAntenna
, 0);
1951 * scaledPower is the minimum of the user input power level
1952 * and the regulatory allowed power level
1954 maxRegAllowedPower
= twiceMaxRegulatoryPower
+ twiceLargestAntenna
;
1956 if (regulatory
->tp_scale
!= ATH9K_TP_SCALE_MAX
) {
1957 maxRegAllowedPower
-=
1958 (tpScaleReductionTable
[(regulatory
->tp_scale
)] * 2);
1961 scaledPower
= min(powerLimit
, maxRegAllowedPower
);
1964 * Reduce scaled Power by number of chains active to get
1965 * to per chain tx power level
1967 switch (ar5416_get_ntxchains(ah
->txchainmask
)) {
1971 scaledPower
-= REDUCE_SCALED_POWER_BY_TWO_CHAIN
;
1974 scaledPower
-= REDUCE_SCALED_POWER_BY_THREE_CHAIN
;
1978 scaledPower
= max((u16
)0, scaledPower
);
1981 * Get target powers from EEPROM - our baseline for TX Power
1984 /* Setup for CTL modes */
1985 /* CTL_11B, CTL_11G, CTL_2GHT20 */
1987 ARRAY_SIZE(ctlModesFor11g
) -
1988 SUB_NUM_CTL_MODES_AT_2G_40
;
1989 pCtlMode
= ctlModesFor11g
;
1990 if (IS_CHAN_HT40(chan
))
1992 numCtlModes
= ARRAY_SIZE(ctlModesFor11g
);
1994 /* Setup for CTL modes */
1995 /* CTL_11A, CTL_5GHT20 */
1996 numCtlModes
= ARRAY_SIZE(ctlModesFor11a
) -
1997 SUB_NUM_CTL_MODES_AT_5G_40
;
1998 pCtlMode
= ctlModesFor11a
;
1999 if (IS_CHAN_HT40(chan
))
2001 numCtlModes
= ARRAY_SIZE(ctlModesFor11a
);
2005 * For MIMO, need to apply regulatory caps individually across
2006 * dynamically running modes: CCK, OFDM, HT20, HT40
2008 * The outer loop walks through each possible applicable runtime mode.
2009 * The inner loop walks through each ctlIndex entry in EEPROM.
2010 * The ctl value is encoded as [7:4] == test group, [3:0] == test mode.
2012 for (ctlMode
= 0; ctlMode
< numCtlModes
; ctlMode
++) {
2013 bool isHt40CtlMode
= (pCtlMode
[ctlMode
] == CTL_5GHT40
) ||
2014 (pCtlMode
[ctlMode
] == CTL_2GHT40
);
2016 freq
= centers
.synth_center
;
2017 else if (pCtlMode
[ctlMode
] & EXT_ADDITIVE
)
2018 freq
= centers
.ext_center
;
2020 freq
= centers
.ctl_center
;
2022 ath_print(common
, ATH_DBG_REGULATORY
,
2023 "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
2024 "EXT_ADDITIVE %d\n",
2025 ctlMode
, numCtlModes
, isHt40CtlMode
,
2026 (pCtlMode
[ctlMode
] & EXT_ADDITIVE
));
2028 /* walk through each CTL index stored in EEPROM */
2030 ctlIndex
= pEepData
->ctlIndex_2G
;
2031 ctlNum
= AR9300_NUM_CTLS_2G
;
2033 ctlIndex
= pEepData
->ctlIndex_5G
;
2034 ctlNum
= AR9300_NUM_CTLS_5G
;
2037 for (i
= 0; (i
< ctlNum
) && ctlIndex
[i
]; i
++) {
2038 ath_print(common
, ATH_DBG_REGULATORY
,
2039 "LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
2040 "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
2042 i
, cfgCtl
, pCtlMode
[ctlMode
], ctlIndex
[i
],
2046 * compare test group from regulatory
2047 * channel list with test mode from pCtlMode
2050 if ((((cfgCtl
& ~CTL_MODE_M
) |
2051 (pCtlMode
[ctlMode
] & CTL_MODE_M
)) ==
2053 (((cfgCtl
& ~CTL_MODE_M
) |
2054 (pCtlMode
[ctlMode
] & CTL_MODE_M
)) ==
2055 ((ctlIndex
[i
] & CTL_MODE_M
) |
2058 ar9003_hw_get_max_edge_power(pEepData
,
2062 if ((cfgCtl
& ~CTL_MODE_M
) == SD_NO_CTL
)
2064 * Find the minimum of all CTL
2065 * edge powers that apply to
2069 min(twiceMaxEdgePower
,
2080 minCtlPower
= (u8
)min(twiceMaxEdgePower
, scaledPower
);
2082 ath_print(common
, ATH_DBG_REGULATORY
,
2083 "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d "
2084 "sP %d minCtlPwr %d\n",
2085 ctlMode
, pCtlMode
[ctlMode
], twiceMaxEdgePower
,
2086 scaledPower
, minCtlPower
);
2088 /* Apply ctl mode to correct target power set */
2089 switch (pCtlMode
[ctlMode
]) {
2091 for (i
= ALL_TARGET_LEGACY_1L_5L
;
2092 i
<= ALL_TARGET_LEGACY_11S
; i
++)
2094 (u8
)min((u16
)pPwrArray
[i
],
2099 for (i
= ALL_TARGET_LEGACY_6_24
;
2100 i
<= ALL_TARGET_LEGACY_54
; i
++)
2102 (u8
)min((u16
)pPwrArray
[i
],
2107 for (i
= ALL_TARGET_HT20_0_8_16
;
2108 i
<= ALL_TARGET_HT20_21
; i
++)
2110 (u8
)min((u16
)pPwrArray
[i
],
2112 pPwrArray
[ALL_TARGET_HT20_22
] =
2113 (u8
)min((u16
)pPwrArray
[ALL_TARGET_HT20_22
],
2115 pPwrArray
[ALL_TARGET_HT20_23
] =
2116 (u8
)min((u16
)pPwrArray
[ALL_TARGET_HT20_23
],
2121 for (i
= ALL_TARGET_HT40_0_8_16
;
2122 i
<= ALL_TARGET_HT40_23
; i
++)
2124 (u8
)min((u16
)pPwrArray
[i
],
2130 } /* end ctl mode checking */
2133 static void ath9k_hw_ar9300_set_txpower(struct ath_hw
*ah
,
2134 struct ath9k_channel
*chan
, u16 cfgCtl
,
2135 u8 twiceAntennaReduction
,
2136 u8 twiceMaxRegulatoryPower
,
2139 struct ath_common
*common
= ath9k_hw_common(ah
);
2140 u8 targetPowerValT2
[ar9300RateSize
];
2143 ar9003_hw_set_target_power_eeprom(ah
, chan
->channel
, targetPowerValT2
);
2144 ar9003_hw_set_power_per_rate_table(ah
, chan
,
2145 targetPowerValT2
, cfgCtl
,
2146 twiceAntennaReduction
,
2147 twiceMaxRegulatoryPower
,
2150 while (i
< ar9300RateSize
) {
2151 ath_print(common
, ATH_DBG_EEPROM
,
2152 "TPC[%02d] 0x%08x ", i
, targetPowerValT2
[i
]);
2154 ath_print(common
, ATH_DBG_EEPROM
,
2155 "TPC[%02d] 0x%08x ", i
, targetPowerValT2
[i
]);
2157 ath_print(common
, ATH_DBG_EEPROM
,
2158 "TPC[%02d] 0x%08x ", i
, targetPowerValT2
[i
]);
2160 ath_print(common
, ATH_DBG_EEPROM
,
2161 "TPC[%02d] 0x%08x\n\n", i
, targetPowerValT2
[i
]);
2165 /* Write target power array to registers */
2166 ar9003_hw_tx_power_regwrite(ah
, targetPowerValT2
);
2169 * This is the TX power we send back to driver core,
2170 * and it can use to pass to userspace to display our
2171 * currently configured TX power setting.
2173 * Since power is rate dependent, use one of the indices
2174 * from the AR9300_Rates enum to select an entry from
2175 * targetPowerValT2[] to report. Currently returns the
2176 * power for HT40 MCS 0, HT20 MCS 0, or OFDM 6 Mbps
2177 * as CCK power is less interesting (?).
2179 i
= ALL_TARGET_LEGACY_6_24
; /* legacy */
2180 if (IS_CHAN_HT40(chan
))
2181 i
= ALL_TARGET_HT40_0_8_16
; /* ht40 */
2182 else if (IS_CHAN_HT20(chan
))
2183 i
= ALL_TARGET_HT20_0_8_16
; /* ht20 */
2185 ah
->txpower_limit
= targetPowerValT2
[i
];
2187 ar9003_hw_calibration_apply(ah
, chan
->channel
);
2190 static u16
ath9k_hw_ar9300_get_spur_channel(struct ath_hw
*ah
,
2196 s32
ar9003_hw_get_tx_gain_idx(struct ath_hw
*ah
)
2198 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
2200 return (eep
->baseEepHeader
.txrxgain
>> 4) & 0xf; /* bits 7:4 */
2203 s32
ar9003_hw_get_rx_gain_idx(struct ath_hw
*ah
)
2205 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
2207 return (eep
->baseEepHeader
.txrxgain
) & 0xf; /* bits 3:0 */
2210 const struct eeprom_ops eep_ar9300_ops
= {
2211 .check_eeprom
= ath9k_hw_ar9300_check_eeprom
,
2212 .get_eeprom
= ath9k_hw_ar9300_get_eeprom
,
2213 .fill_eeprom
= ath9k_hw_ar9300_fill_eeprom
,
2214 .get_eeprom_ver
= ath9k_hw_ar9300_get_eeprom_ver
,
2215 .get_eeprom_rev
= ath9k_hw_ar9300_get_eeprom_rev
,
2216 .get_num_ant_config
= ath9k_hw_ar9300_get_num_ant_config
,
2217 .get_eeprom_antenna_cfg
= ath9k_hw_ar9300_get_eeprom_antenna_cfg
,
2218 .set_board_values
= ath9k_hw_ar9300_set_board_values
,
2219 .set_addac
= ath9k_hw_ar9300_set_addac
,
2220 .set_txpower
= ath9k_hw_ar9300_set_txpower
,
2221 .get_spur_channel
= ath9k_hw_ar9300_get_spur_channel