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 static const struct ar9300_eeprom ar9300_default
= {
61 .macAddr
= {1, 2, 3, 4, 5, 6},
62 .custData
= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
63 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
65 .regDmn
= { LE16(0), LE16(0x1f) },
66 .txrxMask
= 0x77, /* 4 bits tx and 4 bits rx */
68 .opFlags
= AR9300_OPFLAGS_11G
| AR9300_OPFLAGS_11A
,
72 .blueToothOptions
= 0,
74 .deviceType
= 5, /* takes lower byte in eeprom location */
75 .pwrTableOffset
= AR9300_PWR_TABLE_OFFSET
,
76 .params_for_tuning_caps
= {0, 0},
77 .featureEnable
= 0x0c,
79 * bit0 - enable tx temp comp - disabled
80 * bit1 - enable tx volt comp - disabled
81 * bit2 - enable fastClock - enabled
82 * bit3 - enable doubling - enabled
83 * bit4 - enable internal regulator - disabled
84 * bit5 - enable pa predistortion - disabled
86 .miscConfiguration
= 0, /* bit0 - turn down drivestrength */
87 .eepromWriteEnableGpio
= 3,
90 .rxBandSelectGpio
= 0xff,
95 /* ar9300_modal_eep_header 2g */
96 /* 4 idle,t1,t2,b(4 bits per setting) */
97 .antCtrlCommon
= LE32(0x110),
98 /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
99 .antCtrlCommon2
= LE32(0x22222),
102 * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
103 * rx1, rx12, b (2 bits each)
105 .antCtrlChain
= { LE16(0x150), LE16(0x150), LE16(0x150) },
108 * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db
109 * for ar9280 (0xa20c/b20c 5:0)
111 .xatten1DB
= {0, 0, 0},
114 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
115 * for ar9280 (0xa20c/b20c 16:12
117 .xatten1Margin
= {0, 0, 0},
122 * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
123 * channels in usual fbin coding format
125 .spurChans
= {0, 0, 0, 0, 0},
128 * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
129 * if the register is per chain
131 .noiseFloorThreshCh
= {-1, 0, 0},
132 .ob
= {1, 1, 1},/* 3 chain */
133 .db_stage2
= {1, 1, 1}, /* 3 chain */
134 .db_stage3
= {0, 0, 0},
135 .db_stage4
= {0, 0, 0},
137 .txFrameToDataStart
= 0x0e,
138 .txFrameToPaOn
= 0x0e,
139 .txClip
= 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
141 .switchSettling
= 0x2c,
142 .adcDesiredSize
= -30,
145 .txFrameToXpaOn
= 0xe,
147 .papdRateMaskHt20
= LE32(0x80c080),
148 .papdRateMaskHt40
= LE32(0x80c080),
150 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
151 0, 0, 0, 0, 0, 0, 0, 0
159 /* ar9300_cal_data_per_freq_op_loop 2g */
161 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
162 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
163 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
165 .calTarget_freqbin_Cck
= {
169 .calTarget_freqbin_2G
= {
174 .calTarget_freqbin_2GHT20
= {
179 .calTarget_freqbin_2GHT40
= {
184 .calTargetPowerCck
= {
185 /* 1L-5L,5S,11L,11S */
186 { {36, 36, 36, 36} },
187 { {36, 36, 36, 36} },
189 .calTargetPower2G
= {
191 { {32, 32, 28, 24} },
192 { {32, 32, 28, 24} },
193 { {32, 32, 28, 24} },
195 .calTargetPower2GHT20
= {
196 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
197 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
198 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
200 .calTargetPower2GHT40
= {
201 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
202 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
203 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
206 0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
207 0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
237 /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
238 /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
239 /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
240 /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
244 /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
245 /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
246 /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
251 /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
252 /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
258 /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
259 /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
260 /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
261 /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
265 /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
266 /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
267 /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
271 /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
272 /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
273 /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
278 /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
279 /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
280 /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
285 /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
286 /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
287 /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
288 /* Data[11].ctlEdges[3].bChannel */
293 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
294 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
295 { { {60, 1}, {60, 0}, {60, 0}, {60, 1} } },
297 { { {60, 1}, {60, 0}, {0, 0}, {0, 0} } },
298 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
299 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
301 { { {60, 0}, {60, 1}, {60, 1}, {60, 0} } },
302 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
303 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
305 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
306 { { {60, 0}, {60, 1}, {60, 1}, {60, 1} } },
309 /* 4 idle,t1,t2,b (4 bits per setting) */
310 .antCtrlCommon
= LE32(0x110),
311 /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
312 .antCtrlCommon2
= LE32(0x22222),
313 /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
315 LE16(0x000), LE16(0x000), LE16(0x000),
317 /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
318 .xatten1DB
= {0, 0, 0},
321 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
322 * for merlin (0xa20c/b20c 16:12
324 .xatten1Margin
= {0, 0, 0},
327 /* spurChans spur channels in usual fbin coding format */
328 .spurChans
= {0, 0, 0, 0, 0},
329 /* noiseFloorThreshCh Check if the register is per chain */
330 .noiseFloorThreshCh
= {-1, 0, 0},
331 .ob
= {3, 3, 3}, /* 3 chain */
332 .db_stage2
= {3, 3, 3}, /* 3 chain */
333 .db_stage3
= {3, 3, 3}, /* doesn't exist for 2G */
334 .db_stage4
= {3, 3, 3}, /* don't exist for 2G */
336 .txFrameToDataStart
= 0x0e,
337 .txFrameToPaOn
= 0x0e,
338 .txClip
= 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
340 .switchSettling
= 0x2d,
341 .adcDesiredSize
= -30,
344 .txFrameToXpaOn
= 0xe,
346 .papdRateMaskHt20
= LE32(0xf0e0e0),
347 .papdRateMaskHt40
= LE32(0xf0e0e0),
349 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
350 0, 0, 0, 0, 0, 0, 0, 0
396 .calTarget_freqbin_5G
= {
406 .calTarget_freqbin_5GHT20
= {
416 .calTarget_freqbin_5GHT40
= {
426 .calTargetPower5G
= {
428 { {20, 20, 20, 10} },
429 { {20, 20, 20, 10} },
430 { {20, 20, 20, 10} },
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} },
437 .calTargetPower5GHT20
= {
439 * 0_8_16,1-3_9-11_17-19,
440 * 4,5,6,7,12,13,14,15,20,21,22,23
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} },
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} },
451 .calTargetPower5GHT40
= {
453 * 0_8_16,1-3_9-11_17-19,
454 * 4,5,6,7,12,13,14,15,20,21,22,23
456 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
457 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
458 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
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} },
466 0x10, 0x16, 0x18, 0x40, 0x46,
467 0x48, 0x30, 0x36, 0x38
471 /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
472 /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
473 /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
474 /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
475 /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
476 /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
477 /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
478 /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
481 /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
482 /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
483 /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
484 /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
485 /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
486 /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
487 /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
488 /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
492 /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
493 /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
494 /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
495 /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
496 /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
497 /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
498 /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
499 /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
503 /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
504 /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
505 /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
506 /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
507 /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
508 /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
509 /* Data[3].ctlEdges[6].bChannel */ 0xFF,
510 /* Data[3].ctlEdges[7].bChannel */ 0xFF,
514 /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
515 /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
516 /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
517 /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
518 /* Data[4].ctlEdges[4].bChannel */ 0xFF,
519 /* Data[4].ctlEdges[5].bChannel */ 0xFF,
520 /* Data[4].ctlEdges[6].bChannel */ 0xFF,
521 /* Data[4].ctlEdges[7].bChannel */ 0xFF,
525 /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
526 /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
527 /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
528 /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
529 /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
530 /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
531 /* Data[5].ctlEdges[6].bChannel */ 0xFF,
532 /* Data[5].ctlEdges[7].bChannel */ 0xFF
536 /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
537 /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
538 /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
539 /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
540 /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
541 /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
542 /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
543 /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
547 /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
548 /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
549 /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
550 /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
551 /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
552 /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
553 /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
554 /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
558 /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
559 /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
560 /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
561 /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
562 /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
563 /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
564 /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
565 /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
571 {60, 1}, {60, 1}, {60, 1}, {60, 1},
572 {60, 1}, {60, 1}, {60, 1}, {60, 0},
577 {60, 1}, {60, 1}, {60, 1}, {60, 1},
578 {60, 1}, {60, 1}, {60, 1}, {60, 0},
583 {60, 0}, {60, 1}, {60, 0}, {60, 1},
584 {60, 1}, {60, 1}, {60, 1}, {60, 1},
589 {60, 0}, {60, 1}, {60, 1}, {60, 0},
590 {60, 1}, {60, 0}, {60, 0}, {60, 0},
595 {60, 1}, {60, 1}, {60, 1}, {60, 0},
596 {60, 0}, {60, 0}, {60, 0}, {60, 0},
601 {60, 1}, {60, 1}, {60, 1}, {60, 1},
602 {60, 1}, {60, 0}, {60, 0}, {60, 0},
607 {60, 1}, {60, 1}, {60, 1}, {60, 1},
608 {60, 1}, {60, 1}, {60, 1}, {60, 1},
613 {60, 1}, {60, 1}, {60, 0}, {60, 1},
614 {60, 1}, {60, 1}, {60, 1}, {60, 0},
619 {60, 1}, {60, 0}, {60, 1}, {60, 1},
620 {60, 1}, {60, 1}, {60, 0}, {60, 1},
626 static u16
ath9k_hw_fbin2freq(u8 fbin
, bool is2GHz
)
628 if (fbin
== AR9300_BCHAN_UNUSED
)
631 return (u16
) ((is2GHz
) ? (2300 + fbin
) : (4800 + 5 * fbin
));
634 static int ath9k_hw_ar9300_check_eeprom(struct ath_hw
*ah
)
639 static u32
ath9k_hw_ar9300_get_eeprom(struct ath_hw
*ah
,
640 enum eeprom_param param
)
642 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
643 struct ar9300_base_eep_hdr
*pBase
= &eep
->baseEepHeader
;
647 return eep
->macAddr
[0] << 8 | eep
->macAddr
[1];
649 return eep
->macAddr
[2] << 8 | eep
->macAddr
[3];
651 return eep
->macAddr
[4] << 8 | eep
->macAddr
[5];
653 return le16_to_cpu(pBase
->regDmn
[0]);
655 return le16_to_cpu(pBase
->regDmn
[1]);
657 return pBase
->deviceCap
;
659 return pBase
->opCapFlags
.opFlags
;
661 return pBase
->rfSilent
;
663 return (pBase
->txrxMask
>> 4) & 0xf;
665 return pBase
->txrxMask
& 0xf;
666 case EEP_DRIVE_STRENGTH
:
667 #define AR9300_EEP_BASE_DRIV_STRENGTH 0x1
668 return pBase
->miscConfiguration
& AR9300_EEP_BASE_DRIV_STRENGTH
;
669 case EEP_INTERNAL_REGULATOR
:
670 /* Bit 4 is internal regulator flag */
671 return (pBase
->featureEnable
& 0x10) >> 4;
673 return le32_to_cpu(pBase
->swreg
);
675 return !!(pBase
->featureEnable
& BIT(5));
681 static bool ar9300_eeprom_read_byte(struct ath_common
*common
, int address
,
686 if (unlikely(!ath9k_hw_nvram_read(common
, address
/ 2, &val
)))
689 *buffer
= (val
>> (8 * (address
% 2))) & 0xff;
693 static bool ar9300_eeprom_read_word(struct ath_common
*common
, int address
,
698 if (unlikely(!ath9k_hw_nvram_read(common
, address
/ 2, &val
)))
701 buffer
[0] = val
>> 8;
702 buffer
[1] = val
& 0xff;
707 static bool ar9300_read_eeprom(struct ath_hw
*ah
, int address
, u8
*buffer
,
710 struct ath_common
*common
= ath9k_hw_common(ah
);
713 if ((address
< 0) || ((address
+ count
) / 2 > AR9300_EEPROM_SIZE
- 1)) {
714 ath_print(common
, ATH_DBG_EEPROM
,
715 "eeprom address not in range\n");
720 * Since we're reading the bytes in reverse order from a little-endian
721 * word stream, an even address means we only use the lower half of
722 * the 16-bit word at that address
724 if (address
% 2 == 0) {
725 if (!ar9300_eeprom_read_byte(common
, address
--, buffer
++))
731 for (i
= 0; i
< count
/ 2; i
++) {
732 if (!ar9300_eeprom_read_word(common
, address
, buffer
))
740 if (!ar9300_eeprom_read_byte(common
, address
, buffer
))
746 ath_print(common
, ATH_DBG_EEPROM
,
747 "unable to read eeprom region at offset %d\n", address
);
751 static void ar9300_comp_hdr_unpack(u8
*best
, int *code
, int *reference
,
752 int *length
, int *major
, int *minor
)
754 unsigned long value
[4];
760 *code
= ((value
[0] >> 5) & 0x0007);
761 *reference
= (value
[0] & 0x001f) | ((value
[1] >> 2) & 0x0020);
762 *length
= ((value
[1] << 4) & 0x07f0) | ((value
[2] >> 4) & 0x000f);
763 *major
= (value
[2] & 0x000f);
764 *minor
= (value
[3] & 0x00ff);
767 static u16
ar9300_comp_cksum(u8
*data
, int dsize
)
769 int it
, checksum
= 0;
771 for (it
= 0; it
< dsize
; it
++) {
772 checksum
+= data
[it
];
779 static bool ar9300_uncompress_block(struct ath_hw
*ah
,
789 struct ath_common
*common
= ath9k_hw_common(ah
);
793 for (it
= 0; it
< size
; it
+= (length
+2)) {
797 length
= block
[it
+1];
800 if (length
> 0 && spot
>= 0 && spot
+length
<= mdataSize
) {
801 ath_print(common
, ATH_DBG_EEPROM
,
802 "Restore at %d: spot=%d "
803 "offset=%d length=%d\n",
804 it
, spot
, offset
, length
);
805 memcpy(&mptr
[spot
], &block
[it
+2], length
);
807 } else if (length
> 0) {
808 ath_print(common
, ATH_DBG_EEPROM
,
809 "Bad restore at %d: spot=%d "
810 "offset=%d length=%d\n",
811 it
, spot
, offset
, length
);
818 static int ar9300_compress_decision(struct ath_hw
*ah
,
823 u8
*word
, int length
, int mdata_size
)
825 struct ath_common
*common
= ath9k_hw_common(ah
);
830 if (length
!= mdata_size
) {
831 ath_print(common
, ATH_DBG_EEPROM
,
832 "EEPROM structure size mismatch"
833 "memory=%d eeprom=%d\n", mdata_size
, length
);
836 memcpy(mptr
, (u8
*) (word
+ COMP_HDR_LEN
), length
);
837 ath_print(common
, ATH_DBG_EEPROM
, "restored eeprom %d:"
838 " uncompressed, length %d\n", it
, length
);
841 if (reference
== 0) {
844 if (reference
!= 2) {
845 ath_print(common
, ATH_DBG_EEPROM
,
846 "cant find reference eeprom"
847 "struct %d\n", reference
);
850 memcpy(mptr
, &ar9300_default
, mdata_size
);
852 ath_print(common
, ATH_DBG_EEPROM
,
853 "restore eeprom %d: block, reference %d,"
854 " length %d\n", it
, reference
, length
);
855 ar9300_uncompress_block(ah
, mptr
, mdata_size
,
856 (u8
*) (word
+ COMP_HDR_LEN
), length
);
859 ath_print(common
, ATH_DBG_EEPROM
, "unknown compression"
867 * Read the configuration data from the eeprom.
868 * The data can be put in any specified memory buffer.
870 * Returns -1 on error.
871 * Returns address of next memory location on success.
873 static int ar9300_eeprom_restore_internal(struct ath_hw
*ah
,
874 u8
*mptr
, int mdata_size
)
881 int reference
, length
, major
, minor
;
884 u16 checksum
, mchecksum
;
885 struct ath_common
*common
= ath9k_hw_common(ah
);
887 word
= kzalloc(2048, GFP_KERNEL
);
891 memcpy(mptr
, &ar9300_default
, mdata_size
);
893 cptr
= AR9300_BASE_ADDR
;
894 for (it
= 0; it
< MSTATE
; it
++) {
895 if (!ar9300_read_eeprom(ah
, cptr
, word
, COMP_HDR_LEN
))
898 if ((word
[0] == 0 && word
[1] == 0 && word
[2] == 0 &&
899 word
[3] == 0) || (word
[0] == 0xff && word
[1] == 0xff
900 && word
[2] == 0xff && word
[3] == 0xff))
903 ar9300_comp_hdr_unpack(word
, &code
, &reference
,
904 &length
, &major
, &minor
);
905 ath_print(common
, ATH_DBG_EEPROM
,
906 "Found block at %x: code=%d ref=%d"
907 "length=%d major=%d minor=%d\n", cptr
, code
,
908 reference
, length
, major
, minor
);
909 if (length
>= 1024) {
910 ath_print(common
, ATH_DBG_EEPROM
,
911 "Skipping bad header\n");
912 cptr
-= COMP_HDR_LEN
;
917 ar9300_read_eeprom(ah
, cptr
, word
,
918 COMP_HDR_LEN
+ osize
+ COMP_CKSUM_LEN
);
919 checksum
= ar9300_comp_cksum(&word
[COMP_HDR_LEN
], length
);
920 mchecksum
= word
[COMP_HDR_LEN
+ osize
] |
921 (word
[COMP_HDR_LEN
+ osize
+ 1] << 8);
922 ath_print(common
, ATH_DBG_EEPROM
,
923 "checksum %x %x\n", checksum
, mchecksum
);
924 if (checksum
== mchecksum
) {
925 ar9300_compress_decision(ah
, it
, code
, reference
, mptr
,
926 word
, length
, mdata_size
);
928 ath_print(common
, ATH_DBG_EEPROM
,
929 "skipping block with bad checksum\n");
931 cptr
-= (COMP_HDR_LEN
+ osize
+ COMP_CKSUM_LEN
);
943 * Restore the configuration structure by reading the eeprom.
944 * This function destroys any existing in-memory structure
947 static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw
*ah
)
949 u8
*mptr
= (u8
*) &ah
->eeprom
.ar9300_eep
;
951 if (ar9300_eeprom_restore_internal(ah
, mptr
,
952 sizeof(struct ar9300_eeprom
)) < 0)
958 /* XXX: review hardware docs */
959 static int ath9k_hw_ar9300_get_eeprom_ver(struct ath_hw
*ah
)
961 return ah
->eeprom
.ar9300_eep
.eepromVersion
;
964 /* XXX: could be read from the eepromVersion, not sure yet */
965 static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw
*ah
)
970 static u8
ath9k_hw_ar9300_get_num_ant_config(struct ath_hw
*ah
,
971 enum ath9k_hal_freq_band freq_band
)
976 static u32
ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw
*ah
,
977 struct ath9k_channel
*chan
)
982 static s32
ar9003_hw_xpa_bias_level_get(struct ath_hw
*ah
, bool is2ghz
)
984 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
987 return eep
->modalHeader2G
.xpaBiasLvl
;
989 return eep
->modalHeader5G
.xpaBiasLvl
;
992 static void ar9003_hw_xpa_bias_level_apply(struct ath_hw
*ah
, bool is2ghz
)
994 int bias
= ar9003_hw_xpa_bias_level_get(ah
, is2ghz
);
995 REG_RMW_FIELD(ah
, AR_CH0_TOP
, AR_CH0_TOP_XPABIASLVL
, (bias
& 0x3));
996 REG_RMW_FIELD(ah
, AR_CH0_THERM
, AR_CH0_THERM_SPARE
,
997 ((bias
>> 2) & 0x3));
1000 static u32
ar9003_hw_ant_ctrl_common_get(struct ath_hw
*ah
, bool is2ghz
)
1002 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1006 val
= eep
->modalHeader2G
.antCtrlCommon
;
1008 val
= eep
->modalHeader5G
.antCtrlCommon
;
1009 return le32_to_cpu(val
);
1012 static u32
ar9003_hw_ant_ctrl_common_2_get(struct ath_hw
*ah
, bool is2ghz
)
1014 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1018 val
= eep
->modalHeader2G
.antCtrlCommon2
;
1020 val
= eep
->modalHeader5G
.antCtrlCommon2
;
1021 return le32_to_cpu(val
);
1024 static u16
ar9003_hw_ant_ctrl_chain_get(struct ath_hw
*ah
,
1028 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1031 if (chain
>= 0 && chain
< AR9300_MAX_CHAINS
) {
1033 val
= eep
->modalHeader2G
.antCtrlChain
[chain
];
1035 val
= eep
->modalHeader5G
.antCtrlChain
[chain
];
1038 return le16_to_cpu(val
);
1041 static void ar9003_hw_ant_ctrl_apply(struct ath_hw
*ah
, bool is2ghz
)
1043 u32 value
= ar9003_hw_ant_ctrl_common_get(ah
, is2ghz
);
1044 REG_RMW_FIELD(ah
, AR_PHY_SWITCH_COM
, AR_SWITCH_TABLE_COM_ALL
, value
);
1046 value
= ar9003_hw_ant_ctrl_common_2_get(ah
, is2ghz
);
1047 REG_RMW_FIELD(ah
, AR_PHY_SWITCH_COM_2
, AR_SWITCH_TABLE_COM2_ALL
, value
);
1049 value
= ar9003_hw_ant_ctrl_chain_get(ah
, 0, is2ghz
);
1050 REG_RMW_FIELD(ah
, AR_PHY_SWITCH_CHAIN_0
, AR_SWITCH_TABLE_ALL
, value
);
1052 value
= ar9003_hw_ant_ctrl_chain_get(ah
, 1, is2ghz
);
1053 REG_RMW_FIELD(ah
, AR_PHY_SWITCH_CHAIN_1
, AR_SWITCH_TABLE_ALL
, value
);
1055 value
= ar9003_hw_ant_ctrl_chain_get(ah
, 2, is2ghz
);
1056 REG_RMW_FIELD(ah
, AR_PHY_SWITCH_CHAIN_2
, AR_SWITCH_TABLE_ALL
, value
);
1059 static void ar9003_hw_drive_strength_apply(struct ath_hw
*ah
)
1064 drive_strength
= ath9k_hw_ar9300_get_eeprom(ah
, EEP_DRIVE_STRENGTH
);
1066 if (!drive_strength
)
1069 reg
= REG_READ(ah
, AR_PHY_65NM_CH0_BIAS1
);
1077 REG_WRITE(ah
, AR_PHY_65NM_CH0_BIAS1
, reg
);
1079 reg
= REG_READ(ah
, AR_PHY_65NM_CH0_BIAS2
);
1090 REG_WRITE(ah
, AR_PHY_65NM_CH0_BIAS2
, reg
);
1092 reg
= REG_READ(ah
, AR_PHY_65NM_CH0_BIAS4
);
1097 REG_WRITE(ah
, AR_PHY_65NM_CH0_BIAS4
, reg
);
1100 static void ar9003_hw_internal_regulator_apply(struct ath_hw
*ah
)
1102 int internal_regulator
=
1103 ath9k_hw_ar9300_get_eeprom(ah
, EEP_INTERNAL_REGULATOR
);
1105 if (internal_regulator
) {
1106 /* Internal regulator is ON. Write swreg register. */
1107 int swreg
= ath9k_hw_ar9300_get_eeprom(ah
, EEP_SWREG
);
1108 REG_WRITE(ah
, AR_RTC_REG_CONTROL1
,
1109 REG_READ(ah
, AR_RTC_REG_CONTROL1
) &
1110 (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM
));
1111 REG_WRITE(ah
, AR_RTC_REG_CONTROL0
, swreg
);
1112 /* Set REG_CONTROL1.SWREG_PROGRAM */
1113 REG_WRITE(ah
, AR_RTC_REG_CONTROL1
,
1115 AR_RTC_REG_CONTROL1
) |
1116 AR_RTC_REG_CONTROL1_SWREG_PROGRAM
);
1118 REG_WRITE(ah
, AR_RTC_SLEEP_CLK
,
1121 AR_RTC_FORCE_SWREG_PRD
));
1125 static void ath9k_hw_ar9300_set_board_values(struct ath_hw
*ah
,
1126 struct ath9k_channel
*chan
)
1128 ar9003_hw_xpa_bias_level_apply(ah
, IS_CHAN_2GHZ(chan
));
1129 ar9003_hw_ant_ctrl_apply(ah
, IS_CHAN_2GHZ(chan
));
1130 ar9003_hw_drive_strength_apply(ah
);
1131 ar9003_hw_internal_regulator_apply(ah
);
1134 static void ath9k_hw_ar9300_set_addac(struct ath_hw
*ah
,
1135 struct ath9k_channel
*chan
)
1140 * Returns the interpolated y value corresponding to the specified x value
1141 * from the np ordered pairs of data (px,py).
1142 * The pairs do not have to be in any order.
1143 * If the specified x value is less than any of the px,
1144 * the returned y value is equal to the py for the lowest px.
1145 * If the specified x value is greater than any of the px,
1146 * the returned y value is equal to the py for the highest px.
1148 static int ar9003_hw_power_interpolate(int32_t x
,
1149 int32_t *px
, int32_t *py
, u_int16_t np
)
1152 int lx
= 0, ly
= 0, lhave
= 0;
1153 int hx
= 0, hy
= 0, hhave
= 0;
1160 /* identify best lower and higher x calibration measurement */
1161 for (ip
= 0; ip
< np
; ip
++) {
1164 /* this measurement is higher than our desired x */
1166 if (!hhave
|| dx
> (x
- hx
)) {
1167 /* new best higher x measurement */
1173 /* this measurement is lower than our desired x */
1175 if (!lhave
|| dx
< (x
- lx
)) {
1176 /* new best lower x measurement */
1184 /* the low x is good */
1186 /* so is the high x */
1188 /* they're the same, so just pick one */
1191 else /* interpolate */
1192 y
= ly
+ (((x
- lx
) * (hy
- ly
)) / (hx
- lx
));
1193 } else /* only low is good, use it */
1195 } else if (hhave
) /* only high is good, use it */
1197 else /* nothing is good,this should never happen unless np=0, ???? */
1202 static u8
ar9003_hw_eeprom_get_tgt_pwr(struct ath_hw
*ah
,
1203 u16 rateIndex
, u16 freq
, bool is2GHz
)
1206 s32 targetPowerArray
[AR9300_NUM_5G_20_TARGET_POWERS
];
1207 s32 freqArray
[AR9300_NUM_5G_20_TARGET_POWERS
];
1208 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1209 struct cal_tgt_pow_legacy
*pEepromTargetPwr
;
1213 numPiers
= AR9300_NUM_2G_20_TARGET_POWERS
;
1214 pEepromTargetPwr
= eep
->calTargetPower2G
;
1215 pFreqBin
= eep
->calTarget_freqbin_2G
;
1217 numPiers
= AR9300_NUM_5G_20_TARGET_POWERS
;
1218 pEepromTargetPwr
= eep
->calTargetPower5G
;
1219 pFreqBin
= eep
->calTarget_freqbin_5G
;
1223 * create array of channels and targetpower from
1224 * targetpower piers stored on eeprom
1226 for (i
= 0; i
< numPiers
; i
++) {
1227 freqArray
[i
] = FBIN2FREQ(pFreqBin
[i
], is2GHz
);
1228 targetPowerArray
[i
] = pEepromTargetPwr
[i
].tPow2x
[rateIndex
];
1231 /* interpolate to get target power for given frequency */
1232 return (u8
) ar9003_hw_power_interpolate((s32
) freq
,
1234 targetPowerArray
, numPiers
);
1237 static u8
ar9003_hw_eeprom_get_ht20_tgt_pwr(struct ath_hw
*ah
,
1239 u16 freq
, bool is2GHz
)
1242 s32 targetPowerArray
[AR9300_NUM_5G_20_TARGET_POWERS
];
1243 s32 freqArray
[AR9300_NUM_5G_20_TARGET_POWERS
];
1244 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1245 struct cal_tgt_pow_ht
*pEepromTargetPwr
;
1249 numPiers
= AR9300_NUM_2G_20_TARGET_POWERS
;
1250 pEepromTargetPwr
= eep
->calTargetPower2GHT20
;
1251 pFreqBin
= eep
->calTarget_freqbin_2GHT20
;
1253 numPiers
= AR9300_NUM_5G_20_TARGET_POWERS
;
1254 pEepromTargetPwr
= eep
->calTargetPower5GHT20
;
1255 pFreqBin
= eep
->calTarget_freqbin_5GHT20
;
1259 * create array of channels and targetpower
1260 * from targetpower piers stored on eeprom
1262 for (i
= 0; i
< numPiers
; i
++) {
1263 freqArray
[i
] = FBIN2FREQ(pFreqBin
[i
], is2GHz
);
1264 targetPowerArray
[i
] = pEepromTargetPwr
[i
].tPow2x
[rateIndex
];
1267 /* interpolate to get target power for given frequency */
1268 return (u8
) ar9003_hw_power_interpolate((s32
) freq
,
1270 targetPowerArray
, numPiers
);
1273 static u8
ar9003_hw_eeprom_get_ht40_tgt_pwr(struct ath_hw
*ah
,
1275 u16 freq
, bool is2GHz
)
1278 s32 targetPowerArray
[AR9300_NUM_5G_40_TARGET_POWERS
];
1279 s32 freqArray
[AR9300_NUM_5G_40_TARGET_POWERS
];
1280 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1281 struct cal_tgt_pow_ht
*pEepromTargetPwr
;
1285 numPiers
= AR9300_NUM_2G_40_TARGET_POWERS
;
1286 pEepromTargetPwr
= eep
->calTargetPower2GHT40
;
1287 pFreqBin
= eep
->calTarget_freqbin_2GHT40
;
1289 numPiers
= AR9300_NUM_5G_40_TARGET_POWERS
;
1290 pEepromTargetPwr
= eep
->calTargetPower5GHT40
;
1291 pFreqBin
= eep
->calTarget_freqbin_5GHT40
;
1295 * create array of channels and targetpower from
1296 * targetpower piers stored on eeprom
1298 for (i
= 0; i
< numPiers
; i
++) {
1299 freqArray
[i
] = FBIN2FREQ(pFreqBin
[i
], is2GHz
);
1300 targetPowerArray
[i
] = pEepromTargetPwr
[i
].tPow2x
[rateIndex
];
1303 /* interpolate to get target power for given frequency */
1304 return (u8
) ar9003_hw_power_interpolate((s32
) freq
,
1306 targetPowerArray
, numPiers
);
1309 static u8
ar9003_hw_eeprom_get_cck_tgt_pwr(struct ath_hw
*ah
,
1310 u16 rateIndex
, u16 freq
)
1312 u16 numPiers
= AR9300_NUM_2G_CCK_TARGET_POWERS
, i
;
1313 s32 targetPowerArray
[AR9300_NUM_2G_CCK_TARGET_POWERS
];
1314 s32 freqArray
[AR9300_NUM_2G_CCK_TARGET_POWERS
];
1315 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1316 struct cal_tgt_pow_legacy
*pEepromTargetPwr
= eep
->calTargetPowerCck
;
1317 u8
*pFreqBin
= eep
->calTarget_freqbin_Cck
;
1320 * create array of channels and targetpower from
1321 * targetpower piers stored on eeprom
1323 for (i
= 0; i
< numPiers
; i
++) {
1324 freqArray
[i
] = FBIN2FREQ(pFreqBin
[i
], 1);
1325 targetPowerArray
[i
] = pEepromTargetPwr
[i
].tPow2x
[rateIndex
];
1328 /* interpolate to get target power for given frequency */
1329 return (u8
) ar9003_hw_power_interpolate((s32
) freq
,
1331 targetPowerArray
, numPiers
);
1334 /* Set tx power registers to array of values passed in */
1335 static int ar9003_hw_tx_power_regwrite(struct ath_hw
*ah
, u8
* pPwrArray
)
1337 #define POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
1338 /* make sure forced gain is not set */
1339 REG_WRITE(ah
, 0xa458, 0);
1341 /* Write the OFDM power per rate set */
1343 /* 6 (LSB), 9, 12, 18 (MSB) */
1344 REG_WRITE(ah
, 0xa3c0,
1345 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_6_24
], 24) |
1346 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_6_24
], 16) |
1347 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_6_24
], 8) |
1348 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_6_24
], 0));
1350 /* 24 (LSB), 36, 48, 54 (MSB) */
1351 REG_WRITE(ah
, 0xa3c4,
1352 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_54
], 24) |
1353 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_48
], 16) |
1354 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_36
], 8) |
1355 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_6_24
], 0));
1357 /* Write the CCK power per rate set */
1359 /* 1L (LSB), reserved, 2L, 2S (MSB) */
1360 REG_WRITE(ah
, 0xa3c8,
1361 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_1L_5L
], 24) |
1362 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_1L_5L
], 16) |
1363 /* POW_SM(txPowerTimes2, 8) | this is reserved for AR9003 */
1364 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_1L_5L
], 0));
1366 /* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */
1367 REG_WRITE(ah
, 0xa3cc,
1368 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_11S
], 24) |
1369 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_11L
], 16) |
1370 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_5S
], 8) |
1371 POW_SM(pPwrArray
[ALL_TARGET_LEGACY_1L_5L
], 0)
1374 /* Write the HT20 power per rate set */
1376 /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */
1377 REG_WRITE(ah
, 0xa3d0,
1378 POW_SM(pPwrArray
[ALL_TARGET_HT20_5
], 24) |
1379 POW_SM(pPwrArray
[ALL_TARGET_HT20_4
], 16) |
1380 POW_SM(pPwrArray
[ALL_TARGET_HT20_1_3_9_11_17_19
], 8) |
1381 POW_SM(pPwrArray
[ALL_TARGET_HT20_0_8_16
], 0)
1384 /* 6 (LSB), 7, 12, 13 (MSB) */
1385 REG_WRITE(ah
, 0xa3d4,
1386 POW_SM(pPwrArray
[ALL_TARGET_HT20_13
], 24) |
1387 POW_SM(pPwrArray
[ALL_TARGET_HT20_12
], 16) |
1388 POW_SM(pPwrArray
[ALL_TARGET_HT20_7
], 8) |
1389 POW_SM(pPwrArray
[ALL_TARGET_HT20_6
], 0)
1392 /* 14 (LSB), 15, 20, 21 */
1393 REG_WRITE(ah
, 0xa3e4,
1394 POW_SM(pPwrArray
[ALL_TARGET_HT20_21
], 24) |
1395 POW_SM(pPwrArray
[ALL_TARGET_HT20_20
], 16) |
1396 POW_SM(pPwrArray
[ALL_TARGET_HT20_15
], 8) |
1397 POW_SM(pPwrArray
[ALL_TARGET_HT20_14
], 0)
1400 /* Mixed HT20 and HT40 rates */
1402 /* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */
1403 REG_WRITE(ah
, 0xa3e8,
1404 POW_SM(pPwrArray
[ALL_TARGET_HT40_23
], 24) |
1405 POW_SM(pPwrArray
[ALL_TARGET_HT40_22
], 16) |
1406 POW_SM(pPwrArray
[ALL_TARGET_HT20_23
], 8) |
1407 POW_SM(pPwrArray
[ALL_TARGET_HT20_22
], 0)
1411 * Write the HT40 power per rate set
1412 * correct PAR difference between HT40 and HT20/LEGACY
1413 * 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB)
1415 REG_WRITE(ah
, 0xa3d8,
1416 POW_SM(pPwrArray
[ALL_TARGET_HT40_5
], 24) |
1417 POW_SM(pPwrArray
[ALL_TARGET_HT40_4
], 16) |
1418 POW_SM(pPwrArray
[ALL_TARGET_HT40_1_3_9_11_17_19
], 8) |
1419 POW_SM(pPwrArray
[ALL_TARGET_HT40_0_8_16
], 0)
1422 /* 6 (LSB), 7, 12, 13 (MSB) */
1423 REG_WRITE(ah
, 0xa3dc,
1424 POW_SM(pPwrArray
[ALL_TARGET_HT40_13
], 24) |
1425 POW_SM(pPwrArray
[ALL_TARGET_HT40_12
], 16) |
1426 POW_SM(pPwrArray
[ALL_TARGET_HT40_7
], 8) |
1427 POW_SM(pPwrArray
[ALL_TARGET_HT40_6
], 0)
1430 /* 14 (LSB), 15, 20, 21 */
1431 REG_WRITE(ah
, 0xa3ec,
1432 POW_SM(pPwrArray
[ALL_TARGET_HT40_21
], 24) |
1433 POW_SM(pPwrArray
[ALL_TARGET_HT40_20
], 16) |
1434 POW_SM(pPwrArray
[ALL_TARGET_HT40_15
], 8) |
1435 POW_SM(pPwrArray
[ALL_TARGET_HT40_14
], 0)
1442 static void ar9003_hw_set_target_power_eeprom(struct ath_hw
*ah
, u16 freq
,
1443 u8
*targetPowerValT2
)
1445 /* XXX: hard code for now, need to get from eeprom struct */
1446 u8 ht40PowerIncForPdadc
= 0;
1447 bool is2GHz
= false;
1449 struct ath_common
*common
= ath9k_hw_common(ah
);
1454 targetPowerValT2
[ALL_TARGET_LEGACY_6_24
] =
1455 ar9003_hw_eeprom_get_tgt_pwr(ah
, LEGACY_TARGET_RATE_6_24
, freq
,
1457 targetPowerValT2
[ALL_TARGET_LEGACY_36
] =
1458 ar9003_hw_eeprom_get_tgt_pwr(ah
, LEGACY_TARGET_RATE_36
, freq
,
1460 targetPowerValT2
[ALL_TARGET_LEGACY_48
] =
1461 ar9003_hw_eeprom_get_tgt_pwr(ah
, LEGACY_TARGET_RATE_48
, freq
,
1463 targetPowerValT2
[ALL_TARGET_LEGACY_54
] =
1464 ar9003_hw_eeprom_get_tgt_pwr(ah
, LEGACY_TARGET_RATE_54
, freq
,
1466 targetPowerValT2
[ALL_TARGET_LEGACY_1L_5L
] =
1467 ar9003_hw_eeprom_get_cck_tgt_pwr(ah
, LEGACY_TARGET_RATE_1L_5L
,
1469 targetPowerValT2
[ALL_TARGET_LEGACY_5S
] =
1470 ar9003_hw_eeprom_get_cck_tgt_pwr(ah
, LEGACY_TARGET_RATE_5S
, freq
);
1471 targetPowerValT2
[ALL_TARGET_LEGACY_11L
] =
1472 ar9003_hw_eeprom_get_cck_tgt_pwr(ah
, LEGACY_TARGET_RATE_11L
, freq
);
1473 targetPowerValT2
[ALL_TARGET_LEGACY_11S
] =
1474 ar9003_hw_eeprom_get_cck_tgt_pwr(ah
, LEGACY_TARGET_RATE_11S
, freq
);
1475 targetPowerValT2
[ALL_TARGET_HT20_0_8_16
] =
1476 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_0_8_16
, freq
,
1478 targetPowerValT2
[ALL_TARGET_HT20_1_3_9_11_17_19
] =
1479 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_1_3_9_11_17_19
,
1481 targetPowerValT2
[ALL_TARGET_HT20_4
] =
1482 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_4
, freq
,
1484 targetPowerValT2
[ALL_TARGET_HT20_5
] =
1485 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_5
, freq
,
1487 targetPowerValT2
[ALL_TARGET_HT20_6
] =
1488 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_6
, freq
,
1490 targetPowerValT2
[ALL_TARGET_HT20_7
] =
1491 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_7
, freq
,
1493 targetPowerValT2
[ALL_TARGET_HT20_12
] =
1494 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_12
, freq
,
1496 targetPowerValT2
[ALL_TARGET_HT20_13
] =
1497 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_13
, freq
,
1499 targetPowerValT2
[ALL_TARGET_HT20_14
] =
1500 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_14
, freq
,
1502 targetPowerValT2
[ALL_TARGET_HT20_15
] =
1503 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_15
, freq
,
1505 targetPowerValT2
[ALL_TARGET_HT20_20
] =
1506 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_20
, freq
,
1508 targetPowerValT2
[ALL_TARGET_HT20_21
] =
1509 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_21
, freq
,
1511 targetPowerValT2
[ALL_TARGET_HT20_22
] =
1512 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_22
, freq
,
1514 targetPowerValT2
[ALL_TARGET_HT20_23
] =
1515 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah
, HT_TARGET_RATE_23
, freq
,
1517 targetPowerValT2
[ALL_TARGET_HT40_0_8_16
] =
1518 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_0_8_16
, freq
,
1519 is2GHz
) + ht40PowerIncForPdadc
;
1520 targetPowerValT2
[ALL_TARGET_HT40_1_3_9_11_17_19
] =
1521 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_1_3_9_11_17_19
,
1523 is2GHz
) + ht40PowerIncForPdadc
;
1524 targetPowerValT2
[ALL_TARGET_HT40_4
] =
1525 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_4
, freq
,
1526 is2GHz
) + ht40PowerIncForPdadc
;
1527 targetPowerValT2
[ALL_TARGET_HT40_5
] =
1528 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_5
, freq
,
1529 is2GHz
) + ht40PowerIncForPdadc
;
1530 targetPowerValT2
[ALL_TARGET_HT40_6
] =
1531 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_6
, freq
,
1532 is2GHz
) + ht40PowerIncForPdadc
;
1533 targetPowerValT2
[ALL_TARGET_HT40_7
] =
1534 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_7
, freq
,
1535 is2GHz
) + ht40PowerIncForPdadc
;
1536 targetPowerValT2
[ALL_TARGET_HT40_12
] =
1537 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_12
, freq
,
1538 is2GHz
) + ht40PowerIncForPdadc
;
1539 targetPowerValT2
[ALL_TARGET_HT40_13
] =
1540 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_13
, freq
,
1541 is2GHz
) + ht40PowerIncForPdadc
;
1542 targetPowerValT2
[ALL_TARGET_HT40_14
] =
1543 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_14
, freq
,
1544 is2GHz
) + ht40PowerIncForPdadc
;
1545 targetPowerValT2
[ALL_TARGET_HT40_15
] =
1546 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_15
, freq
,
1547 is2GHz
) + ht40PowerIncForPdadc
;
1548 targetPowerValT2
[ALL_TARGET_HT40_20
] =
1549 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_20
, freq
,
1550 is2GHz
) + ht40PowerIncForPdadc
;
1551 targetPowerValT2
[ALL_TARGET_HT40_21
] =
1552 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_21
, freq
,
1553 is2GHz
) + ht40PowerIncForPdadc
;
1554 targetPowerValT2
[ALL_TARGET_HT40_22
] =
1555 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_22
, freq
,
1556 is2GHz
) + ht40PowerIncForPdadc
;
1557 targetPowerValT2
[ALL_TARGET_HT40_23
] =
1558 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah
, HT_TARGET_RATE_23
, freq
,
1559 is2GHz
) + ht40PowerIncForPdadc
;
1561 while (i
< ar9300RateSize
) {
1562 ath_print(common
, ATH_DBG_EEPROM
,
1563 "TPC[%02d] 0x%08x ", i
, targetPowerValT2
[i
]);
1566 ath_print(common
, ATH_DBG_EEPROM
,
1567 "TPC[%02d] 0x%08x ", i
, targetPowerValT2
[i
]);
1570 ath_print(common
, ATH_DBG_EEPROM
,
1571 "TPC[%02d] 0x%08x ", i
, targetPowerValT2
[i
]);
1574 ath_print(common
, ATH_DBG_EEPROM
,
1575 "TPC[%02d] 0x%08x\n", i
, targetPowerValT2
[i
]);
1580 static int ar9003_hw_cal_pier_get(struct ath_hw
*ah
,
1586 int *ptemperature
, int *pvoltage
)
1589 struct ar9300_cal_data_per_freq_op_loop
*pCalPierStruct
;
1591 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1592 struct ath_common
*common
= ath9k_hw_common(ah
);
1594 if (ichain
>= AR9300_MAX_CHAINS
) {
1595 ath_print(common
, ATH_DBG_EEPROM
,
1596 "Invalid chain index, must be less than %d\n",
1601 if (mode
) { /* 5GHz */
1602 if (ipier
>= AR9300_NUM_5G_CAL_PIERS
) {
1603 ath_print(common
, ATH_DBG_EEPROM
,
1604 "Invalid 5GHz cal pier index, must "
1605 "be less than %d\n",
1606 AR9300_NUM_5G_CAL_PIERS
);
1609 pCalPier
= &(eep
->calFreqPier5G
[ipier
]);
1610 pCalPierStruct
= &(eep
->calPierData5G
[ichain
][ipier
]);
1613 if (ipier
>= AR9300_NUM_2G_CAL_PIERS
) {
1614 ath_print(common
, ATH_DBG_EEPROM
,
1615 "Invalid 2GHz cal pier index, must "
1616 "be less than %d\n", AR9300_NUM_2G_CAL_PIERS
);
1620 pCalPier
= &(eep
->calFreqPier2G
[ipier
]);
1621 pCalPierStruct
= &(eep
->calPierData2G
[ichain
][ipier
]);
1625 *pfrequency
= FBIN2FREQ(*pCalPier
, is2GHz
);
1626 *pcorrection
= pCalPierStruct
->refPower
;
1627 *ptemperature
= pCalPierStruct
->tempMeas
;
1628 *pvoltage
= pCalPierStruct
->voltMeas
;
1633 static int ar9003_hw_power_control_override(struct ath_hw
*ah
,
1636 int *voltage
, int *temperature
)
1639 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
1641 REG_RMW(ah
, AR_PHY_TPC_11_B0
,
1642 (correction
[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S
),
1643 AR_PHY_TPC_OLPC_GAIN_DELTA
);
1644 REG_RMW(ah
, AR_PHY_TPC_11_B1
,
1645 (correction
[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S
),
1646 AR_PHY_TPC_OLPC_GAIN_DELTA
);
1647 REG_RMW(ah
, AR_PHY_TPC_11_B2
,
1648 (correction
[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S
),
1649 AR_PHY_TPC_OLPC_GAIN_DELTA
);
1651 /* enable open loop power control on chip */
1652 REG_RMW(ah
, AR_PHY_TPC_6_B0
,
1653 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S
),
1654 AR_PHY_TPC_6_ERROR_EST_MODE
);
1655 REG_RMW(ah
, AR_PHY_TPC_6_B1
,
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_B2
,
1659 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S
),
1660 AR_PHY_TPC_6_ERROR_EST_MODE
);
1663 * enable temperature compensation
1664 * Need to use register names
1666 if (frequency
< 4000)
1667 tempSlope
= eep
->modalHeader2G
.tempSlope
;
1669 tempSlope
= eep
->modalHeader5G
.tempSlope
;
1671 REG_RMW_FIELD(ah
, AR_PHY_TPC_19
, AR_PHY_TPC_19_ALPHA_THERM
, tempSlope
);
1672 REG_RMW_FIELD(ah
, AR_PHY_TPC_18
, AR_PHY_TPC_18_THERM_CAL_VALUE
,
1678 /* Apply the recorded correction values. */
1679 static int ar9003_hw_calibration_apply(struct ath_hw
*ah
, int frequency
)
1681 int ichain
, ipier
, npier
;
1683 int lfrequency
[AR9300_MAX_CHAINS
],
1684 lcorrection
[AR9300_MAX_CHAINS
],
1685 ltemperature
[AR9300_MAX_CHAINS
], lvoltage
[AR9300_MAX_CHAINS
];
1686 int hfrequency
[AR9300_MAX_CHAINS
],
1687 hcorrection
[AR9300_MAX_CHAINS
],
1688 htemperature
[AR9300_MAX_CHAINS
], hvoltage
[AR9300_MAX_CHAINS
];
1690 int correction
[AR9300_MAX_CHAINS
],
1691 voltage
[AR9300_MAX_CHAINS
], temperature
[AR9300_MAX_CHAINS
];
1692 int pfrequency
, pcorrection
, ptemperature
, pvoltage
;
1693 struct ath_common
*common
= ath9k_hw_common(ah
);
1695 mode
= (frequency
>= 4000);
1697 npier
= AR9300_NUM_5G_CAL_PIERS
;
1699 npier
= AR9300_NUM_2G_CAL_PIERS
;
1701 for (ichain
= 0; ichain
< AR9300_MAX_CHAINS
; ichain
++) {
1702 lfrequency
[ichain
] = 0;
1703 hfrequency
[ichain
] = 100000;
1705 /* identify best lower and higher frequency calibration measurement */
1706 for (ichain
= 0; ichain
< AR9300_MAX_CHAINS
; ichain
++) {
1707 for (ipier
= 0; ipier
< npier
; ipier
++) {
1708 if (!ar9003_hw_cal_pier_get(ah
, mode
, ipier
, ichain
,
1709 &pfrequency
, &pcorrection
,
1710 &ptemperature
, &pvoltage
)) {
1711 fdiff
= frequency
- pfrequency
;
1714 * this measurement is higher than
1715 * our desired frequency
1718 if (hfrequency
[ichain
] <= 0 ||
1719 hfrequency
[ichain
] >= 100000 ||
1721 (frequency
- hfrequency
[ichain
])) {
1724 * frequency measurement
1726 hfrequency
[ichain
] = pfrequency
;
1727 hcorrection
[ichain
] =
1729 htemperature
[ichain
] =
1731 hvoltage
[ichain
] = pvoltage
;
1735 if (lfrequency
[ichain
] <= 0
1737 (frequency
- lfrequency
[ichain
])) {
1740 * frequency measurement
1742 lfrequency
[ichain
] = pfrequency
;
1743 lcorrection
[ichain
] =
1745 ltemperature
[ichain
] =
1747 lvoltage
[ichain
] = pvoltage
;
1755 for (ichain
= 0; ichain
< AR9300_MAX_CHAINS
; ichain
++) {
1756 ath_print(common
, ATH_DBG_EEPROM
,
1757 "ch=%d f=%d low=%d %d h=%d %d\n",
1758 ichain
, frequency
, lfrequency
[ichain
],
1759 lcorrection
[ichain
], hfrequency
[ichain
],
1760 hcorrection
[ichain
]);
1761 /* they're the same, so just pick one */
1762 if (hfrequency
[ichain
] == lfrequency
[ichain
]) {
1763 correction
[ichain
] = lcorrection
[ichain
];
1764 voltage
[ichain
] = lvoltage
[ichain
];
1765 temperature
[ichain
] = ltemperature
[ichain
];
1767 /* the low frequency is good */
1768 else if (frequency
- lfrequency
[ichain
] < 1000) {
1769 /* so is the high frequency, interpolate */
1770 if (hfrequency
[ichain
] - frequency
< 1000) {
1772 correction
[ichain
] = lcorrection
[ichain
] +
1773 (((frequency
- lfrequency
[ichain
]) *
1774 (hcorrection
[ichain
] -
1775 lcorrection
[ichain
])) /
1776 (hfrequency
[ichain
] - lfrequency
[ichain
]));
1778 temperature
[ichain
] = ltemperature
[ichain
] +
1779 (((frequency
- lfrequency
[ichain
]) *
1780 (htemperature
[ichain
] -
1781 ltemperature
[ichain
])) /
1782 (hfrequency
[ichain
] - lfrequency
[ichain
]));
1787 lfrequency
[ichain
]) * (hvoltage
[ichain
] -
1789 / (hfrequency
[ichain
] -
1790 lfrequency
[ichain
]));
1792 /* only low is good, use it */
1794 correction
[ichain
] = lcorrection
[ichain
];
1795 temperature
[ichain
] = ltemperature
[ichain
];
1796 voltage
[ichain
] = lvoltage
[ichain
];
1799 /* only high is good, use it */
1800 else if (hfrequency
[ichain
] - frequency
< 1000) {
1801 correction
[ichain
] = hcorrection
[ichain
];
1802 temperature
[ichain
] = htemperature
[ichain
];
1803 voltage
[ichain
] = hvoltage
[ichain
];
1804 } else { /* nothing is good, presume 0???? */
1805 correction
[ichain
] = 0;
1806 temperature
[ichain
] = 0;
1807 voltage
[ichain
] = 0;
1811 ar9003_hw_power_control_override(ah
, frequency
, correction
, voltage
,
1814 ath_print(common
, ATH_DBG_EEPROM
,
1815 "for frequency=%d, calibration correction = %d %d %d\n",
1816 frequency
, correction
[0], correction
[1], correction
[2]);
1821 static u16
ar9003_hw_get_direct_edge_power(struct ar9300_eeprom
*eep
,
1826 struct cal_ctl_data_2g
*ctl_2g
= eep
->ctlPowerData_2G
;
1827 struct cal_ctl_data_5g
*ctl_5g
= eep
->ctlPowerData_5G
;
1830 return ctl_2g
[idx
].ctlEdges
[edge
].tPower
;
1832 return ctl_5g
[idx
].ctlEdges
[edge
].tPower
;
1835 static u16
ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom
*eep
,
1841 struct cal_ctl_data_2g
*ctl_2g
= eep
->ctlPowerData_2G
;
1842 struct cal_ctl_data_5g
*ctl_5g
= eep
->ctlPowerData_5G
;
1844 u8
*ctl_freqbin
= is2GHz
?
1845 &eep
->ctl_freqbin_2G
[idx
][0] :
1846 &eep
->ctl_freqbin_5G
[idx
][0];
1849 if (ath9k_hw_fbin2freq(ctl_freqbin
[edge
- 1], 1) < freq
&&
1850 ctl_2g
[idx
].ctlEdges
[edge
- 1].flag
)
1851 return ctl_2g
[idx
].ctlEdges
[edge
- 1].tPower
;
1853 if (ath9k_hw_fbin2freq(ctl_freqbin
[edge
- 1], 0) < freq
&&
1854 ctl_5g
[idx
].ctlEdges
[edge
- 1].flag
)
1855 return ctl_5g
[idx
].ctlEdges
[edge
- 1].tPower
;
1858 return AR9300_MAX_RATE_POWER
;
1862 * Find the maximum conformance test limit for the given channel and CTL info
1864 static u16
ar9003_hw_get_max_edge_power(struct ar9300_eeprom
*eep
,
1865 u16 freq
, int idx
, bool is2GHz
)
1867 u16 twiceMaxEdgePower
= AR9300_MAX_RATE_POWER
;
1868 u8
*ctl_freqbin
= is2GHz
?
1869 &eep
->ctl_freqbin_2G
[idx
][0] :
1870 &eep
->ctl_freqbin_5G
[idx
][0];
1871 u16 num_edges
= is2GHz
?
1872 AR9300_NUM_BAND_EDGES_2G
: AR9300_NUM_BAND_EDGES_5G
;
1875 /* Get the edge power */
1877 (edge
< num_edges
) && (ctl_freqbin
[edge
] != AR9300_BCHAN_UNUSED
);
1880 * If there's an exact channel match or an inband flag set
1881 * on the lower channel use the given rdEdgePower
1883 if (freq
== ath9k_hw_fbin2freq(ctl_freqbin
[edge
], is2GHz
)) {
1885 ar9003_hw_get_direct_edge_power(eep
, idx
,
1888 } else if ((edge
> 0) &&
1889 (freq
< ath9k_hw_fbin2freq(ctl_freqbin
[edge
],
1892 ar9003_hw_get_indirect_edge_power(eep
, idx
,
1896 * Leave loop - no more affecting edges possible in
1897 * this monotonic increasing list
1902 return twiceMaxEdgePower
;
1905 static void ar9003_hw_set_power_per_rate_table(struct ath_hw
*ah
,
1906 struct ath9k_channel
*chan
,
1907 u8
*pPwrArray
, u16 cfgCtl
,
1908 u8 twiceAntennaReduction
,
1909 u8 twiceMaxRegulatoryPower
,
1912 struct ath_regulatory
*regulatory
= ath9k_hw_regulatory(ah
);
1913 struct ath_common
*common
= ath9k_hw_common(ah
);
1914 struct ar9300_eeprom
*pEepData
= &ah
->eeprom
.ar9300_eep
;
1915 u16 twiceMaxEdgePower
= AR9300_MAX_RATE_POWER
;
1916 static const u16 tpScaleReductionTable
[5] = {
1917 0, 3, 6, 9, AR9300_MAX_RATE_POWER
1920 int16_t twiceLargestAntenna
;
1921 u16 scaledPower
= 0, minCtlPower
, maxRegAllowedPower
;
1922 u16 ctlModesFor11a
[] = {
1923 CTL_11A
, CTL_5GHT20
, CTL_11A_EXT
, CTL_5GHT40
1925 u16 ctlModesFor11g
[] = {
1926 CTL_11B
, CTL_11G
, CTL_2GHT20
, CTL_11B_EXT
,
1927 CTL_11G_EXT
, CTL_2GHT40
1929 u16 numCtlModes
, *pCtlMode
, ctlMode
, freq
;
1930 struct chan_centers centers
;
1933 u16 twiceMinEdgePower
;
1934 bool is2ghz
= IS_CHAN_2GHZ(chan
);
1936 ath9k_hw_get_channel_centers(ah
, chan
, ¢ers
);
1938 /* Compute TxPower reduction due to Antenna Gain */
1940 twiceLargestAntenna
= pEepData
->modalHeader2G
.antennaGain
;
1942 twiceLargestAntenna
= pEepData
->modalHeader5G
.antennaGain
;
1944 twiceLargestAntenna
= (int16_t)min((twiceAntennaReduction
) -
1945 twiceLargestAntenna
, 0);
1948 * scaledPower is the minimum of the user input power level
1949 * and the regulatory allowed power level
1951 maxRegAllowedPower
= twiceMaxRegulatoryPower
+ twiceLargestAntenna
;
1953 if (regulatory
->tp_scale
!= ATH9K_TP_SCALE_MAX
) {
1954 maxRegAllowedPower
-=
1955 (tpScaleReductionTable
[(regulatory
->tp_scale
)] * 2);
1958 scaledPower
= min(powerLimit
, maxRegAllowedPower
);
1961 * Reduce scaled Power by number of chains active to get
1962 * to per chain tx power level
1964 switch (ar5416_get_ntxchains(ah
->txchainmask
)) {
1968 scaledPower
-= REDUCE_SCALED_POWER_BY_TWO_CHAIN
;
1971 scaledPower
-= REDUCE_SCALED_POWER_BY_THREE_CHAIN
;
1975 scaledPower
= max((u16
)0, scaledPower
);
1978 * Get target powers from EEPROM - our baseline for TX Power
1981 /* Setup for CTL modes */
1982 /* CTL_11B, CTL_11G, CTL_2GHT20 */
1984 ARRAY_SIZE(ctlModesFor11g
) -
1985 SUB_NUM_CTL_MODES_AT_2G_40
;
1986 pCtlMode
= ctlModesFor11g
;
1987 if (IS_CHAN_HT40(chan
))
1989 numCtlModes
= ARRAY_SIZE(ctlModesFor11g
);
1991 /* Setup for CTL modes */
1992 /* CTL_11A, CTL_5GHT20 */
1993 numCtlModes
= ARRAY_SIZE(ctlModesFor11a
) -
1994 SUB_NUM_CTL_MODES_AT_5G_40
;
1995 pCtlMode
= ctlModesFor11a
;
1996 if (IS_CHAN_HT40(chan
))
1998 numCtlModes
= ARRAY_SIZE(ctlModesFor11a
);
2002 * For MIMO, need to apply regulatory caps individually across
2003 * dynamically running modes: CCK, OFDM, HT20, HT40
2005 * The outer loop walks through each possible applicable runtime mode.
2006 * The inner loop walks through each ctlIndex entry in EEPROM.
2007 * The ctl value is encoded as [7:4] == test group, [3:0] == test mode.
2009 for (ctlMode
= 0; ctlMode
< numCtlModes
; ctlMode
++) {
2010 bool isHt40CtlMode
= (pCtlMode
[ctlMode
] == CTL_5GHT40
) ||
2011 (pCtlMode
[ctlMode
] == CTL_2GHT40
);
2013 freq
= centers
.synth_center
;
2014 else if (pCtlMode
[ctlMode
] & EXT_ADDITIVE
)
2015 freq
= centers
.ext_center
;
2017 freq
= centers
.ctl_center
;
2019 ath_print(common
, ATH_DBG_REGULATORY
,
2020 "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
2021 "EXT_ADDITIVE %d\n",
2022 ctlMode
, numCtlModes
, isHt40CtlMode
,
2023 (pCtlMode
[ctlMode
] & EXT_ADDITIVE
));
2025 /* walk through each CTL index stored in EEPROM */
2027 ctlIndex
= pEepData
->ctlIndex_2G
;
2028 ctlNum
= AR9300_NUM_CTLS_2G
;
2030 ctlIndex
= pEepData
->ctlIndex_5G
;
2031 ctlNum
= AR9300_NUM_CTLS_5G
;
2034 for (i
= 0; (i
< ctlNum
) && ctlIndex
[i
]; i
++) {
2035 ath_print(common
, ATH_DBG_REGULATORY
,
2036 "LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
2037 "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
2039 i
, cfgCtl
, pCtlMode
[ctlMode
], ctlIndex
[i
],
2043 * compare test group from regulatory
2044 * channel list with test mode from pCtlMode
2047 if ((((cfgCtl
& ~CTL_MODE_M
) |
2048 (pCtlMode
[ctlMode
] & CTL_MODE_M
)) ==
2050 (((cfgCtl
& ~CTL_MODE_M
) |
2051 (pCtlMode
[ctlMode
] & CTL_MODE_M
)) ==
2052 ((ctlIndex
[i
] & CTL_MODE_M
) |
2055 ar9003_hw_get_max_edge_power(pEepData
,
2059 if ((cfgCtl
& ~CTL_MODE_M
) == SD_NO_CTL
)
2061 * Find the minimum of all CTL
2062 * edge powers that apply to
2066 min(twiceMaxEdgePower
,
2077 minCtlPower
= (u8
)min(twiceMaxEdgePower
, scaledPower
);
2079 ath_print(common
, ATH_DBG_REGULATORY
,
2080 "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d "
2081 "sP %d minCtlPwr %d\n",
2082 ctlMode
, pCtlMode
[ctlMode
], twiceMaxEdgePower
,
2083 scaledPower
, minCtlPower
);
2085 /* Apply ctl mode to correct target power set */
2086 switch (pCtlMode
[ctlMode
]) {
2088 for (i
= ALL_TARGET_LEGACY_1L_5L
;
2089 i
<= ALL_TARGET_LEGACY_11S
; i
++)
2091 (u8
)min((u16
)pPwrArray
[i
],
2096 for (i
= ALL_TARGET_LEGACY_6_24
;
2097 i
<= ALL_TARGET_LEGACY_54
; i
++)
2099 (u8
)min((u16
)pPwrArray
[i
],
2104 for (i
= ALL_TARGET_HT20_0_8_16
;
2105 i
<= ALL_TARGET_HT20_21
; i
++)
2107 (u8
)min((u16
)pPwrArray
[i
],
2109 pPwrArray
[ALL_TARGET_HT20_22
] =
2110 (u8
)min((u16
)pPwrArray
[ALL_TARGET_HT20_22
],
2112 pPwrArray
[ALL_TARGET_HT20_23
] =
2113 (u8
)min((u16
)pPwrArray
[ALL_TARGET_HT20_23
],
2118 for (i
= ALL_TARGET_HT40_0_8_16
;
2119 i
<= ALL_TARGET_HT40_23
; i
++)
2121 (u8
)min((u16
)pPwrArray
[i
],
2127 } /* end ctl mode checking */
2130 static void ath9k_hw_ar9300_set_txpower(struct ath_hw
*ah
,
2131 struct ath9k_channel
*chan
, u16 cfgCtl
,
2132 u8 twiceAntennaReduction
,
2133 u8 twiceMaxRegulatoryPower
,
2136 struct ath_common
*common
= ath9k_hw_common(ah
);
2137 u8 targetPowerValT2
[ar9300RateSize
];
2140 ar9003_hw_set_target_power_eeprom(ah
, chan
->channel
, targetPowerValT2
);
2141 ar9003_hw_set_power_per_rate_table(ah
, chan
,
2142 targetPowerValT2
, cfgCtl
,
2143 twiceAntennaReduction
,
2144 twiceMaxRegulatoryPower
,
2147 while (i
< ar9300RateSize
) {
2148 ath_print(common
, ATH_DBG_EEPROM
,
2149 "TPC[%02d] 0x%08x ", i
, targetPowerValT2
[i
]);
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\n\n", i
, targetPowerValT2
[i
]);
2162 /* Write target power array to registers */
2163 ar9003_hw_tx_power_regwrite(ah
, targetPowerValT2
);
2166 * This is the TX power we send back to driver core,
2167 * and it can use to pass to userspace to display our
2168 * currently configured TX power setting.
2170 * Since power is rate dependent, use one of the indices
2171 * from the AR9300_Rates enum to select an entry from
2172 * targetPowerValT2[] to report. Currently returns the
2173 * power for HT40 MCS 0, HT20 MCS 0, or OFDM 6 Mbps
2174 * as CCK power is less interesting (?).
2176 i
= ALL_TARGET_LEGACY_6_24
; /* legacy */
2177 if (IS_CHAN_HT40(chan
))
2178 i
= ALL_TARGET_HT40_0_8_16
; /* ht40 */
2179 else if (IS_CHAN_HT20(chan
))
2180 i
= ALL_TARGET_HT20_0_8_16
; /* ht20 */
2182 ah
->txpower_limit
= targetPowerValT2
[i
];
2184 ar9003_hw_calibration_apply(ah
, chan
->channel
);
2187 static u16
ath9k_hw_ar9300_get_spur_channel(struct ath_hw
*ah
,
2193 s32
ar9003_hw_get_tx_gain_idx(struct ath_hw
*ah
)
2195 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
2197 return (eep
->baseEepHeader
.txrxgain
>> 4) & 0xf; /* bits 7:4 */
2200 s32
ar9003_hw_get_rx_gain_idx(struct ath_hw
*ah
)
2202 struct ar9300_eeprom
*eep
= &ah
->eeprom
.ar9300_eep
;
2204 return (eep
->baseEepHeader
.txrxgain
) & 0xf; /* bits 3:0 */
2207 const struct eeprom_ops eep_ar9300_ops
= {
2208 .check_eeprom
= ath9k_hw_ar9300_check_eeprom
,
2209 .get_eeprom
= ath9k_hw_ar9300_get_eeprom
,
2210 .fill_eeprom
= ath9k_hw_ar9300_fill_eeprom
,
2211 .get_eeprom_ver
= ath9k_hw_ar9300_get_eeprom_ver
,
2212 .get_eeprom_rev
= ath9k_hw_ar9300_get_eeprom_rev
,
2213 .get_num_ant_config
= ath9k_hw_ar9300_get_num_ant_config
,
2214 .get_eeprom_antenna_cfg
= ath9k_hw_ar9300_get_eeprom_antenna_cfg
,
2215 .set_board_values
= ath9k_hw_ar9300_set_board_values
,
2216 .set_addac
= ath9k_hw_ar9300_set_addac
,
2217 .set_txpower
= ath9k_hw_ar9300_set_txpower
,
2218 .get_spur_channel
= ath9k_hw_ar9300_get_spur_channel