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,
154 .ant_div_control = 0,
155 .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
162 /* ar9300_cal_data_per_freq_op_loop 2g */
164 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
165 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
166 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
168 .calTarget_freqbin_Cck = {
172 .calTarget_freqbin_2G = {
177 .calTarget_freqbin_2GHT20 = {
182 .calTarget_freqbin_2GHT40 = {
187 .calTargetPowerCck = {
188 /* 1L-5L,5S,11L,11S */
189 { {36, 36, 36, 36} },
190 { {36, 36, 36, 36} },
192 .calTargetPower2G = {
194 { {32, 32, 28, 24} },
195 { {32, 32, 28, 24} },
196 { {32, 32, 28, 24} },
198 .calTargetPower2GHT20 = {
199 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
200 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
201 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
203 .calTargetPower2GHT40 = {
204 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
205 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
206 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
209 0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
210 0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
240 /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
241 /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
242 /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
243 /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
247 /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
248 /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
249 /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
254 /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
255 /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
261 /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
262 /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
263 /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
264 /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
268 /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
269 /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
270 /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
274 /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
275 /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
276 /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
281 /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
282 /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
283 /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
288 /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
289 /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
290 /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
291 /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
295 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
296 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
297 { { {60, 1}, {60, 0}, {60, 0}, {60, 1} } },
299 { { {60, 1}, {60, 0}, {0, 0}, {0, 0} } },
300 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
301 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
303 { { {60, 0}, {60, 1}, {60, 1}, {60, 0} } },
304 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
305 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
307 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
308 { { {60, 0}, {60, 1}, {60, 1}, {60, 1} } },
309 { { {60, 0}, {60, 1}, {60, 1}, {60, 1} } },
312 /* 4 idle,t1,t2,b (4 bits per setting) */
313 .antCtrlCommon = LE32(0x110),
314 /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
315 .antCtrlCommon2 = LE32(0x22222),
316 /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
318 LE16(0x000), LE16(0x000), LE16(0x000),
320 /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
321 .xatten1DB = {0, 0, 0},
324 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
325 * for merlin (0xa20c/b20c 16:12
327 .xatten1Margin = {0, 0, 0},
330 /* spurChans spur channels in usual fbin coding format */
331 .spurChans = {0, 0, 0, 0, 0},
332 /* noiseFloorThreshCh Check if the register is per chain */
333 .noiseFloorThreshCh = {-1, 0, 0},
334 .ob = {3, 3, 3}, /* 3 chain */
335 .db_stage2 = {3, 3, 3}, /* 3 chain */
336 .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
337 .db_stage4 = {3, 3, 3}, /* don't exist for 2G */
339 .txFrameToDataStart = 0x0e,
340 .txFrameToPaOn = 0x0e,
341 .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
343 .switchSettling = 0x2d,
344 .adcDesiredSize = -30,
347 .txFrameToXpaOn = 0xe,
349 .papdRateMaskHt20 = LE32(0xf0e0e0),
350 .papdRateMaskHt40 = LE32(0xf0e0e0),
352 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
358 .xatten1DBLow = {0, 0, 0},
359 .xatten1MarginLow = {0, 0, 0},
360 .xatten1DBHigh = {0, 0, 0},
361 .xatten1MarginHigh = {0, 0, 0}
406 .calTarget_freqbin_5G = {
416 .calTarget_freqbin_5GHT20 = {
426 .calTarget_freqbin_5GHT40 = {
436 .calTargetPower5G = {
438 { {20, 20, 20, 10} },
439 { {20, 20, 20, 10} },
440 { {20, 20, 20, 10} },
441 { {20, 20, 20, 10} },
442 { {20, 20, 20, 10} },
443 { {20, 20, 20, 10} },
444 { {20, 20, 20, 10} },
445 { {20, 20, 20, 10} },
447 .calTargetPower5GHT20 = {
449 * 0_8_16,1-3_9-11_17-19,
450 * 4,5,6,7,12,13,14,15,20,21,22,23
452 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
453 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
454 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
455 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
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} },
461 .calTargetPower5GHT40 = {
463 * 0_8_16,1-3_9-11_17-19,
464 * 4,5,6,7,12,13,14,15,20,21,22,23
466 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
467 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
468 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
469 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
470 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
471 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
472 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
473 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
476 0x10, 0x16, 0x18, 0x40, 0x46,
477 0x48, 0x30, 0x36, 0x38
481 /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
482 /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
483 /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
484 /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
485 /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
486 /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
487 /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
488 /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
491 /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
492 /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
493 /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
494 /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
495 /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
496 /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
497 /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
498 /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
502 /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
503 /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
504 /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
505 /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
506 /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
507 /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
508 /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
509 /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
513 /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
514 /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
515 /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
516 /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
517 /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
518 /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
519 /* Data[3].ctlEdges[6].bChannel */ 0xFF,
520 /* Data[3].ctlEdges[7].bChannel */ 0xFF,
524 /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
525 /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
526 /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
527 /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
528 /* Data[4].ctlEdges[4].bChannel */ 0xFF,
529 /* Data[4].ctlEdges[5].bChannel */ 0xFF,
530 /* Data[4].ctlEdges[6].bChannel */ 0xFF,
531 /* Data[4].ctlEdges[7].bChannel */ 0xFF,
535 /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
536 /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
537 /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
538 /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
539 /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
540 /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
541 /* Data[5].ctlEdges[6].bChannel */ 0xFF,
542 /* Data[5].ctlEdges[7].bChannel */ 0xFF
546 /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
547 /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
548 /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
549 /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
550 /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
551 /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
552 /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
553 /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
557 /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
558 /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
559 /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
560 /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
561 /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
562 /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
563 /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
564 /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
568 /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
569 /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
570 /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
571 /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
572 /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
573 /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
574 /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
575 /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
581 {60, 1}, {60, 1}, {60, 1}, {60, 1},
582 {60, 1}, {60, 1}, {60, 1}, {60, 0},
587 {60, 1}, {60, 1}, {60, 1}, {60, 1},
588 {60, 1}, {60, 1}, {60, 1}, {60, 0},
593 {60, 0}, {60, 1}, {60, 0}, {60, 1},
594 {60, 1}, {60, 1}, {60, 1}, {60, 1},
599 {60, 0}, {60, 1}, {60, 1}, {60, 0},
600 {60, 1}, {60, 0}, {60, 0}, {60, 0},
605 {60, 1}, {60, 1}, {60, 1}, {60, 0},
606 {60, 0}, {60, 0}, {60, 0}, {60, 0},
611 {60, 1}, {60, 1}, {60, 1}, {60, 1},
612 {60, 1}, {60, 0}, {60, 0}, {60, 0},
617 {60, 1}, {60, 1}, {60, 1}, {60, 1},
618 {60, 1}, {60, 1}, {60, 1}, {60, 1},
623 {60, 1}, {60, 1}, {60, 0}, {60, 1},
624 {60, 1}, {60, 1}, {60, 1}, {60, 0},
629 {60, 1}, {60, 0}, {60, 1}, {60, 1},
630 {60, 1}, {60, 1}, {60, 0}, {60, 1},
636 static u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
638 if (fbin == AR9300_BCHAN_UNUSED)
641 return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
644 static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah)
649 static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
650 enum eeprom_param param)
652 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
653 struct ar9300_base_eep_hdr *pBase = &eep->baseEepHeader;
657 return eep->macAddr[0] << 8 | eep->macAddr[1];
659 return eep->macAddr[2] << 8 | eep->macAddr[3];
661 return eep->macAddr[4] << 8 | eep->macAddr[5];
663 return le16_to_cpu(pBase->regDmn[0]);
665 return le16_to_cpu(pBase->regDmn[1]);
667 return pBase->deviceCap;
669 return pBase->opCapFlags.opFlags;
671 return pBase->rfSilent;
673 return (pBase->txrxMask >> 4) & 0xf;
675 return pBase->txrxMask & 0xf;
676 case EEP_DRIVE_STRENGTH:
677 #define AR9300_EEP_BASE_DRIV_STRENGTH 0x1
678 return pBase->miscConfiguration & AR9300_EEP_BASE_DRIV_STRENGTH;
679 case EEP_INTERNAL_REGULATOR:
680 /* Bit 4 is internal regulator flag */
681 return (pBase->featureEnable & 0x10) >> 4;
683 return le32_to_cpu(pBase->swreg);
685 return !!(pBase->featureEnable & BIT(5));
691 static bool ar9300_eeprom_read_byte(struct ath_common *common, int address,
696 if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
699 *buffer = (val >> (8 * (address % 2))) & 0xff;
703 static bool ar9300_eeprom_read_word(struct ath_common *common, int address,
708 if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
711 buffer[0] = val >> 8;
712 buffer[1] = val & 0xff;
717 static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer,
720 struct ath_common *common = ath9k_hw_common(ah);
723 if ((address < 0) || ((address + count) / 2 > AR9300_EEPROM_SIZE - 1)) {
724 ath_print(common, ATH_DBG_EEPROM,
725 "eeprom address not in range\n");
730 * Since we're reading the bytes in reverse order from a little-endian
731 * word stream, an even address means we only use the lower half of
732 * the 16-bit word at that address
734 if (address % 2 == 0) {
735 if (!ar9300_eeprom_read_byte(common, address--, buffer++))
741 for (i = 0; i < count / 2; i++) {
742 if (!ar9300_eeprom_read_word(common, address, buffer))
750 if (!ar9300_eeprom_read_byte(common, address, buffer))
756 ath_print(common, ATH_DBG_EEPROM,
757 "unable to read eeprom region at offset %d\n", address);
761 static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference,
762 int *length, int *major, int *minor)
764 unsigned long value[4];
770 *code = ((value[0] >> 5) & 0x0007);
771 *reference = (value[0] & 0x001f) | ((value[1] >> 2) & 0x0020);
772 *length = ((value[1] << 4) & 0x07f0) | ((value[2] >> 4) & 0x000f);
773 *major = (value[2] & 0x000f);
774 *minor = (value[3] & 0x00ff);
777 static u16 ar9300_comp_cksum(u8 *data, int dsize)
779 int it, checksum = 0;
781 for (it = 0; it < dsize; it++) {
782 checksum += data[it];
789 static bool ar9300_uncompress_block(struct ath_hw *ah,
799 struct ath_common *common = ath9k_hw_common(ah);
803 for (it = 0; it < size; it += (length+2)) {
807 length = block[it+1];
810 if (length > 0 && spot >= 0 && spot+length <= mdataSize) {
811 ath_print(common, ATH_DBG_EEPROM,
812 "Restore at %d: spot=%d "
813 "offset=%d length=%d\n",
814 it, spot, offset, length);
815 memcpy(&mptr[spot], &block[it+2], length);
817 } else if (length > 0) {
818 ath_print(common, ATH_DBG_EEPROM,
819 "Bad restore at %d: spot=%d "
820 "offset=%d length=%d\n",
821 it, spot, offset, length);
828 static int ar9300_compress_decision(struct ath_hw *ah,
833 u8 *word, int length, int mdata_size)
835 struct ath_common *common = ath9k_hw_common(ah);
840 if (length != mdata_size) {
841 ath_print(common, ATH_DBG_EEPROM,
842 "EEPROM structure size mismatch"
843 "memory=%d eeprom=%d\n", mdata_size, length);
846 memcpy(mptr, (u8 *) (word + COMP_HDR_LEN), length);
847 ath_print(common, ATH_DBG_EEPROM, "restored eeprom %d:"
848 " uncompressed, length %d\n", it, length);
851 if (reference == 0) {
854 if (reference != 2) {
855 ath_print(common, ATH_DBG_EEPROM,
856 "cant find reference eeprom"
857 "struct %d\n", reference);
860 memcpy(mptr, &ar9300_default, mdata_size);
862 ath_print(common, ATH_DBG_EEPROM,
863 "restore eeprom %d: block, reference %d,"
864 " length %d\n", it, reference, length);
865 ar9300_uncompress_block(ah, mptr, mdata_size,
866 (u8 *) (word + COMP_HDR_LEN), length);
869 ath_print(common, ATH_DBG_EEPROM, "unknown compression"
877 * Read the configuration data from the eeprom.
878 * The data can be put in any specified memory buffer.
880 * Returns -1 on error.
881 * Returns address of next memory location on success.
883 static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
884 u8 *mptr, int mdata_size)
891 int reference, length, major, minor;
894 u16 checksum, mchecksum;
895 struct ath_common *common = ath9k_hw_common(ah);
897 word = kzalloc(2048, GFP_KERNEL);
901 memcpy(mptr, &ar9300_default, mdata_size);
903 cptr = AR9300_BASE_ADDR;
904 for (it = 0; it < MSTATE; it++) {
905 if (!ar9300_read_eeprom(ah, cptr, word, COMP_HDR_LEN))
908 if ((word[0] == 0 && word[1] == 0 && word[2] == 0 &&
909 word[3] == 0) || (word[0] == 0xff && word[1] == 0xff
910 && word[2] == 0xff && word[3] == 0xff))
913 ar9300_comp_hdr_unpack(word, &code, &reference,
914 &length, &major, &minor);
915 ath_print(common, ATH_DBG_EEPROM,
916 "Found block at %x: code=%d ref=%d"
917 "length=%d major=%d minor=%d\n", cptr, code,
918 reference, length, major, minor);
919 if (length >= 1024) {
920 ath_print(common, ATH_DBG_EEPROM,
921 "Skipping bad header\n");
922 cptr -= COMP_HDR_LEN;
927 ar9300_read_eeprom(ah, cptr, word,
928 COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
929 checksum = ar9300_comp_cksum(&word[COMP_HDR_LEN], length);
930 mchecksum = word[COMP_HDR_LEN + osize] |
931 (word[COMP_HDR_LEN + osize + 1] << 8);
932 ath_print(common, ATH_DBG_EEPROM,
933 "checksum %x %x\n", checksum, mchecksum);
934 if (checksum == mchecksum) {
935 ar9300_compress_decision(ah, it, code, reference, mptr,
936 word, length, mdata_size);
938 ath_print(common, ATH_DBG_EEPROM,
939 "skipping block with bad checksum\n");
941 cptr -= (COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
953 * Restore the configuration structure by reading the eeprom.
954 * This function destroys any existing in-memory structure
957 static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw *ah)
959 u8 *mptr = (u8 *) &ah->eeprom.ar9300_eep;
961 if (ar9300_eeprom_restore_internal(ah, mptr,
962 sizeof(struct ar9300_eeprom)) < 0)
968 /* XXX: review hardware docs */
969 static int ath9k_hw_ar9300_get_eeprom_ver(struct ath_hw *ah)
971 return ah->eeprom.ar9300_eep.eepromVersion;
974 /* XXX: could be read from the eepromVersion, not sure yet */
975 static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw *ah)
980 static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah,
981 enum ath9k_hal_freq_band freq_band)
986 static u32 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah,
987 struct ath9k_channel *chan)
992 static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz)
994 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
997 return eep->modalHeader2G.xpaBiasLvl;
999 return eep->modalHeader5G.xpaBiasLvl;
1002 static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
1004 int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz);
1005 REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, (bias & 0x3));
1006 REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_SPARE,
1007 ((bias >> 2) & 0x3));
1010 static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz)
1012 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1016 val = eep->modalHeader2G.antCtrlCommon;
1018 val = eep->modalHeader5G.antCtrlCommon;
1019 return le32_to_cpu(val);
1022 static u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz)
1024 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1028 val = eep->modalHeader2G.antCtrlCommon2;
1030 val = eep->modalHeader5G.antCtrlCommon2;
1031 return le32_to_cpu(val);
1034 static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah,
1038 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1041 if (chain >= 0 && chain < AR9300_MAX_CHAINS) {
1043 val = eep->modalHeader2G.antCtrlChain[chain];
1045 val = eep->modalHeader5G.antCtrlChain[chain];
1048 return le16_to_cpu(val);
1051 static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
1053 u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);
1054 REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value);
1056 value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz);
1057 REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
1059 value = ar9003_hw_ant_ctrl_chain_get(ah, 0, is2ghz);
1060 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value);
1062 value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz);
1063 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, value);
1065 value = ar9003_hw_ant_ctrl_chain_get(ah, 2, is2ghz);
1066 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, value);
1069 static void ar9003_hw_drive_strength_apply(struct ath_hw *ah)
1074 drive_strength = ath9k_hw_ar9300_get_eeprom(ah, EEP_DRIVE_STRENGTH);
1076 if (!drive_strength)
1079 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS1);
1087 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS1, reg);
1089 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS2);
1100 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS2, reg);
1102 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS4);
1107 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS4, reg);
1110 static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
1112 int internal_regulator =
1113 ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);
1115 if (internal_regulator) {
1116 /* Internal regulator is ON. Write swreg register. */
1117 int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
1118 REG_WRITE(ah, AR_RTC_REG_CONTROL1,
1119 REG_READ(ah, AR_RTC_REG_CONTROL1) &
1120 (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM));
1121 REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg);
1122 /* Set REG_CONTROL1.SWREG_PROGRAM */
1123 REG_WRITE(ah, AR_RTC_REG_CONTROL1,
1125 AR_RTC_REG_CONTROL1) |
1126 AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
1128 REG_WRITE(ah, AR_RTC_SLEEP_CLK,
1131 AR_RTC_FORCE_SWREG_PRD));
1135 static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
1136 struct ath9k_channel *chan)
1138 ar9003_hw_xpa_bias_level_apply(ah, IS_CHAN_2GHZ(chan));
1139 ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan));
1140 ar9003_hw_drive_strength_apply(ah);
1141 ar9003_hw_internal_regulator_apply(ah);
1144 static void ath9k_hw_ar9300_set_addac(struct ath_hw *ah,
1145 struct ath9k_channel *chan)
1150 * Returns the interpolated y value corresponding to the specified x value
1151 * from the np ordered pairs of data (px,py).
1152 * The pairs do not have to be in any order.
1153 * If the specified x value is less than any of the px,
1154 * the returned y value is equal to the py for the lowest px.
1155 * If the specified x value is greater than any of the px,
1156 * the returned y value is equal to the py for the highest px.
1158 static int ar9003_hw_power_interpolate(int32_t x,
1159 int32_t *px, int32_t *py, u_int16_t np)
1162 int lx = 0, ly = 0, lhave = 0;
1163 int hx = 0, hy = 0, hhave = 0;
1170 /* identify best lower and higher x calibration measurement */
1171 for (ip = 0; ip < np; ip++) {
1174 /* this measurement is higher than our desired x */
1176 if (!hhave || dx > (x - hx)) {
1177 /* new best higher x measurement */
1183 /* this measurement is lower than our desired x */
1185 if (!lhave || dx < (x - lx)) {
1186 /* new best lower x measurement */
1194 /* the low x is good */
1196 /* so is the high x */
1198 /* they're the same, so just pick one */
1201 else /* interpolate */
1202 y = ly + (((x - lx) * (hy - ly)) / (hx - lx));
1203 } else /* only low is good, use it */
1205 } else if (hhave) /* only high is good, use it */
1207 else /* nothing is good,this should never happen unless np=0, ???? */
1212 static u8 ar9003_hw_eeprom_get_tgt_pwr(struct ath_hw *ah,
1213 u16 rateIndex, u16 freq, bool is2GHz)
1216 s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS];
1217 s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS];
1218 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1219 struct cal_tgt_pow_legacy *pEepromTargetPwr;
1223 numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
1224 pEepromTargetPwr = eep->calTargetPower2G;
1225 pFreqBin = eep->calTarget_freqbin_2G;
1227 numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
1228 pEepromTargetPwr = eep->calTargetPower5G;
1229 pFreqBin = eep->calTarget_freqbin_5G;
1233 * create array of channels and targetpower from
1234 * targetpower piers stored on eeprom
1236 for (i = 0; i < numPiers; i++) {
1237 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1238 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1241 /* interpolate to get target power for given frequency */
1242 return (u8) ar9003_hw_power_interpolate((s32) freq,
1244 targetPowerArray, numPiers);
1247 static u8 ar9003_hw_eeprom_get_ht20_tgt_pwr(struct ath_hw *ah,
1249 u16 freq, bool is2GHz)
1252 s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS];
1253 s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS];
1254 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1255 struct cal_tgt_pow_ht *pEepromTargetPwr;
1259 numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
1260 pEepromTargetPwr = eep->calTargetPower2GHT20;
1261 pFreqBin = eep->calTarget_freqbin_2GHT20;
1263 numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
1264 pEepromTargetPwr = eep->calTargetPower5GHT20;
1265 pFreqBin = eep->calTarget_freqbin_5GHT20;
1269 * create array of channels and targetpower
1270 * from targetpower piers stored on eeprom
1272 for (i = 0; i < numPiers; i++) {
1273 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1274 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1277 /* interpolate to get target power for given frequency */
1278 return (u8) ar9003_hw_power_interpolate((s32) freq,
1280 targetPowerArray, numPiers);
1283 static u8 ar9003_hw_eeprom_get_ht40_tgt_pwr(struct ath_hw *ah,
1285 u16 freq, bool is2GHz)
1288 s32 targetPowerArray[AR9300_NUM_5G_40_TARGET_POWERS];
1289 s32 freqArray[AR9300_NUM_5G_40_TARGET_POWERS];
1290 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1291 struct cal_tgt_pow_ht *pEepromTargetPwr;
1295 numPiers = AR9300_NUM_2G_40_TARGET_POWERS;
1296 pEepromTargetPwr = eep->calTargetPower2GHT40;
1297 pFreqBin = eep->calTarget_freqbin_2GHT40;
1299 numPiers = AR9300_NUM_5G_40_TARGET_POWERS;
1300 pEepromTargetPwr = eep->calTargetPower5GHT40;
1301 pFreqBin = eep->calTarget_freqbin_5GHT40;
1305 * create array of channels and targetpower from
1306 * targetpower piers stored on eeprom
1308 for (i = 0; i < numPiers; i++) {
1309 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1310 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1313 /* interpolate to get target power for given frequency */
1314 return (u8) ar9003_hw_power_interpolate((s32) freq,
1316 targetPowerArray, numPiers);
1319 static u8 ar9003_hw_eeprom_get_cck_tgt_pwr(struct ath_hw *ah,
1320 u16 rateIndex, u16 freq)
1322 u16 numPiers = AR9300_NUM_2G_CCK_TARGET_POWERS, i;
1323 s32 targetPowerArray[AR9300_NUM_2G_CCK_TARGET_POWERS];
1324 s32 freqArray[AR9300_NUM_2G_CCK_TARGET_POWERS];
1325 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1326 struct cal_tgt_pow_legacy *pEepromTargetPwr = eep->calTargetPowerCck;
1327 u8 *pFreqBin = eep->calTarget_freqbin_Cck;
1330 * create array of channels and targetpower from
1331 * targetpower piers stored on eeprom
1333 for (i = 0; i < numPiers; i++) {
1334 freqArray[i] = FBIN2FREQ(pFreqBin[i], 1);
1335 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1338 /* interpolate to get target power for given frequency */
1339 return (u8) ar9003_hw_power_interpolate((s32) freq,
1341 targetPowerArray, numPiers);
1344 /* Set tx power registers to array of values passed in */
1345 static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
1347 #define POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
1348 /* make sure forced gain is not set */
1349 REG_WRITE(ah, 0xa458, 0);
1351 /* Write the OFDM power per rate set */
1353 /* 6 (LSB), 9, 12, 18 (MSB) */
1354 REG_WRITE(ah, 0xa3c0,
1355 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) |
1356 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 16) |
1357 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) |
1358 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0));
1360 /* 24 (LSB), 36, 48, 54 (MSB) */
1361 REG_WRITE(ah, 0xa3c4,
1362 POW_SM(pPwrArray[ALL_TARGET_LEGACY_54], 24) |
1363 POW_SM(pPwrArray[ALL_TARGET_LEGACY_48], 16) |
1364 POW_SM(pPwrArray[ALL_TARGET_LEGACY_36], 8) |
1365 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0));
1367 /* Write the CCK power per rate set */
1369 /* 1L (LSB), reserved, 2L, 2S (MSB) */
1370 REG_WRITE(ah, 0xa3c8,
1371 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 24) |
1372 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) |
1373 /* POW_SM(txPowerTimes2, 8) | this is reserved for AR9003 */
1374 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0));
1376 /* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */
1377 REG_WRITE(ah, 0xa3cc,
1378 POW_SM(pPwrArray[ALL_TARGET_LEGACY_11S], 24) |
1379 POW_SM(pPwrArray[ALL_TARGET_LEGACY_11L], 16) |
1380 POW_SM(pPwrArray[ALL_TARGET_LEGACY_5S], 8) |
1381 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0)
1384 /* Write the HT20 power per rate set */
1386 /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */
1387 REG_WRITE(ah, 0xa3d0,
1388 POW_SM(pPwrArray[ALL_TARGET_HT20_5], 24) |
1389 POW_SM(pPwrArray[ALL_TARGET_HT20_4], 16) |
1390 POW_SM(pPwrArray[ALL_TARGET_HT20_1_3_9_11_17_19], 8) |
1391 POW_SM(pPwrArray[ALL_TARGET_HT20_0_8_16], 0)
1394 /* 6 (LSB), 7, 12, 13 (MSB) */
1395 REG_WRITE(ah, 0xa3d4,
1396 POW_SM(pPwrArray[ALL_TARGET_HT20_13], 24) |
1397 POW_SM(pPwrArray[ALL_TARGET_HT20_12], 16) |
1398 POW_SM(pPwrArray[ALL_TARGET_HT20_7], 8) |
1399 POW_SM(pPwrArray[ALL_TARGET_HT20_6], 0)
1402 /* 14 (LSB), 15, 20, 21 */
1403 REG_WRITE(ah, 0xa3e4,
1404 POW_SM(pPwrArray[ALL_TARGET_HT20_21], 24) |
1405 POW_SM(pPwrArray[ALL_TARGET_HT20_20], 16) |
1406 POW_SM(pPwrArray[ALL_TARGET_HT20_15], 8) |
1407 POW_SM(pPwrArray[ALL_TARGET_HT20_14], 0)
1410 /* Mixed HT20 and HT40 rates */
1412 /* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */
1413 REG_WRITE(ah, 0xa3e8,
1414 POW_SM(pPwrArray[ALL_TARGET_HT40_23], 24) |
1415 POW_SM(pPwrArray[ALL_TARGET_HT40_22], 16) |
1416 POW_SM(pPwrArray[ALL_TARGET_HT20_23], 8) |
1417 POW_SM(pPwrArray[ALL_TARGET_HT20_22], 0)
1421 * Write the HT40 power per rate set
1422 * correct PAR difference between HT40 and HT20/LEGACY
1423 * 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB)
1425 REG_WRITE(ah, 0xa3d8,
1426 POW_SM(pPwrArray[ALL_TARGET_HT40_5], 24) |
1427 POW_SM(pPwrArray[ALL_TARGET_HT40_4], 16) |
1428 POW_SM(pPwrArray[ALL_TARGET_HT40_1_3_9_11_17_19], 8) |
1429 POW_SM(pPwrArray[ALL_TARGET_HT40_0_8_16], 0)
1432 /* 6 (LSB), 7, 12, 13 (MSB) */
1433 REG_WRITE(ah, 0xa3dc,
1434 POW_SM(pPwrArray[ALL_TARGET_HT40_13], 24) |
1435 POW_SM(pPwrArray[ALL_TARGET_HT40_12], 16) |
1436 POW_SM(pPwrArray[ALL_TARGET_HT40_7], 8) |
1437 POW_SM(pPwrArray[ALL_TARGET_HT40_6], 0)
1440 /* 14 (LSB), 15, 20, 21 */
1441 REG_WRITE(ah, 0xa3ec,
1442 POW_SM(pPwrArray[ALL_TARGET_HT40_21], 24) |
1443 POW_SM(pPwrArray[ALL_TARGET_HT40_20], 16) |
1444 POW_SM(pPwrArray[ALL_TARGET_HT40_15], 8) |
1445 POW_SM(pPwrArray[ALL_TARGET_HT40_14], 0)
1452 static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq,
1453 u8 *targetPowerValT2)
1455 /* XXX: hard code for now, need to get from eeprom struct */
1456 u8 ht40PowerIncForPdadc = 0;
1457 bool is2GHz = false;
1459 struct ath_common *common = ath9k_hw_common(ah);
1464 targetPowerValT2[ALL_TARGET_LEGACY_6_24] =
1465 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_6_24, freq,
1467 targetPowerValT2[ALL_TARGET_LEGACY_36] =
1468 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_36, freq,
1470 targetPowerValT2[ALL_TARGET_LEGACY_48] =
1471 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_48, freq,
1473 targetPowerValT2[ALL_TARGET_LEGACY_54] =
1474 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_54, freq,
1476 targetPowerValT2[ALL_TARGET_LEGACY_1L_5L] =
1477 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_1L_5L,
1479 targetPowerValT2[ALL_TARGET_LEGACY_5S] =
1480 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_5S, freq);
1481 targetPowerValT2[ALL_TARGET_LEGACY_11L] =
1482 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11L, freq);
1483 targetPowerValT2[ALL_TARGET_LEGACY_11S] =
1484 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11S, freq);
1485 targetPowerValT2[ALL_TARGET_HT20_0_8_16] =
1486 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq,
1488 targetPowerValT2[ALL_TARGET_HT20_1_3_9_11_17_19] =
1489 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19,
1491 targetPowerValT2[ALL_TARGET_HT20_4] =
1492 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_4, freq,
1494 targetPowerValT2[ALL_TARGET_HT20_5] =
1495 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_5, freq,
1497 targetPowerValT2[ALL_TARGET_HT20_6] =
1498 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_6, freq,
1500 targetPowerValT2[ALL_TARGET_HT20_7] =
1501 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_7, freq,
1503 targetPowerValT2[ALL_TARGET_HT20_12] =
1504 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_12, freq,
1506 targetPowerValT2[ALL_TARGET_HT20_13] =
1507 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_13, freq,
1509 targetPowerValT2[ALL_TARGET_HT20_14] =
1510 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_14, freq,
1512 targetPowerValT2[ALL_TARGET_HT20_15] =
1513 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_15, freq,
1515 targetPowerValT2[ALL_TARGET_HT20_20] =
1516 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_20, freq,
1518 targetPowerValT2[ALL_TARGET_HT20_21] =
1519 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_21, freq,
1521 targetPowerValT2[ALL_TARGET_HT20_22] =
1522 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_22, freq,
1524 targetPowerValT2[ALL_TARGET_HT20_23] =
1525 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
1527 targetPowerValT2[ALL_TARGET_HT40_0_8_16] =
1528 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq,
1529 is2GHz) + ht40PowerIncForPdadc;
1530 targetPowerValT2[ALL_TARGET_HT40_1_3_9_11_17_19] =
1531 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19,
1533 is2GHz) + ht40PowerIncForPdadc;
1534 targetPowerValT2[ALL_TARGET_HT40_4] =
1535 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_4, freq,
1536 is2GHz) + ht40PowerIncForPdadc;
1537 targetPowerValT2[ALL_TARGET_HT40_5] =
1538 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_5, freq,
1539 is2GHz) + ht40PowerIncForPdadc;
1540 targetPowerValT2[ALL_TARGET_HT40_6] =
1541 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_6, freq,
1542 is2GHz) + ht40PowerIncForPdadc;
1543 targetPowerValT2[ALL_TARGET_HT40_7] =
1544 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_7, freq,
1545 is2GHz) + ht40PowerIncForPdadc;
1546 targetPowerValT2[ALL_TARGET_HT40_12] =
1547 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_12, freq,
1548 is2GHz) + ht40PowerIncForPdadc;
1549 targetPowerValT2[ALL_TARGET_HT40_13] =
1550 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_13, freq,
1551 is2GHz) + ht40PowerIncForPdadc;
1552 targetPowerValT2[ALL_TARGET_HT40_14] =
1553 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_14, freq,
1554 is2GHz) + ht40PowerIncForPdadc;
1555 targetPowerValT2[ALL_TARGET_HT40_15] =
1556 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_15, freq,
1557 is2GHz) + ht40PowerIncForPdadc;
1558 targetPowerValT2[ALL_TARGET_HT40_20] =
1559 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_20, freq,
1560 is2GHz) + ht40PowerIncForPdadc;
1561 targetPowerValT2[ALL_TARGET_HT40_21] =
1562 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_21, freq,
1563 is2GHz) + ht40PowerIncForPdadc;
1564 targetPowerValT2[ALL_TARGET_HT40_22] =
1565 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_22, freq,
1566 is2GHz) + ht40PowerIncForPdadc;
1567 targetPowerValT2[ALL_TARGET_HT40_23] =
1568 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
1569 is2GHz) + ht40PowerIncForPdadc;
1571 while (i < ar9300RateSize) {
1572 ath_print(common, ATH_DBG_EEPROM,
1573 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1576 ath_print(common, ATH_DBG_EEPROM,
1577 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1580 ath_print(common, ATH_DBG_EEPROM,
1581 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1584 ath_print(common, ATH_DBG_EEPROM,
1585 "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
1590 static int ar9003_hw_cal_pier_get(struct ath_hw *ah,
1596 int *ptemperature, int *pvoltage)
1599 struct ar9300_cal_data_per_freq_op_loop *pCalPierStruct;
1601 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1602 struct ath_common *common = ath9k_hw_common(ah);
1604 if (ichain >= AR9300_MAX_CHAINS) {
1605 ath_print(common, ATH_DBG_EEPROM,
1606 "Invalid chain index, must be less than %d\n",
1611 if (mode) { /* 5GHz */
1612 if (ipier >= AR9300_NUM_5G_CAL_PIERS) {
1613 ath_print(common, ATH_DBG_EEPROM,
1614 "Invalid 5GHz cal pier index, must "
1615 "be less than %d\n",
1616 AR9300_NUM_5G_CAL_PIERS);
1619 pCalPier = &(eep->calFreqPier5G[ipier]);
1620 pCalPierStruct = &(eep->calPierData5G[ichain][ipier]);
1623 if (ipier >= AR9300_NUM_2G_CAL_PIERS) {
1624 ath_print(common, ATH_DBG_EEPROM,
1625 "Invalid 2GHz cal pier index, must "
1626 "be less than %d\n", AR9300_NUM_2G_CAL_PIERS);
1630 pCalPier = &(eep->calFreqPier2G[ipier]);
1631 pCalPierStruct = &(eep->calPierData2G[ichain][ipier]);
1635 *pfrequency = FBIN2FREQ(*pCalPier, is2GHz);
1636 *pcorrection = pCalPierStruct->refPower;
1637 *ptemperature = pCalPierStruct->tempMeas;
1638 *pvoltage = pCalPierStruct->voltMeas;
1643 static int ar9003_hw_power_control_override(struct ath_hw *ah,
1646 int *voltage, int *temperature)
1649 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1651 REG_RMW(ah, AR_PHY_TPC_11_B0,
1652 (correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1653 AR_PHY_TPC_OLPC_GAIN_DELTA);
1654 REG_RMW(ah, AR_PHY_TPC_11_B1,
1655 (correction[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1656 AR_PHY_TPC_OLPC_GAIN_DELTA);
1657 REG_RMW(ah, AR_PHY_TPC_11_B2,
1658 (correction[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1659 AR_PHY_TPC_OLPC_GAIN_DELTA);
1661 /* enable open loop power control on chip */
1662 REG_RMW(ah, AR_PHY_TPC_6_B0,
1663 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
1664 AR_PHY_TPC_6_ERROR_EST_MODE);
1665 REG_RMW(ah, AR_PHY_TPC_6_B1,
1666 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
1667 AR_PHY_TPC_6_ERROR_EST_MODE);
1668 REG_RMW(ah, AR_PHY_TPC_6_B2,
1669 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
1670 AR_PHY_TPC_6_ERROR_EST_MODE);
1673 * enable temperature compensation
1674 * Need to use register names
1676 if (frequency < 4000)
1677 tempSlope = eep->modalHeader2G.tempSlope;
1679 tempSlope = eep->modalHeader5G.tempSlope;
1681 REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope);
1682 REG_RMW_FIELD(ah, AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE,
1688 /* Apply the recorded correction values. */
1689 static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
1691 int ichain, ipier, npier;
1693 int lfrequency[AR9300_MAX_CHAINS],
1694 lcorrection[AR9300_MAX_CHAINS],
1695 ltemperature[AR9300_MAX_CHAINS], lvoltage[AR9300_MAX_CHAINS];
1696 int hfrequency[AR9300_MAX_CHAINS],
1697 hcorrection[AR9300_MAX_CHAINS],
1698 htemperature[AR9300_MAX_CHAINS], hvoltage[AR9300_MAX_CHAINS];
1700 int correction[AR9300_MAX_CHAINS],
1701 voltage[AR9300_MAX_CHAINS], temperature[AR9300_MAX_CHAINS];
1702 int pfrequency, pcorrection, ptemperature, pvoltage;
1703 struct ath_common *common = ath9k_hw_common(ah);
1705 mode = (frequency >= 4000);
1707 npier = AR9300_NUM_5G_CAL_PIERS;
1709 npier = AR9300_NUM_2G_CAL_PIERS;
1711 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1712 lfrequency[ichain] = 0;
1713 hfrequency[ichain] = 100000;
1715 /* identify best lower and higher frequency calibration measurement */
1716 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1717 for (ipier = 0; ipier < npier; ipier++) {
1718 if (!ar9003_hw_cal_pier_get(ah, mode, ipier, ichain,
1719 &pfrequency, &pcorrection,
1720 &ptemperature, &pvoltage)) {
1721 fdiff = frequency - pfrequency;
1724 * this measurement is higher than
1725 * our desired frequency
1728 if (hfrequency[ichain] <= 0 ||
1729 hfrequency[ichain] >= 100000 ||
1731 (frequency - hfrequency[ichain])) {
1734 * frequency measurement
1736 hfrequency[ichain] = pfrequency;
1737 hcorrection[ichain] =
1739 htemperature[ichain] =
1741 hvoltage[ichain] = pvoltage;
1745 if (lfrequency[ichain] <= 0
1747 (frequency - lfrequency[ichain])) {
1750 * frequency measurement
1752 lfrequency[ichain] = pfrequency;
1753 lcorrection[ichain] =
1755 ltemperature[ichain] =
1757 lvoltage[ichain] = pvoltage;
1765 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1766 ath_print(common, ATH_DBG_EEPROM,
1767 "ch=%d f=%d low=%d %d h=%d %d\n",
1768 ichain, frequency, lfrequency[ichain],
1769 lcorrection[ichain], hfrequency[ichain],
1770 hcorrection[ichain]);
1771 /* they're the same, so just pick one */
1772 if (hfrequency[ichain] == lfrequency[ichain]) {
1773 correction[ichain] = lcorrection[ichain];
1774 voltage[ichain] = lvoltage[ichain];
1775 temperature[ichain] = ltemperature[ichain];
1777 /* the low frequency is good */
1778 else if (frequency - lfrequency[ichain] < 1000) {
1779 /* so is the high frequency, interpolate */
1780 if (hfrequency[ichain] - frequency < 1000) {
1782 correction[ichain] = lcorrection[ichain] +
1783 (((frequency - lfrequency[ichain]) *
1784 (hcorrection[ichain] -
1785 lcorrection[ichain])) /
1786 (hfrequency[ichain] - lfrequency[ichain]));
1788 temperature[ichain] = ltemperature[ichain] +
1789 (((frequency - lfrequency[ichain]) *
1790 (htemperature[ichain] -
1791 ltemperature[ichain])) /
1792 (hfrequency[ichain] - lfrequency[ichain]));
1797 lfrequency[ichain]) * (hvoltage[ichain] -
1799 / (hfrequency[ichain] -
1800 lfrequency[ichain]));
1802 /* only low is good, use it */
1804 correction[ichain] = lcorrection[ichain];
1805 temperature[ichain] = ltemperature[ichain];
1806 voltage[ichain] = lvoltage[ichain];
1809 /* only high is good, use it */
1810 else if (hfrequency[ichain] - frequency < 1000) {
1811 correction[ichain] = hcorrection[ichain];
1812 temperature[ichain] = htemperature[ichain];
1813 voltage[ichain] = hvoltage[ichain];
1814 } else { /* nothing is good, presume 0???? */
1815 correction[ichain] = 0;
1816 temperature[ichain] = 0;
1817 voltage[ichain] = 0;
1821 ar9003_hw_power_control_override(ah, frequency, correction, voltage,
1824 ath_print(common, ATH_DBG_EEPROM,
1825 "for frequency=%d, calibration correction = %d %d %d\n",
1826 frequency, correction[0], correction[1], correction[2]);
1831 static u16 ar9003_hw_get_direct_edge_power(struct ar9300_eeprom *eep,
1836 struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G;
1837 struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G;
1840 return ctl_2g[idx].ctlEdges[edge].tPower;
1842 return ctl_5g[idx].ctlEdges[edge].tPower;
1845 static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep,
1851 struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G;
1852 struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G;
1854 u8 *ctl_freqbin = is2GHz ?
1855 &eep->ctl_freqbin_2G[idx][0] :
1856 &eep->ctl_freqbin_5G[idx][0];
1859 if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 1) < freq &&
1860 ctl_2g[idx].ctlEdges[edge - 1].flag)
1861 return ctl_2g[idx].ctlEdges[edge - 1].tPower;
1863 if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 0) < freq &&
1864 ctl_5g[idx].ctlEdges[edge - 1].flag)
1865 return ctl_5g[idx].ctlEdges[edge - 1].tPower;
1868 return AR9300_MAX_RATE_POWER;
1872 * Find the maximum conformance test limit for the given channel and CTL info
1874 static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep,
1875 u16 freq, int idx, bool is2GHz)
1877 u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER;
1878 u8 *ctl_freqbin = is2GHz ?
1879 &eep->ctl_freqbin_2G[idx][0] :
1880 &eep->ctl_freqbin_5G[idx][0];
1881 u16 num_edges = is2GHz ?
1882 AR9300_NUM_BAND_EDGES_2G : AR9300_NUM_BAND_EDGES_5G;
1885 /* Get the edge power */
1887 (edge < num_edges) && (ctl_freqbin[edge] != AR9300_BCHAN_UNUSED);
1890 * If there's an exact channel match or an inband flag set
1891 * on the lower channel use the given rdEdgePower
1893 if (freq == ath9k_hw_fbin2freq(ctl_freqbin[edge], is2GHz)) {
1895 ar9003_hw_get_direct_edge_power(eep, idx,
1898 } else if ((edge > 0) &&
1899 (freq < ath9k_hw_fbin2freq(ctl_freqbin[edge],
1902 ar9003_hw_get_indirect_edge_power(eep, idx,
1906 * Leave loop - no more affecting edges possible in
1907 * this monotonic increasing list
1912 return twiceMaxEdgePower;
1915 static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
1916 struct ath9k_channel *chan,
1917 u8 *pPwrArray, u16 cfgCtl,
1918 u8 twiceAntennaReduction,
1919 u8 twiceMaxRegulatoryPower,
1922 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
1923 struct ath_common *common = ath9k_hw_common(ah);
1924 struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep;
1925 u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER;
1926 static const u16 tpScaleReductionTable[5] = {
1927 0, 3, 6, 9, AR9300_MAX_RATE_POWER
1930 int16_t twiceLargestAntenna;
1931 u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
1932 u16 ctlModesFor11a[] = {
1933 CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
1935 u16 ctlModesFor11g[] = {
1936 CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT,
1937 CTL_11G_EXT, CTL_2GHT40
1939 u16 numCtlModes, *pCtlMode, ctlMode, freq;
1940 struct chan_centers centers;
1943 u16 twiceMinEdgePower;
1944 bool is2ghz = IS_CHAN_2GHZ(chan);
1946 ath9k_hw_get_channel_centers(ah, chan, ¢ers);
1948 /* Compute TxPower reduction due to Antenna Gain */
1950 twiceLargestAntenna = pEepData->modalHeader2G.antennaGain;
1952 twiceLargestAntenna = pEepData->modalHeader5G.antennaGain;
1954 twiceLargestAntenna = (int16_t)min((twiceAntennaReduction) -
1955 twiceLargestAntenna, 0);
1958 * scaledPower is the minimum of the user input power level
1959 * and the regulatory allowed power level
1961 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
1963 if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
1964 maxRegAllowedPower -=
1965 (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
1968 scaledPower = min(powerLimit, maxRegAllowedPower);
1971 * Reduce scaled Power by number of chains active to get
1972 * to per chain tx power level
1974 switch (ar5416_get_ntxchains(ah->txchainmask)) {
1978 scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
1981 scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
1985 scaledPower = max((u16)0, scaledPower);
1988 * Get target powers from EEPROM - our baseline for TX Power
1991 /* Setup for CTL modes */
1992 /* CTL_11B, CTL_11G, CTL_2GHT20 */
1994 ARRAY_SIZE(ctlModesFor11g) -
1995 SUB_NUM_CTL_MODES_AT_2G_40;
1996 pCtlMode = ctlModesFor11g;
1997 if (IS_CHAN_HT40(chan))
1999 numCtlModes = ARRAY_SIZE(ctlModesFor11g);
2001 /* Setup for CTL modes */
2002 /* CTL_11A, CTL_5GHT20 */
2003 numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
2004 SUB_NUM_CTL_MODES_AT_5G_40;
2005 pCtlMode = ctlModesFor11a;
2006 if (IS_CHAN_HT40(chan))
2008 numCtlModes = ARRAY_SIZE(ctlModesFor11a);
2012 * For MIMO, need to apply regulatory caps individually across
2013 * dynamically running modes: CCK, OFDM, HT20, HT40
2015 * The outer loop walks through each possible applicable runtime mode.
2016 * The inner loop walks through each ctlIndex entry in EEPROM.
2017 * The ctl value is encoded as [7:4] == test group, [3:0] == test mode.
2019 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
2020 bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
2021 (pCtlMode[ctlMode] == CTL_2GHT40);
2023 freq = centers.synth_center;
2024 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
2025 freq = centers.ext_center;
2027 freq = centers.ctl_center;
2029 ath_print(common, ATH_DBG_REGULATORY,
2030 "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
2031 "EXT_ADDITIVE %d\n",
2032 ctlMode, numCtlModes, isHt40CtlMode,
2033 (pCtlMode[ctlMode] & EXT_ADDITIVE));
2035 /* walk through each CTL index stored in EEPROM */
2037 ctlIndex = pEepData->ctlIndex_2G;
2038 ctlNum = AR9300_NUM_CTLS_2G;
2040 ctlIndex = pEepData->ctlIndex_5G;
2041 ctlNum = AR9300_NUM_CTLS_5G;
2044 for (i = 0; (i < ctlNum) && ctlIndex[i]; i++) {
2045 ath_print(common, ATH_DBG_REGULATORY,
2046 "LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
2047 "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
2049 i, cfgCtl, pCtlMode[ctlMode], ctlIndex[i],
2053 * compare test group from regulatory
2054 * channel list with test mode from pCtlMode
2057 if ((((cfgCtl & ~CTL_MODE_M) |
2058 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
2060 (((cfgCtl & ~CTL_MODE_M) |
2061 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
2062 ((ctlIndex[i] & CTL_MODE_M) |
2065 ar9003_hw_get_max_edge_power(pEepData,
2069 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL)
2071 * Find the minimum of all CTL
2072 * edge powers that apply to
2076 min(twiceMaxEdgePower,
2087 minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
2089 ath_print(common, ATH_DBG_REGULATORY,
2090 "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d "
2091 "sP %d minCtlPwr %d\n",
2092 ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
2093 scaledPower, minCtlPower);
2095 /* Apply ctl mode to correct target power set */
2096 switch (pCtlMode[ctlMode]) {
2098 for (i = ALL_TARGET_LEGACY_1L_5L;
2099 i <= ALL_TARGET_LEGACY_11S; i++)
2101 (u8)min((u16)pPwrArray[i],
2106 for (i = ALL_TARGET_LEGACY_6_24;
2107 i <= ALL_TARGET_LEGACY_54; i++)
2109 (u8)min((u16)pPwrArray[i],
2114 for (i = ALL_TARGET_HT20_0_8_16;
2115 i <= ALL_TARGET_HT20_21; i++)
2117 (u8)min((u16)pPwrArray[i],
2119 pPwrArray[ALL_TARGET_HT20_22] =
2120 (u8)min((u16)pPwrArray[ALL_TARGET_HT20_22],
2122 pPwrArray[ALL_TARGET_HT20_23] =
2123 (u8)min((u16)pPwrArray[ALL_TARGET_HT20_23],
2128 for (i = ALL_TARGET_HT40_0_8_16;
2129 i <= ALL_TARGET_HT40_23; i++)
2131 (u8)min((u16)pPwrArray[i],
2137 } /* end ctl mode checking */
2140 static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
2141 struct ath9k_channel *chan, u16 cfgCtl,
2142 u8 twiceAntennaReduction,
2143 u8 twiceMaxRegulatoryPower,
2144 u8 powerLimit, bool test)
2146 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
2147 struct ath_common *common = ath9k_hw_common(ah);
2148 u8 targetPowerValT2[ar9300RateSize];
2151 ar9003_hw_set_target_power_eeprom(ah, chan->channel, targetPowerValT2);
2152 ar9003_hw_set_power_per_rate_table(ah, chan,
2153 targetPowerValT2, cfgCtl,
2154 twiceAntennaReduction,
2155 twiceMaxRegulatoryPower,
2158 regulatory->max_power_level = 0;
2159 for (i = 0; i < ar9300RateSize; i++) {
2160 if (targetPowerValT2[i] > regulatory->max_power_level)
2161 regulatory->max_power_level = targetPowerValT2[i];
2167 for (i = 0; i < ar9300RateSize; i++) {
2168 ath_print(common, ATH_DBG_EEPROM,
2169 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
2171 ath_print(common, ATH_DBG_EEPROM,
2172 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
2174 ath_print(common, ATH_DBG_EEPROM,
2175 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
2177 ath_print(common, ATH_DBG_EEPROM,
2178 "TPC[%02d] 0x%08x\n\n", i, targetPowerValT2[i]);
2183 * This is the TX power we send back to driver core,
2184 * and it can use to pass to userspace to display our
2185 * currently configured TX power setting.
2187 * Since power is rate dependent, use one of the indices
2188 * from the AR9300_Rates enum to select an entry from
2189 * targetPowerValT2[] to report. Currently returns the
2190 * power for HT40 MCS 0, HT20 MCS 0, or OFDM 6 Mbps
2191 * as CCK power is less interesting (?).
2193 i = ALL_TARGET_LEGACY_6_24; /* legacy */
2194 if (IS_CHAN_HT40(chan))
2195 i = ALL_TARGET_HT40_0_8_16; /* ht40 */
2196 else if (IS_CHAN_HT20(chan))
2197 i = ALL_TARGET_HT20_0_8_16; /* ht20 */
2199 ah->txpower_limit = targetPowerValT2[i];
2200 regulatory->max_power_level = targetPowerValT2[i];
2202 /* Write target power array to registers */
2203 ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
2204 ar9003_hw_calibration_apply(ah, chan->channel);
2207 static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah,
2213 s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah)
2215 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
2217 return (eep->baseEepHeader.txrxgain >> 4) & 0xf; /* bits 7:4 */
2220 s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah)
2222 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
2224 return (eep->baseEepHeader.txrxgain) & 0xf; /* bits 3:0 */
2227 const struct eeprom_ops eep_ar9300_ops = {
2228 .check_eeprom = ath9k_hw_ar9300_check_eeprom,
2229 .get_eeprom = ath9k_hw_ar9300_get_eeprom,
2230 .fill_eeprom = ath9k_hw_ar9300_fill_eeprom,
2231 .get_eeprom_ver = ath9k_hw_ar9300_get_eeprom_ver,
2232 .get_eeprom_rev = ath9k_hw_ar9300_get_eeprom_rev,
2233 .get_num_ant_config = ath9k_hw_ar9300_get_num_ant_config,
2234 .get_eeprom_antenna_cfg = ath9k_hw_ar9300_get_eeprom_antenna_cfg,
2235 .set_board_values = ath9k_hw_ar9300_set_board_values,
2236 .set_addac = ath9k_hw_ar9300_set_addac,
2237 .set_txpower = ath9k_hw_ar9300_set_txpower,
2238 .get_spur_channel = ath9k_hw_ar9300_get_spur_channel