blob: 29a138631f758f44cef37086d852dc53c3cc4fc5 [file] [log] [blame]
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001/*
2 * Copyright (c) 2010 Atheros Communications Inc.
3 *
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.
7 *
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.
15 */
16
17#include "hw.h"
18#include "ar9003_phy.h"
19#include "ar9003_eeprom.h"
20
21#define COMP_HDR_LEN 4
22#define COMP_CKSUM_LEN 2
23
24#define AR_CH0_TOP (0x00016288)
25#define AR_CH0_TOP_XPABIASLVL (0x3)
26#define AR_CH0_TOP_XPABIASLVL_S (8)
27
28#define AR_CH0_THERM (0x00016290)
29#define AR_CH0_THERM_SPARE (0x3f)
30#define AR_CH0_THERM_SPARE_S (0)
31
32#define AR_SWITCH_TABLE_COM_ALL (0xffff)
33#define AR_SWITCH_TABLE_COM_ALL_S (0)
34
35#define AR_SWITCH_TABLE_COM2_ALL (0xffffff)
36#define AR_SWITCH_TABLE_COM2_ALL_S (0)
37
38#define AR_SWITCH_TABLE_ALL (0xfff)
39#define AR_SWITCH_TABLE_ALL_S (0)
40
Felix Fietkauffdc4cb2010-05-11 17:23:03 +020041#define LE16(x) __constant_cpu_to_le16(x)
42#define LE32(x) __constant_cpu_to_le32(x)
43
Luis R. Rodriguez824b1852010-08-01 02:25:16 -040044/* 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 */
54
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 */
57
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -040058static 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 = {
Felix Fietkauffdc4cb2010-05-11 17:23:03 +020065 .regDmn = { LE16(0), LE16(0x1f) },
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -040066 .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
67 .opCapFlags = {
68 .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
69 .eepMisc = 0,
70 },
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,
78 /*
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
Felix Fietkau49352502010-06-12 00:33:59 -040084 * bit5 - enable pa predistortion - disabled
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -040085 */
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,
93 },
94 .modalHeader2G = {
95 /* ar9300_modal_eep_header 2g */
96 /* 4 idle,t1,t2,b(4 bits per setting) */
Felix Fietkauffdc4cb2010-05-11 17:23:03 +020097 .antCtrlCommon = LE32(0x110),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -040098 /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
Felix Fietkauffdc4cb2010-05-11 17:23:03 +020099 .antCtrlCommon2 = LE32(0x22222),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400100
101 /*
102 * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
103 * rx1, rx12, b (2 bits each)
104 */
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200105 .antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) },
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400106
107 /*
108 * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db
109 * for ar9280 (0xa20c/b20c 5:0)
110 */
111 .xatten1DB = {0, 0, 0},
112
113 /*
114 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
115 * for ar9280 (0xa20c/b20c 16:12
116 */
117 .xatten1Margin = {0, 0, 0},
118 .tempSlope = 36,
119 .voltSlope = 0,
120
121 /*
122 * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
123 * channels in usual fbin coding format
124 */
125 .spurChans = {0, 0, 0, 0, 0},
126
127 /*
128 * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
129 * if the register is per chain
130 */
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,
Senthil Balasubramanian3ceb8012010-11-10 05:03:09 -0800147 .papdRateMaskHt20 = LE32(0x0cf0e0e0),
148 .papdRateMaskHt40 = LE32(0x6cf0e0e0),
Felix Fietkau49352502010-06-12 00:33:59 -0400149 .futureModal = {
Senthil Balasubramanianb3dd6bc2010-11-10 05:03:07 -0800150 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400151 },
152 },
Senthil Balasubramanianb3dd6bc2010-11-10 05:03:07 -0800153 .base_ext1 = {
154 .ant_div_control = 0,
155 .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
156 },
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400157 .calFreqPier2G = {
158 FREQ2FBIN(2412, 1),
159 FREQ2FBIN(2437, 1),
160 FREQ2FBIN(2472, 1),
161 },
162 /* ar9300_cal_data_per_freq_op_loop 2g */
163 .calPierData2G = {
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} },
167 },
168 .calTarget_freqbin_Cck = {
169 FREQ2FBIN(2412, 1),
170 FREQ2FBIN(2484, 1),
171 },
172 .calTarget_freqbin_2G = {
173 FREQ2FBIN(2412, 1),
174 FREQ2FBIN(2437, 1),
175 FREQ2FBIN(2472, 1)
176 },
177 .calTarget_freqbin_2GHT20 = {
178 FREQ2FBIN(2412, 1),
179 FREQ2FBIN(2437, 1),
180 FREQ2FBIN(2472, 1)
181 },
182 .calTarget_freqbin_2GHT40 = {
183 FREQ2FBIN(2412, 1),
184 FREQ2FBIN(2437, 1),
185 FREQ2FBIN(2472, 1)
186 },
187 .calTargetPowerCck = {
188 /* 1L-5L,5S,11L,11S */
189 { {36, 36, 36, 36} },
190 { {36, 36, 36, 36} },
191 },
192 .calTargetPower2G = {
193 /* 6-24,36,48,54 */
194 { {32, 32, 28, 24} },
195 { {32, 32, 28, 24} },
196 { {32, 32, 28, 24} },
197 },
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} },
202 },
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} },
207 },
208 .ctlIndex_2G = {
209 0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
210 0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
211 },
212 .ctl_freqbin_2G = {
213 {
214 FREQ2FBIN(2412, 1),
215 FREQ2FBIN(2417, 1),
216 FREQ2FBIN(2457, 1),
217 FREQ2FBIN(2462, 1)
218 },
219 {
220 FREQ2FBIN(2412, 1),
221 FREQ2FBIN(2417, 1),
222 FREQ2FBIN(2462, 1),
223 0xFF,
224 },
225
226 {
227 FREQ2FBIN(2412, 1),
228 FREQ2FBIN(2417, 1),
229 FREQ2FBIN(2462, 1),
230 0xFF,
231 },
232 {
233 FREQ2FBIN(2422, 1),
234 FREQ2FBIN(2427, 1),
235 FREQ2FBIN(2447, 1),
236 FREQ2FBIN(2452, 1)
237 },
238
239 {
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),
244 },
245
246 {
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),
250 0,
251 },
252
253 {
254 /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
255 /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
256 FREQ2FBIN(2472, 1),
257 0,
258 },
259
260 {
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),
265 },
266
267 {
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),
271 },
272
273 {
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),
277 0
278 },
279
280 {
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),
284 0
285 },
286
287 {
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),
Senthil Balasubramanianb3dd6bc2010-11-10 05:03:07 -0800291 /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400292 }
293 },
294 .ctlPowerData_2G = {
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} } },
298
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} } },
302
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} } },
306
307 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
308 { { {60, 0}, {60, 1}, {60, 1}, {60, 1} } },
Senthil Balasubramanianef5a6a72010-11-10 05:03:08 -0800309 { { {60, 0}, {60, 1}, {60, 1}, {60, 1} } },
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400310 },
311 .modalHeader5G = {
312 /* 4 idle,t1,t2,b (4 bits per setting) */
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200313 .antCtrlCommon = LE32(0x110),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400314 /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200315 .antCtrlCommon2 = LE32(0x22222),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400316 /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
317 .antCtrlChain = {
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200318 LE16(0x000), LE16(0x000), LE16(0x000),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400319 },
320 /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
321 .xatten1DB = {0, 0, 0},
322
323 /*
324 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
325 * for merlin (0xa20c/b20c 16:12
326 */
327 .xatten1Margin = {0, 0, 0},
328 .tempSlope = 68,
329 .voltSlope = 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 */
338 .xpaBiasLvl = 0,
339 .txFrameToDataStart = 0x0e,
340 .txFrameToPaOn = 0x0e,
341 .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
342 .antennaGain = 0,
343 .switchSettling = 0x2d,
344 .adcDesiredSize = -30,
345 .txEndToXpaOff = 0,
346 .txEndToRxOn = 0x2,
347 .txFrameToXpaOn = 0xe,
348 .thresh62 = 28,
Senthil Balasubramanian3ceb8012010-11-10 05:03:09 -0800349 .papdRateMaskHt20 = LE32(0x0c80c080),
350 .papdRateMaskHt40 = LE32(0x0080c080),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400351 .futureModal = {
Senthil Balasubramanianb3dd6bc2010-11-10 05:03:07 -0800352 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400353 },
354 },
Senthil Balasubramanianb3dd6bc2010-11-10 05:03:07 -0800355 .base_ext2 = {
356 .tempSlopeLow = 0,
357 .tempSlopeHigh = 0,
358 .xatten1DBLow = {0, 0, 0},
359 .xatten1MarginLow = {0, 0, 0},
360 .xatten1DBHigh = {0, 0, 0},
361 .xatten1MarginHigh = {0, 0, 0}
362 },
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400363 .calFreqPier5G = {
364 FREQ2FBIN(5180, 0),
365 FREQ2FBIN(5220, 0),
366 FREQ2FBIN(5320, 0),
367 FREQ2FBIN(5400, 0),
368 FREQ2FBIN(5500, 0),
369 FREQ2FBIN(5600, 0),
370 FREQ2FBIN(5725, 0),
371 FREQ2FBIN(5825, 0)
372 },
373 .calPierData5G = {
374 {
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},
383 },
384 {
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},
393 },
394 {
395 {0, 0, 0, 0, 0},
396 {0, 0, 0, 0, 0},
397 {0, 0, 0, 0, 0},
398 {0, 0, 0, 0, 0},
399 {0, 0, 0, 0, 0},
400 {0, 0, 0, 0, 0},
401 {0, 0, 0, 0, 0},
402 {0, 0, 0, 0, 0},
403 },
404
405 },
406 .calTarget_freqbin_5G = {
407 FREQ2FBIN(5180, 0),
408 FREQ2FBIN(5220, 0),
409 FREQ2FBIN(5320, 0),
410 FREQ2FBIN(5400, 0),
411 FREQ2FBIN(5500, 0),
412 FREQ2FBIN(5600, 0),
413 FREQ2FBIN(5725, 0),
414 FREQ2FBIN(5825, 0)
415 },
416 .calTarget_freqbin_5GHT20 = {
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)
425 },
426 .calTarget_freqbin_5GHT40 = {
427 FREQ2FBIN(5180, 0),
428 FREQ2FBIN(5240, 0),
429 FREQ2FBIN(5320, 0),
430 FREQ2FBIN(5500, 0),
431 FREQ2FBIN(5700, 0),
432 FREQ2FBIN(5745, 0),
433 FREQ2FBIN(5725, 0),
434 FREQ2FBIN(5825, 0)
435 },
436 .calTargetPower5G = {
437 /* 6-24,36,48,54 */
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} },
446 },
447 .calTargetPower5GHT20 = {
448 /*
449 * 0_8_16,1-3_9-11_17-19,
450 * 4,5,6,7,12,13,14,15,20,21,22,23
451 */
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} },
460 },
461 .calTargetPower5GHT40 = {
462 /*
463 * 0_8_16,1-3_9-11_17-19,
464 * 4,5,6,7,12,13,14,15,20,21,22,23
465 */
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} },
474 },
475 .ctlIndex_5G = {
476 0x10, 0x16, 0x18, 0x40, 0x46,
477 0x48, 0x30, 0x36, 0x38
478 },
479 .ctl_freqbin_5G = {
480 {
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)
489 },
490 {
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)
499 },
500
501 {
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)
510 },
511
512 {
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,
521 },
522
523 {
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,
532 },
533
534 {
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
543 },
544
545 {
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)
554 },
555
556 {
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)
565 },
566
567 {
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)
576 }
577 },
578 .ctlPowerData_5G = {
579 {
580 {
581 {60, 1}, {60, 1}, {60, 1}, {60, 1},
582 {60, 1}, {60, 1}, {60, 1}, {60, 0},
583 }
584 },
585 {
586 {
587 {60, 1}, {60, 1}, {60, 1}, {60, 1},
588 {60, 1}, {60, 1}, {60, 1}, {60, 0},
589 }
590 },
591 {
592 {
593 {60, 0}, {60, 1}, {60, 0}, {60, 1},
594 {60, 1}, {60, 1}, {60, 1}, {60, 1},
595 }
596 },
597 {
598 {
599 {60, 0}, {60, 1}, {60, 1}, {60, 0},
600 {60, 1}, {60, 0}, {60, 0}, {60, 0},
601 }
602 },
603 {
604 {
605 {60, 1}, {60, 1}, {60, 1}, {60, 0},
606 {60, 0}, {60, 0}, {60, 0}, {60, 0},
607 }
608 },
609 {
610 {
611 {60, 1}, {60, 1}, {60, 1}, {60, 1},
612 {60, 1}, {60, 0}, {60, 0}, {60, 0},
613 }
614 },
615 {
616 {
617 {60, 1}, {60, 1}, {60, 1}, {60, 1},
618 {60, 1}, {60, 1}, {60, 1}, {60, 1},
619 }
620 },
621 {
622 {
623 {60, 1}, {60, 1}, {60, 0}, {60, 1},
624 {60, 1}, {60, 1}, {60, 1}, {60, 0},
625 }
626 },
627 {
628 {
629 {60, 1}, {60, 0}, {60, 1}, {60, 1},
630 {60, 1}, {60, 1}, {60, 0}, {60, 1},
631 }
632 },
633 }
634};
635
Luis R. Rodriguez824b1852010-08-01 02:25:16 -0400636static u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
637{
638 if (fbin == AR9300_BCHAN_UNUSED)
639 return fbin;
640
641 return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
642}
643
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400644static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah)
645{
646 return 0;
647}
648
649static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
650 enum eeprom_param param)
651{
652 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
653 struct ar9300_base_eep_hdr *pBase = &eep->baseEepHeader;
654
655 switch (param) {
656 case EEP_MAC_LSW:
657 return eep->macAddr[0] << 8 | eep->macAddr[1];
658 case EEP_MAC_MID:
659 return eep->macAddr[2] << 8 | eep->macAddr[3];
660 case EEP_MAC_MSW:
661 return eep->macAddr[4] << 8 | eep->macAddr[5];
662 case EEP_REG_0:
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200663 return le16_to_cpu(pBase->regDmn[0]);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400664 case EEP_REG_1:
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200665 return le16_to_cpu(pBase->regDmn[1]);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400666 case EEP_OP_CAP:
667 return pBase->deviceCap;
668 case EEP_OP_MODE:
669 return pBase->opCapFlags.opFlags;
670 case EEP_RF_SILENT:
671 return pBase->rfSilent;
672 case EEP_TX_MASK:
673 return (pBase->txrxMask >> 4) & 0xf;
674 case EEP_RX_MASK:
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;
682 case EEP_SWREG:
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200683 return le32_to_cpu(pBase->swreg);
Felix Fietkau49352502010-06-12 00:33:59 -0400684 case EEP_PAPRD:
685 return !!(pBase->featureEnable & BIT(5));
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400686 default:
687 return 0;
688 }
689}
690
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200691static bool ar9300_eeprom_read_byte(struct ath_common *common, int address,
692 u8 *buffer)
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400693{
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200694 u16 val;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400695
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200696 if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
697 return false;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400698
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200699 *buffer = (val >> (8 * (address % 2))) & 0xff;
700 return true;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400701}
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400702
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200703static bool ar9300_eeprom_read_word(struct ath_common *common, int address,
704 u8 *buffer)
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400705{
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200706 u16 val;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400707
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200708 if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
709 return false;
710
711 buffer[0] = val >> 8;
712 buffer[1] = val & 0xff;
713
714 return true;
715}
716
717static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer,
718 int count)
719{
720 struct ath_common *common = ath9k_hw_common(ah);
721 int i;
722
723 if ((address < 0) || ((address + count) / 2 > AR9300_EEPROM_SIZE - 1)) {
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400724 ath_print(common, ATH_DBG_EEPROM,
725 "eeprom address not in range\n");
726 return false;
727 }
728
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200729 /*
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
733 */
734 if (address % 2 == 0) {
735 if (!ar9300_eeprom_read_byte(common, address--, buffer++))
736 goto error;
737
738 count--;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400739 }
740
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200741 for (i = 0; i < count / 2; i++) {
742 if (!ar9300_eeprom_read_word(common, address, buffer))
743 goto error;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400744
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200745 address -= 2;
746 buffer += 2;
747 }
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400748
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200749 if (count % 2)
750 if (!ar9300_eeprom_read_byte(common, address, buffer))
751 goto error;
752
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400753 return true;
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200754
755error:
756 ath_print(common, ATH_DBG_EEPROM,
757 "unable to read eeprom region at offset %d\n", address);
758 return false;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400759}
760
761static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference,
762 int *length, int *major, int *minor)
763{
764 unsigned long value[4];
765
766 value[0] = best[0];
767 value[1] = best[1];
768 value[2] = best[2];
769 value[3] = best[3];
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);
775}
776
777static u16 ar9300_comp_cksum(u8 *data, int dsize)
778{
779 int it, checksum = 0;
780
781 for (it = 0; it < dsize; it++) {
782 checksum += data[it];
783 checksum &= 0xffff;
784 }
785
786 return checksum;
787}
788
789static bool ar9300_uncompress_block(struct ath_hw *ah,
790 u8 *mptr,
791 int mdataSize,
792 u8 *block,
793 int size)
794{
795 int it;
796 int spot;
797 int offset;
798 int length;
799 struct ath_common *common = ath9k_hw_common(ah);
800
801 spot = 0;
802
803 for (it = 0; it < size; it += (length+2)) {
804 offset = block[it];
805 offset &= 0xff;
806 spot += offset;
807 length = block[it+1];
808 length &= 0xff;
809
Luis R. Rodriguez803288e2010-08-30 19:26:32 -0400810 if (length > 0 && spot >= 0 && spot+length <= mdataSize) {
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400811 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);
816 spot += 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);
822 return false;
823 }
824 }
825 return true;
826}
827
828static int ar9300_compress_decision(struct ath_hw *ah,
829 int it,
830 int code,
831 int reference,
832 u8 *mptr,
833 u8 *word, int length, int mdata_size)
834{
835 struct ath_common *common = ath9k_hw_common(ah);
836 u8 *dptr;
837
838 switch (code) {
839 case _CompressNone:
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);
844 return -1;
845 }
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);
849 break;
850 case _CompressBlock:
851 if (reference == 0) {
852 dptr = mptr;
853 } else {
854 if (reference != 2) {
855 ath_print(common, ATH_DBG_EEPROM,
856 "cant find reference eeprom"
857 "struct %d\n", reference);
858 return -1;
859 }
860 memcpy(mptr, &ar9300_default, mdata_size);
861 }
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);
867 break;
868 default:
869 ath_print(common, ATH_DBG_EEPROM, "unknown compression"
870 " code %d\n", code);
871 return -1;
872 }
873 return 0;
874}
875
876/*
877 * Read the configuration data from the eeprom.
878 * The data can be put in any specified memory buffer.
879 *
880 * Returns -1 on error.
881 * Returns address of next memory location on success.
882 */
883static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
884 u8 *mptr, int mdata_size)
885{
886#define MDEFAULT 15
887#define MSTATE 100
888 int cptr;
889 u8 *word;
890 int code;
891 int reference, length, major, minor;
892 int osize;
893 int it;
894 u16 checksum, mchecksum;
895 struct ath_common *common = ath9k_hw_common(ah);
896
897 word = kzalloc(2048, GFP_KERNEL);
898 if (!word)
899 return -1;
900
901 memcpy(mptr, &ar9300_default, mdata_size);
902
903 cptr = AR9300_BASE_ADDR;
904 for (it = 0; it < MSTATE; it++) {
905 if (!ar9300_read_eeprom(ah, cptr, word, COMP_HDR_LEN))
906 goto fail;
907
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))
911 break;
912
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;
923 continue;
924 }
925
926 osize = length;
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);
937 } else {
938 ath_print(common, ATH_DBG_EEPROM,
939 "skipping block with bad checksum\n");
940 }
941 cptr -= (COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
942 }
943
944 kfree(word);
945 return cptr;
946
947fail:
948 kfree(word);
949 return -1;
950}
951
952/*
953 * Restore the configuration structure by reading the eeprom.
954 * This function destroys any existing in-memory structure
955 * content.
956 */
957static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw *ah)
958{
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200959 u8 *mptr = (u8 *) &ah->eeprom.ar9300_eep;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400960
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200961 if (ar9300_eeprom_restore_internal(ah, mptr,
962 sizeof(struct ar9300_eeprom)) < 0)
963 return false;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400964
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200965 return true;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400966}
967
968/* XXX: review hardware docs */
969static int ath9k_hw_ar9300_get_eeprom_ver(struct ath_hw *ah)
970{
971 return ah->eeprom.ar9300_eep.eepromVersion;
972}
973
974/* XXX: could be read from the eepromVersion, not sure yet */
975static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw *ah)
976{
977 return 0;
978}
979
980static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah,
Rajkumar Manoharanf799a302010-09-16 11:40:06 +0530981 enum ath9k_hal_freq_band freq_band)
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400982{
983 return 1;
984}
985
Felix Fietkau601e0cb2010-07-11 12:48:39 +0200986static u32 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah,
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400987 struct ath9k_channel *chan)
988{
989 return -EINVAL;
990}
991
992static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz)
993{
994 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
995
996 if (is2ghz)
997 return eep->modalHeader2G.xpaBiasLvl;
998 else
999 return eep->modalHeader5G.xpaBiasLvl;
1000}
1001
1002static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
1003{
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));
1008}
1009
1010static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz)
1011{
1012 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001013 __le32 val;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001014
1015 if (is2ghz)
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001016 val = eep->modalHeader2G.antCtrlCommon;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001017 else
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001018 val = eep->modalHeader5G.antCtrlCommon;
1019 return le32_to_cpu(val);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001020}
1021
1022static u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz)
1023{
1024 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001025 __le32 val;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001026
1027 if (is2ghz)
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001028 val = eep->modalHeader2G.antCtrlCommon2;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001029 else
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001030 val = eep->modalHeader5G.antCtrlCommon2;
1031 return le32_to_cpu(val);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001032}
1033
1034static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah,
1035 int chain,
1036 bool is2ghz)
1037{
1038 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001039 __le16 val = 0;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001040
1041 if (chain >= 0 && chain < AR9300_MAX_CHAINS) {
1042 if (is2ghz)
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001043 val = eep->modalHeader2G.antCtrlChain[chain];
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001044 else
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001045 val = eep->modalHeader5G.antCtrlChain[chain];
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001046 }
1047
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001048 return le16_to_cpu(val);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001049}
1050
1051static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
1052{
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);
1055
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);
1058
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);
1061
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);
1064
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);
1067}
1068
1069static void ar9003_hw_drive_strength_apply(struct ath_hw *ah)
1070{
1071 int drive_strength;
1072 unsigned long reg;
1073
1074 drive_strength = ath9k_hw_ar9300_get_eeprom(ah, EEP_DRIVE_STRENGTH);
1075
1076 if (!drive_strength)
1077 return;
1078
1079 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS1);
1080 reg &= ~0x00ffffc0;
1081 reg |= 0x5 << 21;
1082 reg |= 0x5 << 18;
1083 reg |= 0x5 << 15;
1084 reg |= 0x5 << 12;
1085 reg |= 0x5 << 9;
1086 reg |= 0x5 << 6;
1087 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS1, reg);
1088
1089 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS2);
1090 reg &= ~0xffffffe0;
1091 reg |= 0x5 << 29;
1092 reg |= 0x5 << 26;
1093 reg |= 0x5 << 23;
1094 reg |= 0x5 << 20;
1095 reg |= 0x5 << 17;
1096 reg |= 0x5 << 14;
1097 reg |= 0x5 << 11;
1098 reg |= 0x5 << 8;
1099 reg |= 0x5 << 5;
1100 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS2, reg);
1101
1102 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS4);
1103 reg &= ~0xff800000;
1104 reg |= 0x5 << 29;
1105 reg |= 0x5 << 26;
1106 reg |= 0x5 << 23;
1107 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS4, reg);
1108}
1109
1110static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
1111{
1112 int internal_regulator =
1113 ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);
1114
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,
1124 REG_READ(ah,
1125 AR_RTC_REG_CONTROL1) |
1126 AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
1127 } else {
1128 REG_WRITE(ah, AR_RTC_SLEEP_CLK,
1129 (REG_READ(ah,
1130 AR_RTC_SLEEP_CLK) |
1131 AR_RTC_FORCE_SWREG_PRD));
1132 }
1133}
1134
1135static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
1136 struct ath9k_channel *chan)
1137{
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);
1142}
1143
1144static void ath9k_hw_ar9300_set_addac(struct ath_hw *ah,
1145 struct ath9k_channel *chan)
1146{
1147}
1148
1149/*
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.
1157 */
1158static int ar9003_hw_power_interpolate(int32_t x,
1159 int32_t *px, int32_t *py, u_int16_t np)
1160{
1161 int ip = 0;
1162 int lx = 0, ly = 0, lhave = 0;
1163 int hx = 0, hy = 0, hhave = 0;
1164 int dx = 0;
1165 int y = 0;
1166
1167 lhave = 0;
1168 hhave = 0;
1169
1170 /* identify best lower and higher x calibration measurement */
1171 for (ip = 0; ip < np; ip++) {
1172 dx = x - px[ip];
1173
1174 /* this measurement is higher than our desired x */
1175 if (dx <= 0) {
1176 if (!hhave || dx > (x - hx)) {
1177 /* new best higher x measurement */
1178 hx = px[ip];
1179 hy = py[ip];
1180 hhave = 1;
1181 }
1182 }
1183 /* this measurement is lower than our desired x */
1184 if (dx >= 0) {
1185 if (!lhave || dx < (x - lx)) {
1186 /* new best lower x measurement */
1187 lx = px[ip];
1188 ly = py[ip];
1189 lhave = 1;
1190 }
1191 }
1192 }
1193
1194 /* the low x is good */
1195 if (lhave) {
1196 /* so is the high x */
1197 if (hhave) {
1198 /* they're the same, so just pick one */
1199 if (hx == lx)
1200 y = ly;
1201 else /* interpolate */
1202 y = ly + (((x - lx) * (hy - ly)) / (hx - lx));
1203 } else /* only low is good, use it */
1204 y = ly;
1205 } else if (hhave) /* only high is good, use it */
1206 y = hy;
1207 else /* nothing is good,this should never happen unless np=0, ???? */
1208 y = -(1 << 30);
1209 return y;
1210}
1211
1212static u8 ar9003_hw_eeprom_get_tgt_pwr(struct ath_hw *ah,
1213 u16 rateIndex, u16 freq, bool is2GHz)
1214{
1215 u16 numPiers, i;
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;
1220 u8 *pFreqBin;
1221
1222 if (is2GHz) {
Felix Fietkaud10baf92010-04-26 15:04:38 -04001223 numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001224 pEepromTargetPwr = eep->calTargetPower2G;
1225 pFreqBin = eep->calTarget_freqbin_2G;
1226 } else {
1227 numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
1228 pEepromTargetPwr = eep->calTargetPower5G;
1229 pFreqBin = eep->calTarget_freqbin_5G;
1230 }
1231
1232 /*
1233 * create array of channels and targetpower from
1234 * targetpower piers stored on eeprom
1235 */
1236 for (i = 0; i < numPiers; i++) {
1237 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1238 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1239 }
1240
1241 /* interpolate to get target power for given frequency */
1242 return (u8) ar9003_hw_power_interpolate((s32) freq,
1243 freqArray,
1244 targetPowerArray, numPiers);
1245}
1246
1247static u8 ar9003_hw_eeprom_get_ht20_tgt_pwr(struct ath_hw *ah,
1248 u16 rateIndex,
1249 u16 freq, bool is2GHz)
1250{
1251 u16 numPiers, i;
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;
1256 u8 *pFreqBin;
1257
1258 if (is2GHz) {
Felix Fietkaud10baf92010-04-26 15:04:38 -04001259 numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001260 pEepromTargetPwr = eep->calTargetPower2GHT20;
1261 pFreqBin = eep->calTarget_freqbin_2GHT20;
1262 } else {
1263 numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
1264 pEepromTargetPwr = eep->calTargetPower5GHT20;
1265 pFreqBin = eep->calTarget_freqbin_5GHT20;
1266 }
1267
1268 /*
1269 * create array of channels and targetpower
1270 * from targetpower piers stored on eeprom
1271 */
1272 for (i = 0; i < numPiers; i++) {
1273 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1274 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1275 }
1276
1277 /* interpolate to get target power for given frequency */
1278 return (u8) ar9003_hw_power_interpolate((s32) freq,
1279 freqArray,
1280 targetPowerArray, numPiers);
1281}
1282
1283static u8 ar9003_hw_eeprom_get_ht40_tgt_pwr(struct ath_hw *ah,
1284 u16 rateIndex,
1285 u16 freq, bool is2GHz)
1286{
1287 u16 numPiers, i;
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;
1292 u8 *pFreqBin;
1293
1294 if (is2GHz) {
1295 numPiers = AR9300_NUM_2G_40_TARGET_POWERS;
1296 pEepromTargetPwr = eep->calTargetPower2GHT40;
1297 pFreqBin = eep->calTarget_freqbin_2GHT40;
1298 } else {
1299 numPiers = AR9300_NUM_5G_40_TARGET_POWERS;
1300 pEepromTargetPwr = eep->calTargetPower5GHT40;
1301 pFreqBin = eep->calTarget_freqbin_5GHT40;
1302 }
1303
1304 /*
1305 * create array of channels and targetpower from
1306 * targetpower piers stored on eeprom
1307 */
1308 for (i = 0; i < numPiers; i++) {
1309 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1310 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1311 }
1312
1313 /* interpolate to get target power for given frequency */
1314 return (u8) ar9003_hw_power_interpolate((s32) freq,
1315 freqArray,
1316 targetPowerArray, numPiers);
1317}
1318
1319static u8 ar9003_hw_eeprom_get_cck_tgt_pwr(struct ath_hw *ah,
1320 u16 rateIndex, u16 freq)
1321{
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;
1328
1329 /*
1330 * create array of channels and targetpower from
1331 * targetpower piers stored on eeprom
1332 */
1333 for (i = 0; i < numPiers; i++) {
1334 freqArray[i] = FBIN2FREQ(pFreqBin[i], 1);
1335 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1336 }
1337
1338 /* interpolate to get target power for given frequency */
1339 return (u8) ar9003_hw_power_interpolate((s32) freq,
1340 freqArray,
1341 targetPowerArray, numPiers);
1342}
1343
1344/* Set tx power registers to array of values passed in */
1345static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
1346{
1347#define POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
1348 /* make sure forced gain is not set */
1349 REG_WRITE(ah, 0xa458, 0);
1350
1351 /* Write the OFDM power per rate set */
1352
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));
1359
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));
1366
1367 /* Write the CCK power per rate set */
1368
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));
1375
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)
1382 );
1383
1384 /* Write the HT20 power per rate set */
1385
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)
1392 );
1393
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)
1400 );
1401
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)
1408 );
1409
1410 /* Mixed HT20 and HT40 rates */
1411
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)
1418 );
1419
1420 /*
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)
1424 */
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)
1430 );
1431
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)
1438 );
1439
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)
1446 );
1447
1448 return 0;
1449#undef POW_SM
1450}
1451
Luis R. Rodriguez824b1852010-08-01 02:25:16 -04001452static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq,
1453 u8 *targetPowerValT2)
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001454{
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001455 /* XXX: hard code for now, need to get from eeprom struct */
1456 u8 ht40PowerIncForPdadc = 0;
1457 bool is2GHz = false;
1458 unsigned int i = 0;
1459 struct ath_common *common = ath9k_hw_common(ah);
1460
1461 if (freq < 4000)
1462 is2GHz = true;
1463
1464 targetPowerValT2[ALL_TARGET_LEGACY_6_24] =
1465 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_6_24, freq,
1466 is2GHz);
1467 targetPowerValT2[ALL_TARGET_LEGACY_36] =
1468 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_36, freq,
1469 is2GHz);
1470 targetPowerValT2[ALL_TARGET_LEGACY_48] =
1471 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_48, freq,
1472 is2GHz);
1473 targetPowerValT2[ALL_TARGET_LEGACY_54] =
1474 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_54, freq,
1475 is2GHz);
1476 targetPowerValT2[ALL_TARGET_LEGACY_1L_5L] =
1477 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_1L_5L,
1478 freq);
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,
1487 is2GHz);
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,
1490 freq, is2GHz);
1491 targetPowerValT2[ALL_TARGET_HT20_4] =
1492 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_4, freq,
1493 is2GHz);
1494 targetPowerValT2[ALL_TARGET_HT20_5] =
1495 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_5, freq,
1496 is2GHz);
1497 targetPowerValT2[ALL_TARGET_HT20_6] =
1498 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_6, freq,
1499 is2GHz);
1500 targetPowerValT2[ALL_TARGET_HT20_7] =
1501 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_7, freq,
1502 is2GHz);
1503 targetPowerValT2[ALL_TARGET_HT20_12] =
1504 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_12, freq,
1505 is2GHz);
1506 targetPowerValT2[ALL_TARGET_HT20_13] =
1507 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_13, freq,
1508 is2GHz);
1509 targetPowerValT2[ALL_TARGET_HT20_14] =
1510 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_14, freq,
1511 is2GHz);
1512 targetPowerValT2[ALL_TARGET_HT20_15] =
1513 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_15, freq,
1514 is2GHz);
1515 targetPowerValT2[ALL_TARGET_HT20_20] =
1516 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_20, freq,
1517 is2GHz);
1518 targetPowerValT2[ALL_TARGET_HT20_21] =
1519 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_21, freq,
1520 is2GHz);
1521 targetPowerValT2[ALL_TARGET_HT20_22] =
1522 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_22, freq,
1523 is2GHz);
1524 targetPowerValT2[ALL_TARGET_HT20_23] =
1525 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
1526 is2GHz);
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,
1532 freq,
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;
1570
1571 while (i < ar9300RateSize) {
1572 ath_print(common, ATH_DBG_EEPROM,
1573 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1574 i++;
1575
1576 ath_print(common, ATH_DBG_EEPROM,
1577 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1578 i++;
1579
1580 ath_print(common, ATH_DBG_EEPROM,
1581 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1582 i++;
1583
1584 ath_print(common, ATH_DBG_EEPROM,
1585 "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
1586 i++;
1587 }
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001588}
1589
1590static int ar9003_hw_cal_pier_get(struct ath_hw *ah,
1591 int mode,
1592 int ipier,
1593 int ichain,
1594 int *pfrequency,
1595 int *pcorrection,
1596 int *ptemperature, int *pvoltage)
1597{
1598 u8 *pCalPier;
1599 struct ar9300_cal_data_per_freq_op_loop *pCalPierStruct;
1600 int is2GHz;
1601 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1602 struct ath_common *common = ath9k_hw_common(ah);
1603
1604 if (ichain >= AR9300_MAX_CHAINS) {
1605 ath_print(common, ATH_DBG_EEPROM,
1606 "Invalid chain index, must be less than %d\n",
1607 AR9300_MAX_CHAINS);
1608 return -1;
1609 }
1610
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);
1617 return -1;
1618 }
1619 pCalPier = &(eep->calFreqPier5G[ipier]);
1620 pCalPierStruct = &(eep->calPierData5G[ichain][ipier]);
1621 is2GHz = 0;
1622 } else {
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);
1627 return -1;
1628 }
1629
1630 pCalPier = &(eep->calFreqPier2G[ipier]);
1631 pCalPierStruct = &(eep->calPierData2G[ichain][ipier]);
1632 is2GHz = 1;
1633 }
1634
1635 *pfrequency = FBIN2FREQ(*pCalPier, is2GHz);
1636 *pcorrection = pCalPierStruct->refPower;
1637 *ptemperature = pCalPierStruct->tempMeas;
1638 *pvoltage = pCalPierStruct->voltMeas;
1639
1640 return 0;
1641}
1642
1643static int ar9003_hw_power_control_override(struct ath_hw *ah,
1644 int frequency,
1645 int *correction,
1646 int *voltage, int *temperature)
1647{
1648 int tempSlope = 0;
1649 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1650
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);
1660
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);
1671
1672 /*
1673 * enable temperature compensation
1674 * Need to use register names
1675 */
1676 if (frequency < 4000)
1677 tempSlope = eep->modalHeader2G.tempSlope;
1678 else
1679 tempSlope = eep->modalHeader5G.tempSlope;
1680
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,
1683 temperature[0]);
1684
1685 return 0;
1686}
1687
1688/* Apply the recorded correction values. */
1689static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
1690{
1691 int ichain, ipier, npier;
1692 int mode;
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];
1699 int fdiff;
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);
1704
1705 mode = (frequency >= 4000);
1706 if (mode)
1707 npier = AR9300_NUM_5G_CAL_PIERS;
1708 else
1709 npier = AR9300_NUM_2G_CAL_PIERS;
1710
1711 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1712 lfrequency[ichain] = 0;
1713 hfrequency[ichain] = 100000;
1714 }
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;
1722
1723 /*
1724 * this measurement is higher than
1725 * our desired frequency
1726 */
1727 if (fdiff <= 0) {
1728 if (hfrequency[ichain] <= 0 ||
1729 hfrequency[ichain] >= 100000 ||
1730 fdiff >
1731 (frequency - hfrequency[ichain])) {
1732 /*
1733 * new best higher
1734 * frequency measurement
1735 */
1736 hfrequency[ichain] = pfrequency;
1737 hcorrection[ichain] =
1738 pcorrection;
1739 htemperature[ichain] =
1740 ptemperature;
1741 hvoltage[ichain] = pvoltage;
1742 }
1743 }
1744 if (fdiff >= 0) {
1745 if (lfrequency[ichain] <= 0
1746 || fdiff <
1747 (frequency - lfrequency[ichain])) {
1748 /*
1749 * new best lower
1750 * frequency measurement
1751 */
1752 lfrequency[ichain] = pfrequency;
1753 lcorrection[ichain] =
1754 pcorrection;
1755 ltemperature[ichain] =
1756 ptemperature;
1757 lvoltage[ichain] = pvoltage;
1758 }
1759 }
1760 }
1761 }
1762 }
1763
1764 /* interpolate */
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];
1776 }
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) {
1781
1782 correction[ichain] = lcorrection[ichain] +
1783 (((frequency - lfrequency[ichain]) *
1784 (hcorrection[ichain] -
1785 lcorrection[ichain])) /
1786 (hfrequency[ichain] - lfrequency[ichain]));
1787
1788 temperature[ichain] = ltemperature[ichain] +
1789 (((frequency - lfrequency[ichain]) *
1790 (htemperature[ichain] -
1791 ltemperature[ichain])) /
1792 (hfrequency[ichain] - lfrequency[ichain]));
1793
1794 voltage[ichain] =
1795 lvoltage[ichain] +
1796 (((frequency -
1797 lfrequency[ichain]) * (hvoltage[ichain] -
1798 lvoltage[ichain]))
1799 / (hfrequency[ichain] -
1800 lfrequency[ichain]));
1801 }
1802 /* only low is good, use it */
1803 else {
1804 correction[ichain] = lcorrection[ichain];
1805 temperature[ichain] = ltemperature[ichain];
1806 voltage[ichain] = lvoltage[ichain];
1807 }
1808 }
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;
1818 }
1819 }
1820
1821 ar9003_hw_power_control_override(ah, frequency, correction, voltage,
1822 temperature);
1823
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]);
1827
1828 return 0;
1829}
1830
Luis R. Rodriguez824b1852010-08-01 02:25:16 -04001831static u16 ar9003_hw_get_direct_edge_power(struct ar9300_eeprom *eep,
1832 int idx,
1833 int edge,
1834 bool is2GHz)
1835{
1836 struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G;
1837 struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G;
1838
1839 if (is2GHz)
1840 return ctl_2g[idx].ctlEdges[edge].tPower;
1841 else
1842 return ctl_5g[idx].ctlEdges[edge].tPower;
1843}
1844
1845static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep,
1846 int idx,
1847 unsigned int edge,
1848 u16 freq,
1849 bool is2GHz)
1850{
1851 struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G;
1852 struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G;
1853
1854 u8 *ctl_freqbin = is2GHz ?
1855 &eep->ctl_freqbin_2G[idx][0] :
1856 &eep->ctl_freqbin_5G[idx][0];
1857
1858 if (is2GHz) {
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;
1862 } else {
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;
1866 }
1867
1868 return AR9300_MAX_RATE_POWER;
1869}
1870
1871/*
1872 * Find the maximum conformance test limit for the given channel and CTL info
1873 */
1874static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep,
1875 u16 freq, int idx, bool is2GHz)
1876{
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;
1883 unsigned int edge;
1884
1885 /* Get the edge power */
1886 for (edge = 0;
1887 (edge < num_edges) && (ctl_freqbin[edge] != AR9300_BCHAN_UNUSED);
1888 edge++) {
1889 /*
1890 * If there's an exact channel match or an inband flag set
1891 * on the lower channel use the given rdEdgePower
1892 */
1893 if (freq == ath9k_hw_fbin2freq(ctl_freqbin[edge], is2GHz)) {
1894 twiceMaxEdgePower =
1895 ar9003_hw_get_direct_edge_power(eep, idx,
1896 edge, is2GHz);
1897 break;
1898 } else if ((edge > 0) &&
1899 (freq < ath9k_hw_fbin2freq(ctl_freqbin[edge],
1900 is2GHz))) {
1901 twiceMaxEdgePower =
1902 ar9003_hw_get_indirect_edge_power(eep, idx,
1903 edge, freq,
1904 is2GHz);
1905 /*
1906 * Leave loop - no more affecting edges possible in
1907 * this monotonic increasing list
1908 */
1909 break;
1910 }
1911 }
1912 return twiceMaxEdgePower;
1913}
1914
1915static 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,
1920 u16 powerLimit)
1921{
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
1928 };
1929 int i;
1930 int16_t twiceLargestAntenna;
1931 u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
1932 u16 ctlModesFor11a[] = {
1933 CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
1934 };
1935 u16 ctlModesFor11g[] = {
1936 CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT,
1937 CTL_11G_EXT, CTL_2GHT40
1938 };
1939 u16 numCtlModes, *pCtlMode, ctlMode, freq;
1940 struct chan_centers centers;
1941 u8 *ctlIndex;
1942 u8 ctlNum;
1943 u16 twiceMinEdgePower;
1944 bool is2ghz = IS_CHAN_2GHZ(chan);
1945
1946 ath9k_hw_get_channel_centers(ah, chan, &centers);
1947
1948 /* Compute TxPower reduction due to Antenna Gain */
1949 if (is2ghz)
1950 twiceLargestAntenna = pEepData->modalHeader2G.antennaGain;
1951 else
1952 twiceLargestAntenna = pEepData->modalHeader5G.antennaGain;
1953
1954 twiceLargestAntenna = (int16_t)min((twiceAntennaReduction) -
1955 twiceLargestAntenna, 0);
1956
1957 /*
1958 * scaledPower is the minimum of the user input power level
1959 * and the regulatory allowed power level
1960 */
1961 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
1962
1963 if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
1964 maxRegAllowedPower -=
1965 (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
1966 }
1967
1968 scaledPower = min(powerLimit, maxRegAllowedPower);
1969
1970 /*
1971 * Reduce scaled Power by number of chains active to get
1972 * to per chain tx power level
1973 */
1974 switch (ar5416_get_ntxchains(ah->txchainmask)) {
1975 case 1:
1976 break;
1977 case 2:
1978 scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
1979 break;
1980 case 3:
1981 scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
1982 break;
1983 }
1984
1985 scaledPower = max((u16)0, scaledPower);
1986
1987 /*
1988 * Get target powers from EEPROM - our baseline for TX Power
1989 */
1990 if (is2ghz) {
1991 /* Setup for CTL modes */
1992 /* CTL_11B, CTL_11G, CTL_2GHT20 */
1993 numCtlModes =
1994 ARRAY_SIZE(ctlModesFor11g) -
1995 SUB_NUM_CTL_MODES_AT_2G_40;
1996 pCtlMode = ctlModesFor11g;
1997 if (IS_CHAN_HT40(chan))
1998 /* All 2G CTL's */
1999 numCtlModes = ARRAY_SIZE(ctlModesFor11g);
2000 } else {
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))
2007 /* All 5G CTL's */
2008 numCtlModes = ARRAY_SIZE(ctlModesFor11a);
2009 }
2010
2011 /*
2012 * For MIMO, need to apply regulatory caps individually across
2013 * dynamically running modes: CCK, OFDM, HT20, HT40
2014 *
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.
2018 */
2019 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
2020 bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
2021 (pCtlMode[ctlMode] == CTL_2GHT40);
2022 if (isHt40CtlMode)
2023 freq = centers.synth_center;
2024 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
2025 freq = centers.ext_center;
2026 else
2027 freq = centers.ctl_center;
2028
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));
2034
2035 /* walk through each CTL index stored in EEPROM */
2036 if (is2ghz) {
2037 ctlIndex = pEepData->ctlIndex_2G;
2038 ctlNum = AR9300_NUM_CTLS_2G;
2039 } else {
2040 ctlIndex = pEepData->ctlIndex_5G;
2041 ctlNum = AR9300_NUM_CTLS_5G;
2042 }
2043
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 "
2048 "chan %dn",
2049 i, cfgCtl, pCtlMode[ctlMode], ctlIndex[i],
2050 chan->channel);
2051
2052 /*
2053 * compare test group from regulatory
2054 * channel list with test mode from pCtlMode
2055 * list
2056 */
2057 if ((((cfgCtl & ~CTL_MODE_M) |
2058 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
2059 ctlIndex[i]) ||
2060 (((cfgCtl & ~CTL_MODE_M) |
2061 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
2062 ((ctlIndex[i] & CTL_MODE_M) |
2063 SD_NO_CTL))) {
2064 twiceMinEdgePower =
2065 ar9003_hw_get_max_edge_power(pEepData,
2066 freq, i,
2067 is2ghz);
2068
2069 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL)
2070 /*
2071 * Find the minimum of all CTL
2072 * edge powers that apply to
2073 * this channel
2074 */
2075 twiceMaxEdgePower =
2076 min(twiceMaxEdgePower,
2077 twiceMinEdgePower);
2078 else {
2079 /* specific */
2080 twiceMaxEdgePower =
2081 twiceMinEdgePower;
2082 break;
2083 }
2084 }
2085 }
2086
2087 minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
2088
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);
2094
2095 /* Apply ctl mode to correct target power set */
2096 switch (pCtlMode[ctlMode]) {
2097 case CTL_11B:
2098 for (i = ALL_TARGET_LEGACY_1L_5L;
2099 i <= ALL_TARGET_LEGACY_11S; i++)
2100 pPwrArray[i] =
2101 (u8)min((u16)pPwrArray[i],
2102 minCtlPower);
2103 break;
2104 case CTL_11A:
2105 case CTL_11G:
2106 for (i = ALL_TARGET_LEGACY_6_24;
2107 i <= ALL_TARGET_LEGACY_54; i++)
2108 pPwrArray[i] =
2109 (u8)min((u16)pPwrArray[i],
2110 minCtlPower);
2111 break;
2112 case CTL_5GHT20:
2113 case CTL_2GHT20:
2114 for (i = ALL_TARGET_HT20_0_8_16;
2115 i <= ALL_TARGET_HT20_21; i++)
2116 pPwrArray[i] =
2117 (u8)min((u16)pPwrArray[i],
2118 minCtlPower);
2119 pPwrArray[ALL_TARGET_HT20_22] =
2120 (u8)min((u16)pPwrArray[ALL_TARGET_HT20_22],
2121 minCtlPower);
2122 pPwrArray[ALL_TARGET_HT20_23] =
2123 (u8)min((u16)pPwrArray[ALL_TARGET_HT20_23],
2124 minCtlPower);
2125 break;
2126 case CTL_5GHT40:
2127 case CTL_2GHT40:
2128 for (i = ALL_TARGET_HT40_0_8_16;
2129 i <= ALL_TARGET_HT40_23; i++)
2130 pPwrArray[i] =
2131 (u8)min((u16)pPwrArray[i],
2132 minCtlPower);
2133 break;
2134 default:
2135 break;
2136 }
2137 } /* end ctl mode checking */
2138}
2139
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04002140static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
2141 struct ath9k_channel *chan, u16 cfgCtl,
2142 u8 twiceAntennaReduction,
2143 u8 twiceMaxRegulatoryPower,
Felix Fietkaude40f312010-10-20 03:08:53 +02002144 u8 powerLimit, bool test)
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04002145{
Felix Fietkau6b7b6cf2010-10-20 02:09:44 +02002146 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
Luis R. Rodriguez824b1852010-08-01 02:25:16 -04002147 struct ath_common *common = ath9k_hw_common(ah);
2148 u8 targetPowerValT2[ar9300RateSize];
2149 unsigned int i = 0;
2150
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,
2156 powerLimit);
2157
Felix Fietkaude40f312010-10-20 03:08:53 +02002158 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];
2162 }
2163
2164 if (test)
2165 return;
2166
2167 for (i = 0; i < ar9300RateSize; i++) {
Luis R. Rodriguez824b1852010-08-01 02:25:16 -04002168 ath_print(common, ATH_DBG_EEPROM,
2169 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
2170 i++;
2171 ath_print(common, ATH_DBG_EEPROM,
2172 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
2173 i++;
2174 ath_print(common, ATH_DBG_EEPROM,
2175 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
2176 i++;
2177 ath_print(common, ATH_DBG_EEPROM,
2178 "TPC[%02d] 0x%08x\n\n", i, targetPowerValT2[i]);
2179 i++;
2180 }
2181
Luis R. Rodriguez824b1852010-08-01 02:25:16 -04002182 /*
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.
2186 *
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 (?).
2192 */
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 */
2198
2199 ah->txpower_limit = targetPowerValT2[i];
Felix Fietkaude40f312010-10-20 03:08:53 +02002200 regulatory->max_power_level = targetPowerValT2[i];
Luis R. Rodriguez824b1852010-08-01 02:25:16 -04002201
Felix Fietkaude40f312010-10-20 03:08:53 +02002202 /* Write target power array to registers */
2203 ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04002204 ar9003_hw_calibration_apply(ah, chan->channel);
2205}
2206
2207static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah,
2208 u16 i, bool is2GHz)
2209{
2210 return AR_NO_SPUR;
2211}
2212
Luis R. Rodriguezc14a85d2010-04-15 17:39:21 -04002213s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah)
2214{
2215 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
2216
2217 return (eep->baseEepHeader.txrxgain >> 4) & 0xf; /* bits 7:4 */
2218}
2219
2220s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah)
2221{
2222 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
2223
2224 return (eep->baseEepHeader.txrxgain) & 0xf; /* bits 3:0 */
2225}
2226
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04002227const 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
2239};