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 ieee80211_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