blob: 23eb60ea54551eee078009418c1159eaffc622f2 [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
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -040044static const struct ar9300_eeprom ar9300_default = {
45 .eepromVersion = 2,
46 .templateVersion = 2,
47 .macAddr = {1, 2, 3, 4, 5, 6},
48 .custData = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
49 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
50 .baseEepHeader = {
Felix Fietkauffdc4cb2010-05-11 17:23:03 +020051 .regDmn = { LE16(0), LE16(0x1f) },
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -040052 .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
53 .opCapFlags = {
54 .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
55 .eepMisc = 0,
56 },
57 .rfSilent = 0,
58 .blueToothOptions = 0,
59 .deviceCap = 0,
60 .deviceType = 5, /* takes lower byte in eeprom location */
61 .pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
62 .params_for_tuning_caps = {0, 0},
63 .featureEnable = 0x0c,
64 /*
65 * bit0 - enable tx temp comp - disabled
66 * bit1 - enable tx volt comp - disabled
67 * bit2 - enable fastClock - enabled
68 * bit3 - enable doubling - enabled
69 * bit4 - enable internal regulator - disabled
70 */
71 .miscConfiguration = 0, /* bit0 - turn down drivestrength */
72 .eepromWriteEnableGpio = 3,
73 .wlanDisableGpio = 0,
74 .wlanLedGpio = 8,
75 .rxBandSelectGpio = 0xff,
76 .txrxgain = 0,
77 .swreg = 0,
78 },
79 .modalHeader2G = {
80 /* ar9300_modal_eep_header 2g */
81 /* 4 idle,t1,t2,b(4 bits per setting) */
Felix Fietkauffdc4cb2010-05-11 17:23:03 +020082 .antCtrlCommon = LE32(0x110),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -040083 /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
Felix Fietkauffdc4cb2010-05-11 17:23:03 +020084 .antCtrlCommon2 = LE32(0x22222),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -040085
86 /*
87 * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
88 * rx1, rx12, b (2 bits each)
89 */
Felix Fietkauffdc4cb2010-05-11 17:23:03 +020090 .antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) },
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -040091
92 /*
93 * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db
94 * for ar9280 (0xa20c/b20c 5:0)
95 */
96 .xatten1DB = {0, 0, 0},
97
98 /*
99 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
100 * for ar9280 (0xa20c/b20c 16:12
101 */
102 .xatten1Margin = {0, 0, 0},
103 .tempSlope = 36,
104 .voltSlope = 0,
105
106 /*
107 * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
108 * channels in usual fbin coding format
109 */
110 .spurChans = {0, 0, 0, 0, 0},
111
112 /*
113 * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
114 * if the register is per chain
115 */
116 .noiseFloorThreshCh = {-1, 0, 0},
117 .ob = {1, 1, 1},/* 3 chain */
118 .db_stage2 = {1, 1, 1}, /* 3 chain */
119 .db_stage3 = {0, 0, 0},
120 .db_stage4 = {0, 0, 0},
121 .xpaBiasLvl = 0,
122 .txFrameToDataStart = 0x0e,
123 .txFrameToPaOn = 0x0e,
124 .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
125 .antennaGain = 0,
126 .switchSettling = 0x2c,
127 .adcDesiredSize = -30,
128 .txEndToXpaOff = 0,
129 .txEndToRxOn = 0x2,
130 .txFrameToXpaOn = 0xe,
131 .thresh62 = 28,
132 .futureModal = { /* [32] */
133 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
135 },
136 },
137 .calFreqPier2G = {
138 FREQ2FBIN(2412, 1),
139 FREQ2FBIN(2437, 1),
140 FREQ2FBIN(2472, 1),
141 },
142 /* ar9300_cal_data_per_freq_op_loop 2g */
143 .calPierData2G = {
144 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
145 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
146 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
147 },
148 .calTarget_freqbin_Cck = {
149 FREQ2FBIN(2412, 1),
150 FREQ2FBIN(2484, 1),
151 },
152 .calTarget_freqbin_2G = {
153 FREQ2FBIN(2412, 1),
154 FREQ2FBIN(2437, 1),
155 FREQ2FBIN(2472, 1)
156 },
157 .calTarget_freqbin_2GHT20 = {
158 FREQ2FBIN(2412, 1),
159 FREQ2FBIN(2437, 1),
160 FREQ2FBIN(2472, 1)
161 },
162 .calTarget_freqbin_2GHT40 = {
163 FREQ2FBIN(2412, 1),
164 FREQ2FBIN(2437, 1),
165 FREQ2FBIN(2472, 1)
166 },
167 .calTargetPowerCck = {
168 /* 1L-5L,5S,11L,11S */
169 { {36, 36, 36, 36} },
170 { {36, 36, 36, 36} },
171 },
172 .calTargetPower2G = {
173 /* 6-24,36,48,54 */
174 { {32, 32, 28, 24} },
175 { {32, 32, 28, 24} },
176 { {32, 32, 28, 24} },
177 },
178 .calTargetPower2GHT20 = {
179 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
180 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
181 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
182 },
183 .calTargetPower2GHT40 = {
184 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
185 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
186 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
187 },
188 .ctlIndex_2G = {
189 0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
190 0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
191 },
192 .ctl_freqbin_2G = {
193 {
194 FREQ2FBIN(2412, 1),
195 FREQ2FBIN(2417, 1),
196 FREQ2FBIN(2457, 1),
197 FREQ2FBIN(2462, 1)
198 },
199 {
200 FREQ2FBIN(2412, 1),
201 FREQ2FBIN(2417, 1),
202 FREQ2FBIN(2462, 1),
203 0xFF,
204 },
205
206 {
207 FREQ2FBIN(2412, 1),
208 FREQ2FBIN(2417, 1),
209 FREQ2FBIN(2462, 1),
210 0xFF,
211 },
212 {
213 FREQ2FBIN(2422, 1),
214 FREQ2FBIN(2427, 1),
215 FREQ2FBIN(2447, 1),
216 FREQ2FBIN(2452, 1)
217 },
218
219 {
220 /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
221 /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
222 /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
223 /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
224 },
225
226 {
227 /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
228 /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
229 /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
230 0,
231 },
232
233 {
234 /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
235 /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
236 FREQ2FBIN(2472, 1),
237 0,
238 },
239
240 {
241 /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
242 /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
243 /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
244 /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
245 },
246
247 {
248 /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
249 /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
250 /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
251 },
252
253 {
254 /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
255 /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
256 /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
257 0
258 },
259
260 {
261 /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
262 /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
263 /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
264 0
265 },
266
267 {
268 /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
269 /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
270 /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
271 /* Data[11].ctlEdges[3].bChannel */
272 FREQ2FBIN(2462, 1),
273 }
274 },
275 .ctlPowerData_2G = {
276 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
277 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
278 { { {60, 1}, {60, 0}, {60, 0}, {60, 1} } },
279
280 { { {60, 1}, {60, 0}, {0, 0}, {0, 0} } },
281 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
282 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
283
284 { { {60, 0}, {60, 1}, {60, 1}, {60, 0} } },
285 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
286 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
287
288 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
289 { { {60, 0}, {60, 1}, {60, 1}, {60, 1} } },
290 },
291 .modalHeader5G = {
292 /* 4 idle,t1,t2,b (4 bits per setting) */
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200293 .antCtrlCommon = LE32(0x110),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400294 /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200295 .antCtrlCommon2 = LE32(0x22222),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400296 /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
297 .antCtrlChain = {
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200298 LE16(0x000), LE16(0x000), LE16(0x000),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400299 },
300 /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
301 .xatten1DB = {0, 0, 0},
302
303 /*
304 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
305 * for merlin (0xa20c/b20c 16:12
306 */
307 .xatten1Margin = {0, 0, 0},
308 .tempSlope = 68,
309 .voltSlope = 0,
310 /* spurChans spur channels in usual fbin coding format */
311 .spurChans = {0, 0, 0, 0, 0},
312 /* noiseFloorThreshCh Check if the register is per chain */
313 .noiseFloorThreshCh = {-1, 0, 0},
314 .ob = {3, 3, 3}, /* 3 chain */
315 .db_stage2 = {3, 3, 3}, /* 3 chain */
316 .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
317 .db_stage4 = {3, 3, 3}, /* don't exist for 2G */
318 .xpaBiasLvl = 0,
319 .txFrameToDataStart = 0x0e,
320 .txFrameToPaOn = 0x0e,
321 .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
322 .antennaGain = 0,
323 .switchSettling = 0x2d,
324 .adcDesiredSize = -30,
325 .txEndToXpaOff = 0,
326 .txEndToRxOn = 0x2,
327 .txFrameToXpaOn = 0xe,
328 .thresh62 = 28,
329 .futureModal = {
330 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
331 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
332 },
333 },
334 .calFreqPier5G = {
335 FREQ2FBIN(5180, 0),
336 FREQ2FBIN(5220, 0),
337 FREQ2FBIN(5320, 0),
338 FREQ2FBIN(5400, 0),
339 FREQ2FBIN(5500, 0),
340 FREQ2FBIN(5600, 0),
341 FREQ2FBIN(5725, 0),
342 FREQ2FBIN(5825, 0)
343 },
344 .calPierData5G = {
345 {
346 {0, 0, 0, 0, 0},
347 {0, 0, 0, 0, 0},
348 {0, 0, 0, 0, 0},
349 {0, 0, 0, 0, 0},
350 {0, 0, 0, 0, 0},
351 {0, 0, 0, 0, 0},
352 {0, 0, 0, 0, 0},
353 {0, 0, 0, 0, 0},
354 },
355 {
356 {0, 0, 0, 0, 0},
357 {0, 0, 0, 0, 0},
358 {0, 0, 0, 0, 0},
359 {0, 0, 0, 0, 0},
360 {0, 0, 0, 0, 0},
361 {0, 0, 0, 0, 0},
362 {0, 0, 0, 0, 0},
363 {0, 0, 0, 0, 0},
364 },
365 {
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},
373 {0, 0, 0, 0, 0},
374 },
375
376 },
377 .calTarget_freqbin_5G = {
378 FREQ2FBIN(5180, 0),
379 FREQ2FBIN(5220, 0),
380 FREQ2FBIN(5320, 0),
381 FREQ2FBIN(5400, 0),
382 FREQ2FBIN(5500, 0),
383 FREQ2FBIN(5600, 0),
384 FREQ2FBIN(5725, 0),
385 FREQ2FBIN(5825, 0)
386 },
387 .calTarget_freqbin_5GHT20 = {
388 FREQ2FBIN(5180, 0),
389 FREQ2FBIN(5240, 0),
390 FREQ2FBIN(5320, 0),
391 FREQ2FBIN(5500, 0),
392 FREQ2FBIN(5700, 0),
393 FREQ2FBIN(5745, 0),
394 FREQ2FBIN(5725, 0),
395 FREQ2FBIN(5825, 0)
396 },
397 .calTarget_freqbin_5GHT40 = {
398 FREQ2FBIN(5180, 0),
399 FREQ2FBIN(5240, 0),
400 FREQ2FBIN(5320, 0),
401 FREQ2FBIN(5500, 0),
402 FREQ2FBIN(5700, 0),
403 FREQ2FBIN(5745, 0),
404 FREQ2FBIN(5725, 0),
405 FREQ2FBIN(5825, 0)
406 },
407 .calTargetPower5G = {
408 /* 6-24,36,48,54 */
409 { {20, 20, 20, 10} },
410 { {20, 20, 20, 10} },
411 { {20, 20, 20, 10} },
412 { {20, 20, 20, 10} },
413 { {20, 20, 20, 10} },
414 { {20, 20, 20, 10} },
415 { {20, 20, 20, 10} },
416 { {20, 20, 20, 10} },
417 },
418 .calTargetPower5GHT20 = {
419 /*
420 * 0_8_16,1-3_9-11_17-19,
421 * 4,5,6,7,12,13,14,15,20,21,22,23
422 */
423 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
424 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
425 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
426 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
427 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
428 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
429 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
430 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
431 },
432 .calTargetPower5GHT40 = {
433 /*
434 * 0_8_16,1-3_9-11_17-19,
435 * 4,5,6,7,12,13,14,15,20,21,22,23
436 */
437 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
438 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
439 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
440 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
441 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
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 },
446 .ctlIndex_5G = {
447 0x10, 0x16, 0x18, 0x40, 0x46,
448 0x48, 0x30, 0x36, 0x38
449 },
450 .ctl_freqbin_5G = {
451 {
452 /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
453 /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
454 /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
455 /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
456 /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
457 /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
458 /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
459 /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
460 },
461 {
462 /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
463 /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
464 /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
465 /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
466 /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
467 /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
468 /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
469 /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
470 },
471
472 {
473 /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
474 /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
475 /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
476 /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
477 /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
478 /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
479 /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
480 /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
481 },
482
483 {
484 /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
485 /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
486 /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
487 /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
488 /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
489 /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
490 /* Data[3].ctlEdges[6].bChannel */ 0xFF,
491 /* Data[3].ctlEdges[7].bChannel */ 0xFF,
492 },
493
494 {
495 /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
496 /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
497 /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
498 /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
499 /* Data[4].ctlEdges[4].bChannel */ 0xFF,
500 /* Data[4].ctlEdges[5].bChannel */ 0xFF,
501 /* Data[4].ctlEdges[6].bChannel */ 0xFF,
502 /* Data[4].ctlEdges[7].bChannel */ 0xFF,
503 },
504
505 {
506 /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
507 /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
508 /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
509 /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
510 /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
511 /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
512 /* Data[5].ctlEdges[6].bChannel */ 0xFF,
513 /* Data[5].ctlEdges[7].bChannel */ 0xFF
514 },
515
516 {
517 /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
518 /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
519 /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
520 /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
521 /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
522 /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
523 /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
524 /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
525 },
526
527 {
528 /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
529 /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
530 /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
531 /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
532 /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
533 /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
534 /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
535 /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
536 },
537
538 {
539 /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
540 /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
541 /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
542 /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
543 /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
544 /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
545 /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
546 /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
547 }
548 },
549 .ctlPowerData_5G = {
550 {
551 {
552 {60, 1}, {60, 1}, {60, 1}, {60, 1},
553 {60, 1}, {60, 1}, {60, 1}, {60, 0},
554 }
555 },
556 {
557 {
558 {60, 1}, {60, 1}, {60, 1}, {60, 1},
559 {60, 1}, {60, 1}, {60, 1}, {60, 0},
560 }
561 },
562 {
563 {
564 {60, 0}, {60, 1}, {60, 0}, {60, 1},
565 {60, 1}, {60, 1}, {60, 1}, {60, 1},
566 }
567 },
568 {
569 {
570 {60, 0}, {60, 1}, {60, 1}, {60, 0},
571 {60, 1}, {60, 0}, {60, 0}, {60, 0},
572 }
573 },
574 {
575 {
576 {60, 1}, {60, 1}, {60, 1}, {60, 0},
577 {60, 0}, {60, 0}, {60, 0}, {60, 0},
578 }
579 },
580 {
581 {
582 {60, 1}, {60, 1}, {60, 1}, {60, 1},
583 {60, 1}, {60, 0}, {60, 0}, {60, 0},
584 }
585 },
586 {
587 {
588 {60, 1}, {60, 1}, {60, 1}, {60, 1},
589 {60, 1}, {60, 1}, {60, 1}, {60, 1},
590 }
591 },
592 {
593 {
594 {60, 1}, {60, 1}, {60, 0}, {60, 1},
595 {60, 1}, {60, 1}, {60, 1}, {60, 0},
596 }
597 },
598 {
599 {
600 {60, 1}, {60, 0}, {60, 1}, {60, 1},
601 {60, 1}, {60, 1}, {60, 0}, {60, 1},
602 }
603 },
604 }
605};
606
607static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah)
608{
609 return 0;
610}
611
612static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
613 enum eeprom_param param)
614{
615 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
616 struct ar9300_base_eep_hdr *pBase = &eep->baseEepHeader;
617
618 switch (param) {
619 case EEP_MAC_LSW:
620 return eep->macAddr[0] << 8 | eep->macAddr[1];
621 case EEP_MAC_MID:
622 return eep->macAddr[2] << 8 | eep->macAddr[3];
623 case EEP_MAC_MSW:
624 return eep->macAddr[4] << 8 | eep->macAddr[5];
625 case EEP_REG_0:
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200626 return le16_to_cpu(pBase->regDmn[0]);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400627 case EEP_REG_1:
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200628 return le16_to_cpu(pBase->regDmn[1]);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400629 case EEP_OP_CAP:
630 return pBase->deviceCap;
631 case EEP_OP_MODE:
632 return pBase->opCapFlags.opFlags;
633 case EEP_RF_SILENT:
634 return pBase->rfSilent;
635 case EEP_TX_MASK:
636 return (pBase->txrxMask >> 4) & 0xf;
637 case EEP_RX_MASK:
638 return pBase->txrxMask & 0xf;
639 case EEP_DRIVE_STRENGTH:
640#define AR9300_EEP_BASE_DRIV_STRENGTH 0x1
641 return pBase->miscConfiguration & AR9300_EEP_BASE_DRIV_STRENGTH;
642 case EEP_INTERNAL_REGULATOR:
643 /* Bit 4 is internal regulator flag */
644 return (pBase->featureEnable & 0x10) >> 4;
645 case EEP_SWREG:
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200646 return le32_to_cpu(pBase->swreg);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400647 default:
648 return 0;
649 }
650}
651
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200652static bool ar9300_eeprom_read_byte(struct ath_common *common, int address,
653 u8 *buffer)
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400654{
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200655 u16 val;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400656
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200657 if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
658 return false;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400659
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200660 *buffer = (val >> (8 * (address % 2))) & 0xff;
661 return true;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400662}
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400663
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200664static bool ar9300_eeprom_read_word(struct ath_common *common, int address,
665 u8 *buffer)
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400666{
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200667 u16 val;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400668
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200669 if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
670 return false;
671
672 buffer[0] = val >> 8;
673 buffer[1] = val & 0xff;
674
675 return true;
676}
677
678static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer,
679 int count)
680{
681 struct ath_common *common = ath9k_hw_common(ah);
682 int i;
683
684 if ((address < 0) || ((address + count) / 2 > AR9300_EEPROM_SIZE - 1)) {
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400685 ath_print(common, ATH_DBG_EEPROM,
686 "eeprom address not in range\n");
687 return false;
688 }
689
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200690 /*
691 * Since we're reading the bytes in reverse order from a little-endian
692 * word stream, an even address means we only use the lower half of
693 * the 16-bit word at that address
694 */
695 if (address % 2 == 0) {
696 if (!ar9300_eeprom_read_byte(common, address--, buffer++))
697 goto error;
698
699 count--;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400700 }
701
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200702 for (i = 0; i < count / 2; i++) {
703 if (!ar9300_eeprom_read_word(common, address, buffer))
704 goto error;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400705
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200706 address -= 2;
707 buffer += 2;
708 }
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400709
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200710 if (count % 2)
711 if (!ar9300_eeprom_read_byte(common, address, buffer))
712 goto error;
713
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400714 return true;
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200715
716error:
717 ath_print(common, ATH_DBG_EEPROM,
718 "unable to read eeprom region at offset %d\n", address);
719 return false;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400720}
721
722static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference,
723 int *length, int *major, int *minor)
724{
725 unsigned long value[4];
726
727 value[0] = best[0];
728 value[1] = best[1];
729 value[2] = best[2];
730 value[3] = best[3];
731 *code = ((value[0] >> 5) & 0x0007);
732 *reference = (value[0] & 0x001f) | ((value[1] >> 2) & 0x0020);
733 *length = ((value[1] << 4) & 0x07f0) | ((value[2] >> 4) & 0x000f);
734 *major = (value[2] & 0x000f);
735 *minor = (value[3] & 0x00ff);
736}
737
738static u16 ar9300_comp_cksum(u8 *data, int dsize)
739{
740 int it, checksum = 0;
741
742 for (it = 0; it < dsize; it++) {
743 checksum += data[it];
744 checksum &= 0xffff;
745 }
746
747 return checksum;
748}
749
750static bool ar9300_uncompress_block(struct ath_hw *ah,
751 u8 *mptr,
752 int mdataSize,
753 u8 *block,
754 int size)
755{
756 int it;
757 int spot;
758 int offset;
759 int length;
760 struct ath_common *common = ath9k_hw_common(ah);
761
762 spot = 0;
763
764 for (it = 0; it < size; it += (length+2)) {
765 offset = block[it];
766 offset &= 0xff;
767 spot += offset;
768 length = block[it+1];
769 length &= 0xff;
770
771 if (length > 0 && spot >= 0 && spot+length < mdataSize) {
772 ath_print(common, ATH_DBG_EEPROM,
773 "Restore at %d: spot=%d "
774 "offset=%d length=%d\n",
775 it, spot, offset, length);
776 memcpy(&mptr[spot], &block[it+2], length);
777 spot += length;
778 } else if (length > 0) {
779 ath_print(common, ATH_DBG_EEPROM,
780 "Bad restore at %d: spot=%d "
781 "offset=%d length=%d\n",
782 it, spot, offset, length);
783 return false;
784 }
785 }
786 return true;
787}
788
789static int ar9300_compress_decision(struct ath_hw *ah,
790 int it,
791 int code,
792 int reference,
793 u8 *mptr,
794 u8 *word, int length, int mdata_size)
795{
796 struct ath_common *common = ath9k_hw_common(ah);
797 u8 *dptr;
798
799 switch (code) {
800 case _CompressNone:
801 if (length != mdata_size) {
802 ath_print(common, ATH_DBG_EEPROM,
803 "EEPROM structure size mismatch"
804 "memory=%d eeprom=%d\n", mdata_size, length);
805 return -1;
806 }
807 memcpy(mptr, (u8 *) (word + COMP_HDR_LEN), length);
808 ath_print(common, ATH_DBG_EEPROM, "restored eeprom %d:"
809 " uncompressed, length %d\n", it, length);
810 break;
811 case _CompressBlock:
812 if (reference == 0) {
813 dptr = mptr;
814 } else {
815 if (reference != 2) {
816 ath_print(common, ATH_DBG_EEPROM,
817 "cant find reference eeprom"
818 "struct %d\n", reference);
819 return -1;
820 }
821 memcpy(mptr, &ar9300_default, mdata_size);
822 }
823 ath_print(common, ATH_DBG_EEPROM,
824 "restore eeprom %d: block, reference %d,"
825 " length %d\n", it, reference, length);
826 ar9300_uncompress_block(ah, mptr, mdata_size,
827 (u8 *) (word + COMP_HDR_LEN), length);
828 break;
829 default:
830 ath_print(common, ATH_DBG_EEPROM, "unknown compression"
831 " code %d\n", code);
832 return -1;
833 }
834 return 0;
835}
836
837/*
838 * Read the configuration data from the eeprom.
839 * The data can be put in any specified memory buffer.
840 *
841 * Returns -1 on error.
842 * Returns address of next memory location on success.
843 */
844static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
845 u8 *mptr, int mdata_size)
846{
847#define MDEFAULT 15
848#define MSTATE 100
849 int cptr;
850 u8 *word;
851 int code;
852 int reference, length, major, minor;
853 int osize;
854 int it;
855 u16 checksum, mchecksum;
856 struct ath_common *common = ath9k_hw_common(ah);
857
858 word = kzalloc(2048, GFP_KERNEL);
859 if (!word)
860 return -1;
861
862 memcpy(mptr, &ar9300_default, mdata_size);
863
864 cptr = AR9300_BASE_ADDR;
865 for (it = 0; it < MSTATE; it++) {
866 if (!ar9300_read_eeprom(ah, cptr, word, COMP_HDR_LEN))
867 goto fail;
868
869 if ((word[0] == 0 && word[1] == 0 && word[2] == 0 &&
870 word[3] == 0) || (word[0] == 0xff && word[1] == 0xff
871 && word[2] == 0xff && word[3] == 0xff))
872 break;
873
874 ar9300_comp_hdr_unpack(word, &code, &reference,
875 &length, &major, &minor);
876 ath_print(common, ATH_DBG_EEPROM,
877 "Found block at %x: code=%d ref=%d"
878 "length=%d major=%d minor=%d\n", cptr, code,
879 reference, length, major, minor);
880 if (length >= 1024) {
881 ath_print(common, ATH_DBG_EEPROM,
882 "Skipping bad header\n");
883 cptr -= COMP_HDR_LEN;
884 continue;
885 }
886
887 osize = length;
888 ar9300_read_eeprom(ah, cptr, word,
889 COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
890 checksum = ar9300_comp_cksum(&word[COMP_HDR_LEN], length);
891 mchecksum = word[COMP_HDR_LEN + osize] |
892 (word[COMP_HDR_LEN + osize + 1] << 8);
893 ath_print(common, ATH_DBG_EEPROM,
894 "checksum %x %x\n", checksum, mchecksum);
895 if (checksum == mchecksum) {
896 ar9300_compress_decision(ah, it, code, reference, mptr,
897 word, length, mdata_size);
898 } else {
899 ath_print(common, ATH_DBG_EEPROM,
900 "skipping block with bad checksum\n");
901 }
902 cptr -= (COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
903 }
904
905 kfree(word);
906 return cptr;
907
908fail:
909 kfree(word);
910 return -1;
911}
912
913/*
914 * Restore the configuration structure by reading the eeprom.
915 * This function destroys any existing in-memory structure
916 * content.
917 */
918static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw *ah)
919{
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200920 u8 *mptr = (u8 *) &ah->eeprom.ar9300_eep;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400921
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200922 if (ar9300_eeprom_restore_internal(ah, mptr,
923 sizeof(struct ar9300_eeprom)) < 0)
924 return false;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400925
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200926 return true;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400927}
928
929/* XXX: review hardware docs */
930static int ath9k_hw_ar9300_get_eeprom_ver(struct ath_hw *ah)
931{
932 return ah->eeprom.ar9300_eep.eepromVersion;
933}
934
935/* XXX: could be read from the eepromVersion, not sure yet */
936static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw *ah)
937{
938 return 0;
939}
940
941static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah,
942 enum ieee80211_band freq_band)
943{
944 return 1;
945}
946
947static u16 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah,
948 struct ath9k_channel *chan)
949{
950 return -EINVAL;
951}
952
953static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz)
954{
955 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
956
957 if (is2ghz)
958 return eep->modalHeader2G.xpaBiasLvl;
959 else
960 return eep->modalHeader5G.xpaBiasLvl;
961}
962
963static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
964{
965 int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz);
966 REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, (bias & 0x3));
967 REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_SPARE,
968 ((bias >> 2) & 0x3));
969}
970
971static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz)
972{
973 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200974 __le32 val;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400975
976 if (is2ghz)
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200977 val = eep->modalHeader2G.antCtrlCommon;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400978 else
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200979 val = eep->modalHeader5G.antCtrlCommon;
980 return le32_to_cpu(val);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400981}
982
983static u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz)
984{
985 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200986 __le32 val;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400987
988 if (is2ghz)
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200989 val = eep->modalHeader2G.antCtrlCommon2;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400990 else
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200991 val = eep->modalHeader5G.antCtrlCommon2;
992 return le32_to_cpu(val);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400993}
994
995static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah,
996 int chain,
997 bool is2ghz)
998{
999 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001000 __le16 val = 0;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001001
1002 if (chain >= 0 && chain < AR9300_MAX_CHAINS) {
1003 if (is2ghz)
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001004 val = eep->modalHeader2G.antCtrlChain[chain];
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001005 else
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001006 val = eep->modalHeader5G.antCtrlChain[chain];
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001007 }
1008
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001009 return le16_to_cpu(val);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001010}
1011
1012static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
1013{
1014 u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);
1015 REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value);
1016
1017 value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz);
1018 REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
1019
1020 value = ar9003_hw_ant_ctrl_chain_get(ah, 0, is2ghz);
1021 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value);
1022
1023 value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz);
1024 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, value);
1025
1026 value = ar9003_hw_ant_ctrl_chain_get(ah, 2, is2ghz);
1027 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, value);
1028}
1029
1030static void ar9003_hw_drive_strength_apply(struct ath_hw *ah)
1031{
1032 int drive_strength;
1033 unsigned long reg;
1034
1035 drive_strength = ath9k_hw_ar9300_get_eeprom(ah, EEP_DRIVE_STRENGTH);
1036
1037 if (!drive_strength)
1038 return;
1039
1040 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS1);
1041 reg &= ~0x00ffffc0;
1042 reg |= 0x5 << 21;
1043 reg |= 0x5 << 18;
1044 reg |= 0x5 << 15;
1045 reg |= 0x5 << 12;
1046 reg |= 0x5 << 9;
1047 reg |= 0x5 << 6;
1048 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS1, reg);
1049
1050 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS2);
1051 reg &= ~0xffffffe0;
1052 reg |= 0x5 << 29;
1053 reg |= 0x5 << 26;
1054 reg |= 0x5 << 23;
1055 reg |= 0x5 << 20;
1056 reg |= 0x5 << 17;
1057 reg |= 0x5 << 14;
1058 reg |= 0x5 << 11;
1059 reg |= 0x5 << 8;
1060 reg |= 0x5 << 5;
1061 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS2, reg);
1062
1063 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS4);
1064 reg &= ~0xff800000;
1065 reg |= 0x5 << 29;
1066 reg |= 0x5 << 26;
1067 reg |= 0x5 << 23;
1068 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS4, reg);
1069}
1070
1071static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
1072{
1073 int internal_regulator =
1074 ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);
1075
1076 if (internal_regulator) {
1077 /* Internal regulator is ON. Write swreg register. */
1078 int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
1079 REG_WRITE(ah, AR_RTC_REG_CONTROL1,
1080 REG_READ(ah, AR_RTC_REG_CONTROL1) &
1081 (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM));
1082 REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg);
1083 /* Set REG_CONTROL1.SWREG_PROGRAM */
1084 REG_WRITE(ah, AR_RTC_REG_CONTROL1,
1085 REG_READ(ah,
1086 AR_RTC_REG_CONTROL1) |
1087 AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
1088 } else {
1089 REG_WRITE(ah, AR_RTC_SLEEP_CLK,
1090 (REG_READ(ah,
1091 AR_RTC_SLEEP_CLK) |
1092 AR_RTC_FORCE_SWREG_PRD));
1093 }
1094}
1095
1096static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
1097 struct ath9k_channel *chan)
1098{
1099 ar9003_hw_xpa_bias_level_apply(ah, IS_CHAN_2GHZ(chan));
1100 ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan));
1101 ar9003_hw_drive_strength_apply(ah);
1102 ar9003_hw_internal_regulator_apply(ah);
1103}
1104
1105static void ath9k_hw_ar9300_set_addac(struct ath_hw *ah,
1106 struct ath9k_channel *chan)
1107{
1108}
1109
1110/*
1111 * Returns the interpolated y value corresponding to the specified x value
1112 * from the np ordered pairs of data (px,py).
1113 * The pairs do not have to be in any order.
1114 * If the specified x value is less than any of the px,
1115 * the returned y value is equal to the py for the lowest px.
1116 * If the specified x value is greater than any of the px,
1117 * the returned y value is equal to the py for the highest px.
1118 */
1119static int ar9003_hw_power_interpolate(int32_t x,
1120 int32_t *px, int32_t *py, u_int16_t np)
1121{
1122 int ip = 0;
1123 int lx = 0, ly = 0, lhave = 0;
1124 int hx = 0, hy = 0, hhave = 0;
1125 int dx = 0;
1126 int y = 0;
1127
1128 lhave = 0;
1129 hhave = 0;
1130
1131 /* identify best lower and higher x calibration measurement */
1132 for (ip = 0; ip < np; ip++) {
1133 dx = x - px[ip];
1134
1135 /* this measurement is higher than our desired x */
1136 if (dx <= 0) {
1137 if (!hhave || dx > (x - hx)) {
1138 /* new best higher x measurement */
1139 hx = px[ip];
1140 hy = py[ip];
1141 hhave = 1;
1142 }
1143 }
1144 /* this measurement is lower than our desired x */
1145 if (dx >= 0) {
1146 if (!lhave || dx < (x - lx)) {
1147 /* new best lower x measurement */
1148 lx = px[ip];
1149 ly = py[ip];
1150 lhave = 1;
1151 }
1152 }
1153 }
1154
1155 /* the low x is good */
1156 if (lhave) {
1157 /* so is the high x */
1158 if (hhave) {
1159 /* they're the same, so just pick one */
1160 if (hx == lx)
1161 y = ly;
1162 else /* interpolate */
1163 y = ly + (((x - lx) * (hy - ly)) / (hx - lx));
1164 } else /* only low is good, use it */
1165 y = ly;
1166 } else if (hhave) /* only high is good, use it */
1167 y = hy;
1168 else /* nothing is good,this should never happen unless np=0, ???? */
1169 y = -(1 << 30);
1170 return y;
1171}
1172
1173static u8 ar9003_hw_eeprom_get_tgt_pwr(struct ath_hw *ah,
1174 u16 rateIndex, u16 freq, bool is2GHz)
1175{
1176 u16 numPiers, i;
1177 s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS];
1178 s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS];
1179 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1180 struct cal_tgt_pow_legacy *pEepromTargetPwr;
1181 u8 *pFreqBin;
1182
1183 if (is2GHz) {
Felix Fietkaud10baf92010-04-26 15:04:38 -04001184 numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001185 pEepromTargetPwr = eep->calTargetPower2G;
1186 pFreqBin = eep->calTarget_freqbin_2G;
1187 } else {
1188 numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
1189 pEepromTargetPwr = eep->calTargetPower5G;
1190 pFreqBin = eep->calTarget_freqbin_5G;
1191 }
1192
1193 /*
1194 * create array of channels and targetpower from
1195 * targetpower piers stored on eeprom
1196 */
1197 for (i = 0; i < numPiers; i++) {
1198 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1199 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1200 }
1201
1202 /* interpolate to get target power for given frequency */
1203 return (u8) ar9003_hw_power_interpolate((s32) freq,
1204 freqArray,
1205 targetPowerArray, numPiers);
1206}
1207
1208static u8 ar9003_hw_eeprom_get_ht20_tgt_pwr(struct ath_hw *ah,
1209 u16 rateIndex,
1210 u16 freq, bool is2GHz)
1211{
1212 u16 numPiers, i;
1213 s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS];
1214 s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS];
1215 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1216 struct cal_tgt_pow_ht *pEepromTargetPwr;
1217 u8 *pFreqBin;
1218
1219 if (is2GHz) {
Felix Fietkaud10baf92010-04-26 15:04:38 -04001220 numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001221 pEepromTargetPwr = eep->calTargetPower2GHT20;
1222 pFreqBin = eep->calTarget_freqbin_2GHT20;
1223 } else {
1224 numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
1225 pEepromTargetPwr = eep->calTargetPower5GHT20;
1226 pFreqBin = eep->calTarget_freqbin_5GHT20;
1227 }
1228
1229 /*
1230 * create array of channels and targetpower
1231 * from targetpower piers stored on eeprom
1232 */
1233 for (i = 0; i < numPiers; i++) {
1234 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1235 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1236 }
1237
1238 /* interpolate to get target power for given frequency */
1239 return (u8) ar9003_hw_power_interpolate((s32) freq,
1240 freqArray,
1241 targetPowerArray, numPiers);
1242}
1243
1244static u8 ar9003_hw_eeprom_get_ht40_tgt_pwr(struct ath_hw *ah,
1245 u16 rateIndex,
1246 u16 freq, bool is2GHz)
1247{
1248 u16 numPiers, i;
1249 s32 targetPowerArray[AR9300_NUM_5G_40_TARGET_POWERS];
1250 s32 freqArray[AR9300_NUM_5G_40_TARGET_POWERS];
1251 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1252 struct cal_tgt_pow_ht *pEepromTargetPwr;
1253 u8 *pFreqBin;
1254
1255 if (is2GHz) {
1256 numPiers = AR9300_NUM_2G_40_TARGET_POWERS;
1257 pEepromTargetPwr = eep->calTargetPower2GHT40;
1258 pFreqBin = eep->calTarget_freqbin_2GHT40;
1259 } else {
1260 numPiers = AR9300_NUM_5G_40_TARGET_POWERS;
1261 pEepromTargetPwr = eep->calTargetPower5GHT40;
1262 pFreqBin = eep->calTarget_freqbin_5GHT40;
1263 }
1264
1265 /*
1266 * create array of channels and targetpower from
1267 * targetpower piers stored on eeprom
1268 */
1269 for (i = 0; i < numPiers; i++) {
1270 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1271 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1272 }
1273
1274 /* interpolate to get target power for given frequency */
1275 return (u8) ar9003_hw_power_interpolate((s32) freq,
1276 freqArray,
1277 targetPowerArray, numPiers);
1278}
1279
1280static u8 ar9003_hw_eeprom_get_cck_tgt_pwr(struct ath_hw *ah,
1281 u16 rateIndex, u16 freq)
1282{
1283 u16 numPiers = AR9300_NUM_2G_CCK_TARGET_POWERS, i;
1284 s32 targetPowerArray[AR9300_NUM_2G_CCK_TARGET_POWERS];
1285 s32 freqArray[AR9300_NUM_2G_CCK_TARGET_POWERS];
1286 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1287 struct cal_tgt_pow_legacy *pEepromTargetPwr = eep->calTargetPowerCck;
1288 u8 *pFreqBin = eep->calTarget_freqbin_Cck;
1289
1290 /*
1291 * create array of channels and targetpower from
1292 * targetpower piers stored on eeprom
1293 */
1294 for (i = 0; i < numPiers; i++) {
1295 freqArray[i] = FBIN2FREQ(pFreqBin[i], 1);
1296 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1297 }
1298
1299 /* interpolate to get target power for given frequency */
1300 return (u8) ar9003_hw_power_interpolate((s32) freq,
1301 freqArray,
1302 targetPowerArray, numPiers);
1303}
1304
1305/* Set tx power registers to array of values passed in */
1306static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
1307{
1308#define POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
1309 /* make sure forced gain is not set */
1310 REG_WRITE(ah, 0xa458, 0);
1311
1312 /* Write the OFDM power per rate set */
1313
1314 /* 6 (LSB), 9, 12, 18 (MSB) */
1315 REG_WRITE(ah, 0xa3c0,
1316 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) |
1317 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 16) |
1318 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) |
1319 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0));
1320
1321 /* 24 (LSB), 36, 48, 54 (MSB) */
1322 REG_WRITE(ah, 0xa3c4,
1323 POW_SM(pPwrArray[ALL_TARGET_LEGACY_54], 24) |
1324 POW_SM(pPwrArray[ALL_TARGET_LEGACY_48], 16) |
1325 POW_SM(pPwrArray[ALL_TARGET_LEGACY_36], 8) |
1326 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0));
1327
1328 /* Write the CCK power per rate set */
1329
1330 /* 1L (LSB), reserved, 2L, 2S (MSB) */
1331 REG_WRITE(ah, 0xa3c8,
1332 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 24) |
1333 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) |
1334 /* POW_SM(txPowerTimes2, 8) | this is reserved for AR9003 */
1335 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0));
1336
1337 /* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */
1338 REG_WRITE(ah, 0xa3cc,
1339 POW_SM(pPwrArray[ALL_TARGET_LEGACY_11S], 24) |
1340 POW_SM(pPwrArray[ALL_TARGET_LEGACY_11L], 16) |
1341 POW_SM(pPwrArray[ALL_TARGET_LEGACY_5S], 8) |
1342 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0)
1343 );
1344
1345 /* Write the HT20 power per rate set */
1346
1347 /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */
1348 REG_WRITE(ah, 0xa3d0,
1349 POW_SM(pPwrArray[ALL_TARGET_HT20_5], 24) |
1350 POW_SM(pPwrArray[ALL_TARGET_HT20_4], 16) |
1351 POW_SM(pPwrArray[ALL_TARGET_HT20_1_3_9_11_17_19], 8) |
1352 POW_SM(pPwrArray[ALL_TARGET_HT20_0_8_16], 0)
1353 );
1354
1355 /* 6 (LSB), 7, 12, 13 (MSB) */
1356 REG_WRITE(ah, 0xa3d4,
1357 POW_SM(pPwrArray[ALL_TARGET_HT20_13], 24) |
1358 POW_SM(pPwrArray[ALL_TARGET_HT20_12], 16) |
1359 POW_SM(pPwrArray[ALL_TARGET_HT20_7], 8) |
1360 POW_SM(pPwrArray[ALL_TARGET_HT20_6], 0)
1361 );
1362
1363 /* 14 (LSB), 15, 20, 21 */
1364 REG_WRITE(ah, 0xa3e4,
1365 POW_SM(pPwrArray[ALL_TARGET_HT20_21], 24) |
1366 POW_SM(pPwrArray[ALL_TARGET_HT20_20], 16) |
1367 POW_SM(pPwrArray[ALL_TARGET_HT20_15], 8) |
1368 POW_SM(pPwrArray[ALL_TARGET_HT20_14], 0)
1369 );
1370
1371 /* Mixed HT20 and HT40 rates */
1372
1373 /* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */
1374 REG_WRITE(ah, 0xa3e8,
1375 POW_SM(pPwrArray[ALL_TARGET_HT40_23], 24) |
1376 POW_SM(pPwrArray[ALL_TARGET_HT40_22], 16) |
1377 POW_SM(pPwrArray[ALL_TARGET_HT20_23], 8) |
1378 POW_SM(pPwrArray[ALL_TARGET_HT20_22], 0)
1379 );
1380
1381 /*
1382 * Write the HT40 power per rate set
1383 * correct PAR difference between HT40 and HT20/LEGACY
1384 * 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB)
1385 */
1386 REG_WRITE(ah, 0xa3d8,
1387 POW_SM(pPwrArray[ALL_TARGET_HT40_5], 24) |
1388 POW_SM(pPwrArray[ALL_TARGET_HT40_4], 16) |
1389 POW_SM(pPwrArray[ALL_TARGET_HT40_1_3_9_11_17_19], 8) |
1390 POW_SM(pPwrArray[ALL_TARGET_HT40_0_8_16], 0)
1391 );
1392
1393 /* 6 (LSB), 7, 12, 13 (MSB) */
1394 REG_WRITE(ah, 0xa3dc,
1395 POW_SM(pPwrArray[ALL_TARGET_HT40_13], 24) |
1396 POW_SM(pPwrArray[ALL_TARGET_HT40_12], 16) |
1397 POW_SM(pPwrArray[ALL_TARGET_HT40_7], 8) |
1398 POW_SM(pPwrArray[ALL_TARGET_HT40_6], 0)
1399 );
1400
1401 /* 14 (LSB), 15, 20, 21 */
1402 REG_WRITE(ah, 0xa3ec,
1403 POW_SM(pPwrArray[ALL_TARGET_HT40_21], 24) |
1404 POW_SM(pPwrArray[ALL_TARGET_HT40_20], 16) |
1405 POW_SM(pPwrArray[ALL_TARGET_HT40_15], 8) |
1406 POW_SM(pPwrArray[ALL_TARGET_HT40_14], 0)
1407 );
1408
1409 return 0;
1410#undef POW_SM
1411}
1412
1413static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq)
1414{
1415 u8 targetPowerValT2[ar9300RateSize];
1416 /* XXX: hard code for now, need to get from eeprom struct */
1417 u8 ht40PowerIncForPdadc = 0;
1418 bool is2GHz = false;
1419 unsigned int i = 0;
1420 struct ath_common *common = ath9k_hw_common(ah);
1421
1422 if (freq < 4000)
1423 is2GHz = true;
1424
1425 targetPowerValT2[ALL_TARGET_LEGACY_6_24] =
1426 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_6_24, freq,
1427 is2GHz);
1428 targetPowerValT2[ALL_TARGET_LEGACY_36] =
1429 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_36, freq,
1430 is2GHz);
1431 targetPowerValT2[ALL_TARGET_LEGACY_48] =
1432 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_48, freq,
1433 is2GHz);
1434 targetPowerValT2[ALL_TARGET_LEGACY_54] =
1435 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_54, freq,
1436 is2GHz);
1437 targetPowerValT2[ALL_TARGET_LEGACY_1L_5L] =
1438 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_1L_5L,
1439 freq);
1440 targetPowerValT2[ALL_TARGET_LEGACY_5S] =
1441 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_5S, freq);
1442 targetPowerValT2[ALL_TARGET_LEGACY_11L] =
1443 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11L, freq);
1444 targetPowerValT2[ALL_TARGET_LEGACY_11S] =
1445 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11S, freq);
1446 targetPowerValT2[ALL_TARGET_HT20_0_8_16] =
1447 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq,
1448 is2GHz);
1449 targetPowerValT2[ALL_TARGET_HT20_1_3_9_11_17_19] =
1450 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19,
1451 freq, is2GHz);
1452 targetPowerValT2[ALL_TARGET_HT20_4] =
1453 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_4, freq,
1454 is2GHz);
1455 targetPowerValT2[ALL_TARGET_HT20_5] =
1456 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_5, freq,
1457 is2GHz);
1458 targetPowerValT2[ALL_TARGET_HT20_6] =
1459 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_6, freq,
1460 is2GHz);
1461 targetPowerValT2[ALL_TARGET_HT20_7] =
1462 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_7, freq,
1463 is2GHz);
1464 targetPowerValT2[ALL_TARGET_HT20_12] =
1465 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_12, freq,
1466 is2GHz);
1467 targetPowerValT2[ALL_TARGET_HT20_13] =
1468 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_13, freq,
1469 is2GHz);
1470 targetPowerValT2[ALL_TARGET_HT20_14] =
1471 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_14, freq,
1472 is2GHz);
1473 targetPowerValT2[ALL_TARGET_HT20_15] =
1474 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_15, freq,
1475 is2GHz);
1476 targetPowerValT2[ALL_TARGET_HT20_20] =
1477 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_20, freq,
1478 is2GHz);
1479 targetPowerValT2[ALL_TARGET_HT20_21] =
1480 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_21, freq,
1481 is2GHz);
1482 targetPowerValT2[ALL_TARGET_HT20_22] =
1483 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_22, freq,
1484 is2GHz);
1485 targetPowerValT2[ALL_TARGET_HT20_23] =
1486 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
1487 is2GHz);
1488 targetPowerValT2[ALL_TARGET_HT40_0_8_16] =
1489 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq,
1490 is2GHz) + ht40PowerIncForPdadc;
1491 targetPowerValT2[ALL_TARGET_HT40_1_3_9_11_17_19] =
1492 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19,
1493 freq,
1494 is2GHz) + ht40PowerIncForPdadc;
1495 targetPowerValT2[ALL_TARGET_HT40_4] =
1496 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_4, freq,
1497 is2GHz) + ht40PowerIncForPdadc;
1498 targetPowerValT2[ALL_TARGET_HT40_5] =
1499 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_5, freq,
1500 is2GHz) + ht40PowerIncForPdadc;
1501 targetPowerValT2[ALL_TARGET_HT40_6] =
1502 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_6, freq,
1503 is2GHz) + ht40PowerIncForPdadc;
1504 targetPowerValT2[ALL_TARGET_HT40_7] =
1505 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_7, freq,
1506 is2GHz) + ht40PowerIncForPdadc;
1507 targetPowerValT2[ALL_TARGET_HT40_12] =
1508 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_12, freq,
1509 is2GHz) + ht40PowerIncForPdadc;
1510 targetPowerValT2[ALL_TARGET_HT40_13] =
1511 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_13, freq,
1512 is2GHz) + ht40PowerIncForPdadc;
1513 targetPowerValT2[ALL_TARGET_HT40_14] =
1514 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_14, freq,
1515 is2GHz) + ht40PowerIncForPdadc;
1516 targetPowerValT2[ALL_TARGET_HT40_15] =
1517 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_15, freq,
1518 is2GHz) + ht40PowerIncForPdadc;
1519 targetPowerValT2[ALL_TARGET_HT40_20] =
1520 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_20, freq,
1521 is2GHz) + ht40PowerIncForPdadc;
1522 targetPowerValT2[ALL_TARGET_HT40_21] =
1523 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_21, freq,
1524 is2GHz) + ht40PowerIncForPdadc;
1525 targetPowerValT2[ALL_TARGET_HT40_22] =
1526 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_22, freq,
1527 is2GHz) + ht40PowerIncForPdadc;
1528 targetPowerValT2[ALL_TARGET_HT40_23] =
1529 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
1530 is2GHz) + ht40PowerIncForPdadc;
1531
1532 while (i < ar9300RateSize) {
1533 ath_print(common, ATH_DBG_EEPROM,
1534 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1535 i++;
1536
1537 ath_print(common, ATH_DBG_EEPROM,
1538 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1539 i++;
1540
1541 ath_print(common, ATH_DBG_EEPROM,
1542 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1543 i++;
1544
1545 ath_print(common, ATH_DBG_EEPROM,
1546 "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
1547 i++;
1548 }
1549
1550 /* Write target power array to registers */
1551 ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
1552}
1553
1554static int ar9003_hw_cal_pier_get(struct ath_hw *ah,
1555 int mode,
1556 int ipier,
1557 int ichain,
1558 int *pfrequency,
1559 int *pcorrection,
1560 int *ptemperature, int *pvoltage)
1561{
1562 u8 *pCalPier;
1563 struct ar9300_cal_data_per_freq_op_loop *pCalPierStruct;
1564 int is2GHz;
1565 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1566 struct ath_common *common = ath9k_hw_common(ah);
1567
1568 if (ichain >= AR9300_MAX_CHAINS) {
1569 ath_print(common, ATH_DBG_EEPROM,
1570 "Invalid chain index, must be less than %d\n",
1571 AR9300_MAX_CHAINS);
1572 return -1;
1573 }
1574
1575 if (mode) { /* 5GHz */
1576 if (ipier >= AR9300_NUM_5G_CAL_PIERS) {
1577 ath_print(common, ATH_DBG_EEPROM,
1578 "Invalid 5GHz cal pier index, must "
1579 "be less than %d\n",
1580 AR9300_NUM_5G_CAL_PIERS);
1581 return -1;
1582 }
1583 pCalPier = &(eep->calFreqPier5G[ipier]);
1584 pCalPierStruct = &(eep->calPierData5G[ichain][ipier]);
1585 is2GHz = 0;
1586 } else {
1587 if (ipier >= AR9300_NUM_2G_CAL_PIERS) {
1588 ath_print(common, ATH_DBG_EEPROM,
1589 "Invalid 2GHz cal pier index, must "
1590 "be less than %d\n", AR9300_NUM_2G_CAL_PIERS);
1591 return -1;
1592 }
1593
1594 pCalPier = &(eep->calFreqPier2G[ipier]);
1595 pCalPierStruct = &(eep->calPierData2G[ichain][ipier]);
1596 is2GHz = 1;
1597 }
1598
1599 *pfrequency = FBIN2FREQ(*pCalPier, is2GHz);
1600 *pcorrection = pCalPierStruct->refPower;
1601 *ptemperature = pCalPierStruct->tempMeas;
1602 *pvoltage = pCalPierStruct->voltMeas;
1603
1604 return 0;
1605}
1606
1607static int ar9003_hw_power_control_override(struct ath_hw *ah,
1608 int frequency,
1609 int *correction,
1610 int *voltage, int *temperature)
1611{
1612 int tempSlope = 0;
1613 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1614
1615 REG_RMW(ah, AR_PHY_TPC_11_B0,
1616 (correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1617 AR_PHY_TPC_OLPC_GAIN_DELTA);
1618 REG_RMW(ah, AR_PHY_TPC_11_B1,
1619 (correction[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1620 AR_PHY_TPC_OLPC_GAIN_DELTA);
1621 REG_RMW(ah, AR_PHY_TPC_11_B2,
1622 (correction[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1623 AR_PHY_TPC_OLPC_GAIN_DELTA);
1624
1625 /* enable open loop power control on chip */
1626 REG_RMW(ah, AR_PHY_TPC_6_B0,
1627 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
1628 AR_PHY_TPC_6_ERROR_EST_MODE);
1629 REG_RMW(ah, AR_PHY_TPC_6_B1,
1630 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
1631 AR_PHY_TPC_6_ERROR_EST_MODE);
1632 REG_RMW(ah, AR_PHY_TPC_6_B2,
1633 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
1634 AR_PHY_TPC_6_ERROR_EST_MODE);
1635
1636 /*
1637 * enable temperature compensation
1638 * Need to use register names
1639 */
1640 if (frequency < 4000)
1641 tempSlope = eep->modalHeader2G.tempSlope;
1642 else
1643 tempSlope = eep->modalHeader5G.tempSlope;
1644
1645 REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope);
1646 REG_RMW_FIELD(ah, AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE,
1647 temperature[0]);
1648
1649 return 0;
1650}
1651
1652/* Apply the recorded correction values. */
1653static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
1654{
1655 int ichain, ipier, npier;
1656 int mode;
1657 int lfrequency[AR9300_MAX_CHAINS],
1658 lcorrection[AR9300_MAX_CHAINS],
1659 ltemperature[AR9300_MAX_CHAINS], lvoltage[AR9300_MAX_CHAINS];
1660 int hfrequency[AR9300_MAX_CHAINS],
1661 hcorrection[AR9300_MAX_CHAINS],
1662 htemperature[AR9300_MAX_CHAINS], hvoltage[AR9300_MAX_CHAINS];
1663 int fdiff;
1664 int correction[AR9300_MAX_CHAINS],
1665 voltage[AR9300_MAX_CHAINS], temperature[AR9300_MAX_CHAINS];
1666 int pfrequency, pcorrection, ptemperature, pvoltage;
1667 struct ath_common *common = ath9k_hw_common(ah);
1668
1669 mode = (frequency >= 4000);
1670 if (mode)
1671 npier = AR9300_NUM_5G_CAL_PIERS;
1672 else
1673 npier = AR9300_NUM_2G_CAL_PIERS;
1674
1675 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1676 lfrequency[ichain] = 0;
1677 hfrequency[ichain] = 100000;
1678 }
1679 /* identify best lower and higher frequency calibration measurement */
1680 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1681 for (ipier = 0; ipier < npier; ipier++) {
1682 if (!ar9003_hw_cal_pier_get(ah, mode, ipier, ichain,
1683 &pfrequency, &pcorrection,
1684 &ptemperature, &pvoltage)) {
1685 fdiff = frequency - pfrequency;
1686
1687 /*
1688 * this measurement is higher than
1689 * our desired frequency
1690 */
1691 if (fdiff <= 0) {
1692 if (hfrequency[ichain] <= 0 ||
1693 hfrequency[ichain] >= 100000 ||
1694 fdiff >
1695 (frequency - hfrequency[ichain])) {
1696 /*
1697 * new best higher
1698 * frequency measurement
1699 */
1700 hfrequency[ichain] = pfrequency;
1701 hcorrection[ichain] =
1702 pcorrection;
1703 htemperature[ichain] =
1704 ptemperature;
1705 hvoltage[ichain] = pvoltage;
1706 }
1707 }
1708 if (fdiff >= 0) {
1709 if (lfrequency[ichain] <= 0
1710 || fdiff <
1711 (frequency - lfrequency[ichain])) {
1712 /*
1713 * new best lower
1714 * frequency measurement
1715 */
1716 lfrequency[ichain] = pfrequency;
1717 lcorrection[ichain] =
1718 pcorrection;
1719 ltemperature[ichain] =
1720 ptemperature;
1721 lvoltage[ichain] = pvoltage;
1722 }
1723 }
1724 }
1725 }
1726 }
1727
1728 /* interpolate */
1729 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1730 ath_print(common, ATH_DBG_EEPROM,
1731 "ch=%d f=%d low=%d %d h=%d %d\n",
1732 ichain, frequency, lfrequency[ichain],
1733 lcorrection[ichain], hfrequency[ichain],
1734 hcorrection[ichain]);
1735 /* they're the same, so just pick one */
1736 if (hfrequency[ichain] == lfrequency[ichain]) {
1737 correction[ichain] = lcorrection[ichain];
1738 voltage[ichain] = lvoltage[ichain];
1739 temperature[ichain] = ltemperature[ichain];
1740 }
1741 /* the low frequency is good */
1742 else if (frequency - lfrequency[ichain] < 1000) {
1743 /* so is the high frequency, interpolate */
1744 if (hfrequency[ichain] - frequency < 1000) {
1745
1746 correction[ichain] = lcorrection[ichain] +
1747 (((frequency - lfrequency[ichain]) *
1748 (hcorrection[ichain] -
1749 lcorrection[ichain])) /
1750 (hfrequency[ichain] - lfrequency[ichain]));
1751
1752 temperature[ichain] = ltemperature[ichain] +
1753 (((frequency - lfrequency[ichain]) *
1754 (htemperature[ichain] -
1755 ltemperature[ichain])) /
1756 (hfrequency[ichain] - lfrequency[ichain]));
1757
1758 voltage[ichain] =
1759 lvoltage[ichain] +
1760 (((frequency -
1761 lfrequency[ichain]) * (hvoltage[ichain] -
1762 lvoltage[ichain]))
1763 / (hfrequency[ichain] -
1764 lfrequency[ichain]));
1765 }
1766 /* only low is good, use it */
1767 else {
1768 correction[ichain] = lcorrection[ichain];
1769 temperature[ichain] = ltemperature[ichain];
1770 voltage[ichain] = lvoltage[ichain];
1771 }
1772 }
1773 /* only high is good, use it */
1774 else if (hfrequency[ichain] - frequency < 1000) {
1775 correction[ichain] = hcorrection[ichain];
1776 temperature[ichain] = htemperature[ichain];
1777 voltage[ichain] = hvoltage[ichain];
1778 } else { /* nothing is good, presume 0???? */
1779 correction[ichain] = 0;
1780 temperature[ichain] = 0;
1781 voltage[ichain] = 0;
1782 }
1783 }
1784
1785 ar9003_hw_power_control_override(ah, frequency, correction, voltage,
1786 temperature);
1787
1788 ath_print(common, ATH_DBG_EEPROM,
1789 "for frequency=%d, calibration correction = %d %d %d\n",
1790 frequency, correction[0], correction[1], correction[2]);
1791
1792 return 0;
1793}
1794
1795static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
1796 struct ath9k_channel *chan, u16 cfgCtl,
1797 u8 twiceAntennaReduction,
1798 u8 twiceMaxRegulatoryPower,
1799 u8 powerLimit)
1800{
Felix Fietkau597a94b2010-04-26 15:04:37 -04001801 ah->txpower_limit = powerLimit;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001802 ar9003_hw_set_target_power_eeprom(ah, chan->channel);
1803 ar9003_hw_calibration_apply(ah, chan->channel);
1804}
1805
1806static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah,
1807 u16 i, bool is2GHz)
1808{
1809 return AR_NO_SPUR;
1810}
1811
Luis R. Rodriguezc14a85d2010-04-15 17:39:21 -04001812s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah)
1813{
1814 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1815
1816 return (eep->baseEepHeader.txrxgain >> 4) & 0xf; /* bits 7:4 */
1817}
1818
1819s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah)
1820{
1821 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1822
1823 return (eep->baseEepHeader.txrxgain) & 0xf; /* bits 3:0 */
1824}
1825
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001826const struct eeprom_ops eep_ar9300_ops = {
1827 .check_eeprom = ath9k_hw_ar9300_check_eeprom,
1828 .get_eeprom = ath9k_hw_ar9300_get_eeprom,
1829 .fill_eeprom = ath9k_hw_ar9300_fill_eeprom,
1830 .get_eeprom_ver = ath9k_hw_ar9300_get_eeprom_ver,
1831 .get_eeprom_rev = ath9k_hw_ar9300_get_eeprom_rev,
1832 .get_num_ant_config = ath9k_hw_ar9300_get_num_ant_config,
1833 .get_eeprom_antenna_cfg = ath9k_hw_ar9300_get_eeprom_antenna_cfg,
1834 .set_board_values = ath9k_hw_ar9300_set_board_values,
1835 .set_addac = ath9k_hw_ar9300_set_addac,
1836 .set_txpower = ath9k_hw_ar9300_set_txpower,
1837 .get_spur_channel = ath9k_hw_ar9300_get_spur_channel
1838};