Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / net / wireless / ath / ath9k / ar9003_eeprom.c
blobc4182359bee46603cffc46e9781750087f2a5f0f
1 /*
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.
17 #include "hw.h"
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 = {
59 .eepromVersion = 2,
60 .templateVersion = 2,
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},
64 .baseEepHeader = {
65 .regDmn = { LE16(0), LE16(0x1f) },
66 .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
67 .opCapFlags = {
68 .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
69 .eepMisc = 0,
71 .rfSilent = 0,
72 .blueToothOptions = 0,
73 .deviceCap = 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,
88 .wlanDisableGpio = 0,
89 .wlanLedGpio = 8,
90 .rxBandSelectGpio = 0xff,
91 .txrxgain = 0,
92 .swreg = 0,
94 .modalHeader2G = {
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},
118 .tempSlope = 36,
119 .voltSlope = 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},
136 .xpaBiasLvl = 0,
137 .txFrameToDataStart = 0x0e,
138 .txFrameToPaOn = 0x0e,
139 .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
140 .antennaGain = 0,
141 .switchSettling = 0x2c,
142 .adcDesiredSize = -30,
143 .txEndToXpaOff = 0,
144 .txEndToRxOn = 0x2,
145 .txFrameToXpaOn = 0xe,
146 .thresh62 = 28,
147 .papdRateMaskHt20 = LE32(0x80c080),
148 .papdRateMaskHt40 = LE32(0x80c080),
149 .futureModal = {
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
154 .calFreqPier2G = {
155 FREQ2FBIN(2412, 1),
156 FREQ2FBIN(2437, 1),
157 FREQ2FBIN(2472, 1),
159 /* ar9300_cal_data_per_freq_op_loop 2g */
160 .calPierData2G = {
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 = {
166 FREQ2FBIN(2412, 1),
167 FREQ2FBIN(2484, 1),
169 .calTarget_freqbin_2G = {
170 FREQ2FBIN(2412, 1),
171 FREQ2FBIN(2437, 1),
172 FREQ2FBIN(2472, 1)
174 .calTarget_freqbin_2GHT20 = {
175 FREQ2FBIN(2412, 1),
176 FREQ2FBIN(2437, 1),
177 FREQ2FBIN(2472, 1)
179 .calTarget_freqbin_2GHT40 = {
180 FREQ2FBIN(2412, 1),
181 FREQ2FBIN(2437, 1),
182 FREQ2FBIN(2472, 1)
184 .calTargetPowerCck = {
185 /* 1L-5L,5S,11L,11S */
186 { {36, 36, 36, 36} },
187 { {36, 36, 36, 36} },
189 .calTargetPower2G = {
190 /* 6-24,36,48,54 */
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} },
205 .ctlIndex_2G = {
206 0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
207 0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
209 .ctl_freqbin_2G = {
211 FREQ2FBIN(2412, 1),
212 FREQ2FBIN(2417, 1),
213 FREQ2FBIN(2457, 1),
214 FREQ2FBIN(2462, 1)
217 FREQ2FBIN(2412, 1),
218 FREQ2FBIN(2417, 1),
219 FREQ2FBIN(2462, 1),
220 0xFF,
224 FREQ2FBIN(2412, 1),
225 FREQ2FBIN(2417, 1),
226 FREQ2FBIN(2462, 1),
227 0xFF,
230 FREQ2FBIN(2422, 1),
231 FREQ2FBIN(2427, 1),
232 FREQ2FBIN(2447, 1),
233 FREQ2FBIN(2452, 1)
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),
253 FREQ2FBIN(2472, 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 */
289 FREQ2FBIN(2462, 1),
292 .ctlPowerData_2G = {
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} } },
308 .modalHeader5G = {
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) */
314 .antCtrlChain = {
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},
325 .tempSlope = 68,
326 .voltSlope = 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 */
335 .xpaBiasLvl = 0,
336 .txFrameToDataStart = 0x0e,
337 .txFrameToPaOn = 0x0e,
338 .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
339 .antennaGain = 0,
340 .switchSettling = 0x2d,
341 .adcDesiredSize = -30,
342 .txEndToXpaOff = 0,
343 .txEndToRxOn = 0x2,
344 .txFrameToXpaOn = 0xe,
345 .thresh62 = 28,
346 .papdRateMaskHt20 = LE32(0xf0e0e0),
347 .papdRateMaskHt40 = LE32(0xf0e0e0),
348 .futureModal = {
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
353 .calFreqPier5G = {
354 FREQ2FBIN(5180, 0),
355 FREQ2FBIN(5220, 0),
356 FREQ2FBIN(5320, 0),
357 FREQ2FBIN(5400, 0),
358 FREQ2FBIN(5500, 0),
359 FREQ2FBIN(5600, 0),
360 FREQ2FBIN(5725, 0),
361 FREQ2FBIN(5825, 0)
363 .calPierData5G = {
365 {0, 0, 0, 0, 0},
366 {0, 0, 0, 0, 0},
367 {0, 0, 0, 0, 0},
368 {0, 0, 0, 0, 0},
369 {0, 0, 0, 0, 0},
370 {0, 0, 0, 0, 0},
371 {0, 0, 0, 0, 0},
372 {0, 0, 0, 0, 0},
375 {0, 0, 0, 0, 0},
376 {0, 0, 0, 0, 0},
377 {0, 0, 0, 0, 0},
378 {0, 0, 0, 0, 0},
379 {0, 0, 0, 0, 0},
380 {0, 0, 0, 0, 0},
381 {0, 0, 0, 0, 0},
382 {0, 0, 0, 0, 0},
385 {0, 0, 0, 0, 0},
386 {0, 0, 0, 0, 0},
387 {0, 0, 0, 0, 0},
388 {0, 0, 0, 0, 0},
389 {0, 0, 0, 0, 0},
390 {0, 0, 0, 0, 0},
391 {0, 0, 0, 0, 0},
392 {0, 0, 0, 0, 0},
396 .calTarget_freqbin_5G = {
397 FREQ2FBIN(5180, 0),
398 FREQ2FBIN(5220, 0),
399 FREQ2FBIN(5320, 0),
400 FREQ2FBIN(5400, 0),
401 FREQ2FBIN(5500, 0),
402 FREQ2FBIN(5600, 0),
403 FREQ2FBIN(5725, 0),
404 FREQ2FBIN(5825, 0)
406 .calTarget_freqbin_5GHT20 = {
407 FREQ2FBIN(5180, 0),
408 FREQ2FBIN(5240, 0),
409 FREQ2FBIN(5320, 0),
410 FREQ2FBIN(5500, 0),
411 FREQ2FBIN(5700, 0),
412 FREQ2FBIN(5745, 0),
413 FREQ2FBIN(5725, 0),
414 FREQ2FBIN(5825, 0)
416 .calTarget_freqbin_5GHT40 = {
417 FREQ2FBIN(5180, 0),
418 FREQ2FBIN(5240, 0),
419 FREQ2FBIN(5320, 0),
420 FREQ2FBIN(5500, 0),
421 FREQ2FBIN(5700, 0),
422 FREQ2FBIN(5745, 0),
423 FREQ2FBIN(5725, 0),
424 FREQ2FBIN(5825, 0)
426 .calTargetPower5G = {
427 /* 6-24,36,48,54 */
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} },
465 .ctlIndex_5G = {
466 0x10, 0x16, 0x18, 0x40, 0x46,
467 0x48, 0x30, 0x36, 0x38
469 .ctl_freqbin_5G = {
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)
568 .ctlPowerData_5G = {
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)
629 return fbin;
631 return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
634 static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah)
636 return 0;
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;
645 switch (param) {
646 case EEP_MAC_LSW:
647 return eep->macAddr[0] << 8 | eep->macAddr[1];
648 case EEP_MAC_MID:
649 return eep->macAddr[2] << 8 | eep->macAddr[3];
650 case EEP_MAC_MSW:
651 return eep->macAddr[4] << 8 | eep->macAddr[5];
652 case EEP_REG_0:
653 return le16_to_cpu(pBase->regDmn[0]);
654 case EEP_REG_1:
655 return le16_to_cpu(pBase->regDmn[1]);
656 case EEP_OP_CAP:
657 return pBase->deviceCap;
658 case EEP_OP_MODE:
659 return pBase->opCapFlags.opFlags;
660 case EEP_RF_SILENT:
661 return pBase->rfSilent;
662 case EEP_TX_MASK:
663 return (pBase->txrxMask >> 4) & 0xf;
664 case EEP_RX_MASK:
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;
672 case EEP_SWREG:
673 return le32_to_cpu(pBase->swreg);
674 case EEP_PAPRD:
675 return !!(pBase->featureEnable & BIT(5));
676 default:
677 return 0;
681 static bool ar9300_eeprom_read_byte(struct ath_common *common, int address,
682 u8 *buffer)
684 u16 val;
686 if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
687 return false;
689 *buffer = (val >> (8 * (address % 2))) & 0xff;
690 return true;
693 static bool ar9300_eeprom_read_word(struct ath_common *common, int address,
694 u8 *buffer)
696 u16 val;
698 if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
699 return false;
701 buffer[0] = val >> 8;
702 buffer[1] = val & 0xff;
704 return true;
707 static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer,
708 int count)
710 struct ath_common *common = ath9k_hw_common(ah);
711 int i;
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");
716 return false;
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++))
726 goto error;
728 count--;
731 for (i = 0; i < count / 2; i++) {
732 if (!ar9300_eeprom_read_word(common, address, buffer))
733 goto error;
735 address -= 2;
736 buffer += 2;
739 if (count % 2)
740 if (!ar9300_eeprom_read_byte(common, address, buffer))
741 goto error;
743 return true;
745 error:
746 ath_print(common, ATH_DBG_EEPROM,
747 "unable to read eeprom region at offset %d\n", address);
748 return false;
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];
756 value[0] = best[0];
757 value[1] = best[1];
758 value[2] = best[2];
759 value[3] = best[3];
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];
773 checksum &= 0xffff;
776 return checksum;
779 static bool ar9300_uncompress_block(struct ath_hw *ah,
780 u8 *mptr,
781 int mdataSize,
782 u8 *block,
783 int size)
785 int it;
786 int spot;
787 int offset;
788 int length;
789 struct ath_common *common = ath9k_hw_common(ah);
791 spot = 0;
793 for (it = 0; it < size; it += (length+2)) {
794 offset = block[it];
795 offset &= 0xff;
796 spot += offset;
797 length = block[it+1];
798 length &= 0xff;
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);
806 spot += 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);
812 return false;
815 return true;
818 static int ar9300_compress_decision(struct ath_hw *ah,
819 int it,
820 int code,
821 int reference,
822 u8 *mptr,
823 u8 *word, int length, int mdata_size)
825 struct ath_common *common = ath9k_hw_common(ah);
826 u8 *dptr;
828 switch (code) {
829 case _CompressNone:
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);
834 return -1;
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);
839 break;
840 case _CompressBlock:
841 if (reference == 0) {
842 dptr = mptr;
843 } else {
844 if (reference != 2) {
845 ath_print(common, ATH_DBG_EEPROM,
846 "cant find reference eeprom"
847 "struct %d\n", reference);
848 return -1;
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);
857 break;
858 default:
859 ath_print(common, ATH_DBG_EEPROM, "unknown compression"
860 " code %d\n", code);
861 return -1;
863 return 0;
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)
876 #define MDEFAULT 15
877 #define MSTATE 100
878 int cptr;
879 u8 *word;
880 int code;
881 int reference, length, major, minor;
882 int osize;
883 int it;
884 u16 checksum, mchecksum;
885 struct ath_common *common = ath9k_hw_common(ah);
887 word = kzalloc(2048, GFP_KERNEL);
888 if (!word)
889 return -1;
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))
896 goto fail;
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))
901 break;
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;
913 continue;
916 osize = length;
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);
927 } else {
928 ath_print(common, ATH_DBG_EEPROM,
929 "skipping block with bad checksum\n");
931 cptr -= (COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
934 kfree(word);
935 return cptr;
937 fail:
938 kfree(word);
939 return -1;
943 * Restore the configuration structure by reading the eeprom.
944 * This function destroys any existing in-memory structure
945 * content.
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)
953 return false;
955 return true;
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)
967 return 0;
970 static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah,
971 enum ath9k_hal_freq_band freq_band)
973 return 1;
976 static u32 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah,
977 struct ath9k_channel *chan)
979 return -EINVAL;
982 static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz)
984 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
986 if (is2ghz)
987 return eep->modalHeader2G.xpaBiasLvl;
988 else
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;
1003 __le32 val;
1005 if (is2ghz)
1006 val = eep->modalHeader2G.antCtrlCommon;
1007 else
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;
1015 __le32 val;
1017 if (is2ghz)
1018 val = eep->modalHeader2G.antCtrlCommon2;
1019 else
1020 val = eep->modalHeader5G.antCtrlCommon2;
1021 return le32_to_cpu(val);
1024 static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah,
1025 int chain,
1026 bool is2ghz)
1028 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1029 __le16 val = 0;
1031 if (chain >= 0 && chain < AR9300_MAX_CHAINS) {
1032 if (is2ghz)
1033 val = eep->modalHeader2G.antCtrlChain[chain];
1034 else
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)
1061 int drive_strength;
1062 unsigned long reg;
1064 drive_strength = ath9k_hw_ar9300_get_eeprom(ah, EEP_DRIVE_STRENGTH);
1066 if (!drive_strength)
1067 return;
1069 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS1);
1070 reg &= ~0x00ffffc0;
1071 reg |= 0x5 << 21;
1072 reg |= 0x5 << 18;
1073 reg |= 0x5 << 15;
1074 reg |= 0x5 << 12;
1075 reg |= 0x5 << 9;
1076 reg |= 0x5 << 6;
1077 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS1, reg);
1079 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS2);
1080 reg &= ~0xffffffe0;
1081 reg |= 0x5 << 29;
1082 reg |= 0x5 << 26;
1083 reg |= 0x5 << 23;
1084 reg |= 0x5 << 20;
1085 reg |= 0x5 << 17;
1086 reg |= 0x5 << 14;
1087 reg |= 0x5 << 11;
1088 reg |= 0x5 << 8;
1089 reg |= 0x5 << 5;
1090 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS2, reg);
1092 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS4);
1093 reg &= ~0xff800000;
1094 reg |= 0x5 << 29;
1095 reg |= 0x5 << 26;
1096 reg |= 0x5 << 23;
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,
1114 REG_READ(ah,
1115 AR_RTC_REG_CONTROL1) |
1116 AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
1117 } else {
1118 REG_WRITE(ah, AR_RTC_SLEEP_CLK,
1119 (REG_READ(ah,
1120 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)
1151 int ip = 0;
1152 int lx = 0, ly = 0, lhave = 0;
1153 int hx = 0, hy = 0, hhave = 0;
1154 int dx = 0;
1155 int y = 0;
1157 lhave = 0;
1158 hhave = 0;
1160 /* identify best lower and higher x calibration measurement */
1161 for (ip = 0; ip < np; ip++) {
1162 dx = x - px[ip];
1164 /* this measurement is higher than our desired x */
1165 if (dx <= 0) {
1166 if (!hhave || dx > (x - hx)) {
1167 /* new best higher x measurement */
1168 hx = px[ip];
1169 hy = py[ip];
1170 hhave = 1;
1173 /* this measurement is lower than our desired x */
1174 if (dx >= 0) {
1175 if (!lhave || dx < (x - lx)) {
1176 /* new best lower x measurement */
1177 lx = px[ip];
1178 ly = py[ip];
1179 lhave = 1;
1184 /* the low x is good */
1185 if (lhave) {
1186 /* so is the high x */
1187 if (hhave) {
1188 /* they're the same, so just pick one */
1189 if (hx == lx)
1190 y = ly;
1191 else /* interpolate */
1192 y = ly + (((x - lx) * (hy - ly)) / (hx - lx));
1193 } else /* only low is good, use it */
1194 y = ly;
1195 } else if (hhave) /* only high is good, use it */
1196 y = hy;
1197 else /* nothing is good,this should never happen unless np=0, ???? */
1198 y = -(1 << 30);
1199 return y;
1202 static u8 ar9003_hw_eeprom_get_tgt_pwr(struct ath_hw *ah,
1203 u16 rateIndex, u16 freq, bool is2GHz)
1205 u16 numPiers, i;
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;
1210 u8 *pFreqBin;
1212 if (is2GHz) {
1213 numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
1214 pEepromTargetPwr = eep->calTargetPower2G;
1215 pFreqBin = eep->calTarget_freqbin_2G;
1216 } else {
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,
1233 freqArray,
1234 targetPowerArray, numPiers);
1237 static u8 ar9003_hw_eeprom_get_ht20_tgt_pwr(struct ath_hw *ah,
1238 u16 rateIndex,
1239 u16 freq, bool is2GHz)
1241 u16 numPiers, i;
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;
1246 u8 *pFreqBin;
1248 if (is2GHz) {
1249 numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
1250 pEepromTargetPwr = eep->calTargetPower2GHT20;
1251 pFreqBin = eep->calTarget_freqbin_2GHT20;
1252 } else {
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,
1269 freqArray,
1270 targetPowerArray, numPiers);
1273 static u8 ar9003_hw_eeprom_get_ht40_tgt_pwr(struct ath_hw *ah,
1274 u16 rateIndex,
1275 u16 freq, bool is2GHz)
1277 u16 numPiers, i;
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;
1282 u8 *pFreqBin;
1284 if (is2GHz) {
1285 numPiers = AR9300_NUM_2G_40_TARGET_POWERS;
1286 pEepromTargetPwr = eep->calTargetPower2GHT40;
1287 pFreqBin = eep->calTarget_freqbin_2GHT40;
1288 } else {
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,
1305 freqArray,
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,
1330 freqArray,
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)
1438 return 0;
1439 #undef POW_SM
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;
1448 unsigned int i = 0;
1449 struct ath_common *common = ath9k_hw_common(ah);
1451 if (freq < 4000)
1452 is2GHz = true;
1454 targetPowerValT2[ALL_TARGET_LEGACY_6_24] =
1455 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_6_24, freq,
1456 is2GHz);
1457 targetPowerValT2[ALL_TARGET_LEGACY_36] =
1458 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_36, freq,
1459 is2GHz);
1460 targetPowerValT2[ALL_TARGET_LEGACY_48] =
1461 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_48, freq,
1462 is2GHz);
1463 targetPowerValT2[ALL_TARGET_LEGACY_54] =
1464 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_54, freq,
1465 is2GHz);
1466 targetPowerValT2[ALL_TARGET_LEGACY_1L_5L] =
1467 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_1L_5L,
1468 freq);
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,
1477 is2GHz);
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,
1480 freq, is2GHz);
1481 targetPowerValT2[ALL_TARGET_HT20_4] =
1482 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_4, freq,
1483 is2GHz);
1484 targetPowerValT2[ALL_TARGET_HT20_5] =
1485 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_5, freq,
1486 is2GHz);
1487 targetPowerValT2[ALL_TARGET_HT20_6] =
1488 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_6, freq,
1489 is2GHz);
1490 targetPowerValT2[ALL_TARGET_HT20_7] =
1491 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_7, freq,
1492 is2GHz);
1493 targetPowerValT2[ALL_TARGET_HT20_12] =
1494 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_12, freq,
1495 is2GHz);
1496 targetPowerValT2[ALL_TARGET_HT20_13] =
1497 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_13, freq,
1498 is2GHz);
1499 targetPowerValT2[ALL_TARGET_HT20_14] =
1500 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_14, freq,
1501 is2GHz);
1502 targetPowerValT2[ALL_TARGET_HT20_15] =
1503 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_15, freq,
1504 is2GHz);
1505 targetPowerValT2[ALL_TARGET_HT20_20] =
1506 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_20, freq,
1507 is2GHz);
1508 targetPowerValT2[ALL_TARGET_HT20_21] =
1509 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_21, freq,
1510 is2GHz);
1511 targetPowerValT2[ALL_TARGET_HT20_22] =
1512 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_22, freq,
1513 is2GHz);
1514 targetPowerValT2[ALL_TARGET_HT20_23] =
1515 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
1516 is2GHz);
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,
1522 freq,
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]);
1564 i++;
1566 ath_print(common, ATH_DBG_EEPROM,
1567 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1568 i++;
1570 ath_print(common, ATH_DBG_EEPROM,
1571 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1572 i++;
1574 ath_print(common, ATH_DBG_EEPROM,
1575 "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
1576 i++;
1580 static int ar9003_hw_cal_pier_get(struct ath_hw *ah,
1581 int mode,
1582 int ipier,
1583 int ichain,
1584 int *pfrequency,
1585 int *pcorrection,
1586 int *ptemperature, int *pvoltage)
1588 u8 *pCalPier;
1589 struct ar9300_cal_data_per_freq_op_loop *pCalPierStruct;
1590 int is2GHz;
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",
1597 AR9300_MAX_CHAINS);
1598 return -1;
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);
1607 return -1;
1609 pCalPier = &(eep->calFreqPier5G[ipier]);
1610 pCalPierStruct = &(eep->calPierData5G[ichain][ipier]);
1611 is2GHz = 0;
1612 } else {
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);
1617 return -1;
1620 pCalPier = &(eep->calFreqPier2G[ipier]);
1621 pCalPierStruct = &(eep->calPierData2G[ichain][ipier]);
1622 is2GHz = 1;
1625 *pfrequency = FBIN2FREQ(*pCalPier, is2GHz);
1626 *pcorrection = pCalPierStruct->refPower;
1627 *ptemperature = pCalPierStruct->tempMeas;
1628 *pvoltage = pCalPierStruct->voltMeas;
1630 return 0;
1633 static int ar9003_hw_power_control_override(struct ath_hw *ah,
1634 int frequency,
1635 int *correction,
1636 int *voltage, int *temperature)
1638 int tempSlope = 0;
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;
1668 else
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,
1673 temperature[0]);
1675 return 0;
1678 /* Apply the recorded correction values. */
1679 static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
1681 int ichain, ipier, npier;
1682 int mode;
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];
1689 int fdiff;
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);
1696 if (mode)
1697 npier = AR9300_NUM_5G_CAL_PIERS;
1698 else
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
1717 if (fdiff <= 0) {
1718 if (hfrequency[ichain] <= 0 ||
1719 hfrequency[ichain] >= 100000 ||
1720 fdiff >
1721 (frequency - hfrequency[ichain])) {
1723 * new best higher
1724 * frequency measurement
1726 hfrequency[ichain] = pfrequency;
1727 hcorrection[ichain] =
1728 pcorrection;
1729 htemperature[ichain] =
1730 ptemperature;
1731 hvoltage[ichain] = pvoltage;
1734 if (fdiff >= 0) {
1735 if (lfrequency[ichain] <= 0
1736 || fdiff <
1737 (frequency - lfrequency[ichain])) {
1739 * new best lower
1740 * frequency measurement
1742 lfrequency[ichain] = pfrequency;
1743 lcorrection[ichain] =
1744 pcorrection;
1745 ltemperature[ichain] =
1746 ptemperature;
1747 lvoltage[ichain] = pvoltage;
1754 /* interpolate */
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]));
1784 voltage[ichain] =
1785 lvoltage[ichain] +
1786 (((frequency -
1787 lfrequency[ichain]) * (hvoltage[ichain] -
1788 lvoltage[ichain]))
1789 / (hfrequency[ichain] -
1790 lfrequency[ichain]));
1792 /* only low is good, use it */
1793 else {
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,
1812 temperature);
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]);
1818 return 0;
1821 static u16 ar9003_hw_get_direct_edge_power(struct ar9300_eeprom *eep,
1822 int idx,
1823 int edge,
1824 bool is2GHz)
1826 struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G;
1827 struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G;
1829 if (is2GHz)
1830 return ctl_2g[idx].ctlEdges[edge].tPower;
1831 else
1832 return ctl_5g[idx].ctlEdges[edge].tPower;
1835 static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep,
1836 int idx,
1837 unsigned int edge,
1838 u16 freq,
1839 bool is2GHz)
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];
1848 if (is2GHz) {
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;
1852 } else {
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;
1873 unsigned int edge;
1875 /* Get the edge power */
1876 for (edge = 0;
1877 (edge < num_edges) && (ctl_freqbin[edge] != AR9300_BCHAN_UNUSED);
1878 edge++) {
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)) {
1884 twiceMaxEdgePower =
1885 ar9003_hw_get_direct_edge_power(eep, idx,
1886 edge, is2GHz);
1887 break;
1888 } else if ((edge > 0) &&
1889 (freq < ath9k_hw_fbin2freq(ctl_freqbin[edge],
1890 is2GHz))) {
1891 twiceMaxEdgePower =
1892 ar9003_hw_get_indirect_edge_power(eep, idx,
1893 edge, freq,
1894 is2GHz);
1896 * Leave loop - no more affecting edges possible in
1897 * this monotonic increasing list
1899 break;
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,
1910 u16 powerLimit)
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
1919 int i;
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;
1931 u8 *ctlIndex;
1932 u8 ctlNum;
1933 u16 twiceMinEdgePower;
1934 bool is2ghz = IS_CHAN_2GHZ(chan);
1936 ath9k_hw_get_channel_centers(ah, chan, &centers);
1938 /* Compute TxPower reduction due to Antenna Gain */
1939 if (is2ghz)
1940 twiceLargestAntenna = pEepData->modalHeader2G.antennaGain;
1941 else
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)) {
1965 case 1:
1966 break;
1967 case 2:
1968 scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
1969 break;
1970 case 3:
1971 scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
1972 break;
1975 scaledPower = max((u16)0, scaledPower);
1978 * Get target powers from EEPROM - our baseline for TX Power
1980 if (is2ghz) {
1981 /* Setup for CTL modes */
1982 /* CTL_11B, CTL_11G, CTL_2GHT20 */
1983 numCtlModes =
1984 ARRAY_SIZE(ctlModesFor11g) -
1985 SUB_NUM_CTL_MODES_AT_2G_40;
1986 pCtlMode = ctlModesFor11g;
1987 if (IS_CHAN_HT40(chan))
1988 /* All 2G CTL's */
1989 numCtlModes = ARRAY_SIZE(ctlModesFor11g);
1990 } else {
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))
1997 /* All 5G CTL's */
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);
2012 if (isHt40CtlMode)
2013 freq = centers.synth_center;
2014 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
2015 freq = centers.ext_center;
2016 else
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 */
2026 if (is2ghz) {
2027 ctlIndex = pEepData->ctlIndex_2G;
2028 ctlNum = AR9300_NUM_CTLS_2G;
2029 } else {
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 "
2038 "chan %dn",
2039 i, cfgCtl, pCtlMode[ctlMode], ctlIndex[i],
2040 chan->channel);
2043 * compare test group from regulatory
2044 * channel list with test mode from pCtlMode
2045 * list
2047 if ((((cfgCtl & ~CTL_MODE_M) |
2048 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
2049 ctlIndex[i]) ||
2050 (((cfgCtl & ~CTL_MODE_M) |
2051 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
2052 ((ctlIndex[i] & CTL_MODE_M) |
2053 SD_NO_CTL))) {
2054 twiceMinEdgePower =
2055 ar9003_hw_get_max_edge_power(pEepData,
2056 freq, i,
2057 is2ghz);
2059 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL)
2061 * Find the minimum of all CTL
2062 * edge powers that apply to
2063 * this channel
2065 twiceMaxEdgePower =
2066 min(twiceMaxEdgePower,
2067 twiceMinEdgePower);
2068 else {
2069 /* specific */
2070 twiceMaxEdgePower =
2071 twiceMinEdgePower;
2072 break;
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]) {
2087 case CTL_11B:
2088 for (i = ALL_TARGET_LEGACY_1L_5L;
2089 i <= ALL_TARGET_LEGACY_11S; i++)
2090 pPwrArray[i] =
2091 (u8)min((u16)pPwrArray[i],
2092 minCtlPower);
2093 break;
2094 case CTL_11A:
2095 case CTL_11G:
2096 for (i = ALL_TARGET_LEGACY_6_24;
2097 i <= ALL_TARGET_LEGACY_54; i++)
2098 pPwrArray[i] =
2099 (u8)min((u16)pPwrArray[i],
2100 minCtlPower);
2101 break;
2102 case CTL_5GHT20:
2103 case CTL_2GHT20:
2104 for (i = ALL_TARGET_HT20_0_8_16;
2105 i <= ALL_TARGET_HT20_21; i++)
2106 pPwrArray[i] =
2107 (u8)min((u16)pPwrArray[i],
2108 minCtlPower);
2109 pPwrArray[ALL_TARGET_HT20_22] =
2110 (u8)min((u16)pPwrArray[ALL_TARGET_HT20_22],
2111 minCtlPower);
2112 pPwrArray[ALL_TARGET_HT20_23] =
2113 (u8)min((u16)pPwrArray[ALL_TARGET_HT20_23],
2114 minCtlPower);
2115 break;
2116 case CTL_5GHT40:
2117 case CTL_2GHT40:
2118 for (i = ALL_TARGET_HT40_0_8_16;
2119 i <= ALL_TARGET_HT40_23; i++)
2120 pPwrArray[i] =
2121 (u8)min((u16)pPwrArray[i],
2122 minCtlPower);
2123 break;
2124 default:
2125 break;
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,
2134 u8 powerLimit)
2136 struct ath_common *common = ath9k_hw_common(ah);
2137 u8 targetPowerValT2[ar9300RateSize];
2138 unsigned int i = 0;
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,
2145 powerLimit);
2147 while (i < ar9300RateSize) {
2148 ath_print(common, ATH_DBG_EEPROM,
2149 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
2150 i++;
2151 ath_print(common, ATH_DBG_EEPROM,
2152 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
2153 i++;
2154 ath_print(common, ATH_DBG_EEPROM,
2155 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
2156 i++;
2157 ath_print(common, ATH_DBG_EEPROM,
2158 "TPC[%02d] 0x%08x\n\n", i, targetPowerValT2[i]);
2159 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,
2188 u16 i, bool is2GHz)
2190 return AR_NO_SPUR;
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