1 /*
2 * Copyright (c) 2013 Qualcomm Atheros, 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 WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
17
18 #include "opt_ah.h"
19
20 #ifdef AH_SUPPORT_AR9300
21
22 #include "ah.h"
23 #include "ah_internal.h"
24
25 #include "ar9300/ar9300.h"
26 #include "ar9300/ar9300reg.h"
27 #include "ar9300/ar9300phy.h"
28
29 #if ATH_SUPPORT_AIC
30
31 #define ATH_AIC_TEST_PATTERN 1
32
33 struct ath_aic_sram_info {
34 HAL_BOOL valid;
35 u_int8_t rot_quad_att_db;
36 HAL_BOOL vga_quad_sign;
37 u_int8_t rot_dir_att_db;
38 HAL_BOOL vga_dir_sign;
39 u_int8_t com_att_6db;
40 };
41
42 struct ath_aic_out_info {
43 int16_t dir_path_gain_lin;
44 int16_t quad_path_gain_lin;
45 struct ath_aic_sram_info sram;
46 };
47
48 #define ATH_AIC_MAX_COM_ATT_DB_TABLE 6
49 #define ATH_AIC_MAX_AIC_LIN_TABLE 69
50 #define ATH_AIC_MIN_ROT_DIR_ATT_DB 0
51 #define ATH_AIC_MIN_ROT_QUAD_ATT_DB 0
52 #define ATH_AIC_MAX_ROT_DIR_ATT_DB 37
53 #define ATH_AIC_MAX_ROT_QUAD_ATT_DB 37
54 #define ATH_AIC_SRAM_AUTO_INCREMENT 0x80000000
55 #define ATH_AIC_SRAM_GAIN_TABLE_OFFSET 0x280
56 #define ATH_AIC_SRAM_CAL_OFFSET 0x140
57 #define ATH_AIC_MAX_CAL_COUNT 5
58 #define ATH_AIC_MEAS_MAG_THRESH 20
59 #define ATH_AIC_BT_JUPITER_CTRL 0x66820
60 #define ATH_AIC_BT_AIC_ENABLE 0x02
61
62
63 static const u_int8_t com_att_db_table[ATH_AIC_MAX_COM_ATT_DB_TABLE] = {
64 0, 3, 9, 15, 21, 27};
65
66 static const u_int16_t aic_lin_table[ATH_AIC_MAX_AIC_LIN_TABLE] = {
67 8191, 7300, 6506, 5799, 5168, 4606, 4105, 3659,
68 3261, 2906, 2590, 2309, 2057, 1834, 1634, 1457,
69 1298, 1157, 1031, 919, 819, 730, 651, 580,
70 517, 461, 411, 366, 326, 291, 259, 231,
71 206, 183, 163, 146, 130, 116, 103, 92,
72 82, 73, 65, 58, 52, 46, 41, 37,
73 33, 29, 26, 23, 21, 18, 16, 15,
74 13, 12, 10, 9, 8, 7, 7, 6,
75 5, 5, 4, 4, 3};
76
77 #if ATH_AIC_TEST_PATTERN
78 static const u_int32_t aic_test_pattern[ATH_AIC_MAX_BT_CHANNEL] = {
79 0x00000, // 0
80 0x00000,
81 0x00000,
82 0x00000,
83 0x00000,
84 0x00000,
85 0x00000,
86 0x00000,
87 0x00000,
88 0x1918d,
89 0x1938d, // 10
90 0x00000,
91 0x1978d,
92 0x19e8d,
93 0x00000,
94 0x00000,
95 0x00000,
96 0x00000,
97 0x00000,
98 0x00000,
99 0x00000, // 20
100 0x00000,
101 0x00000,
102 0x1ce8f,
103 0x00000,
104 0x00000,
105 0x00000,
106 0x00000,
107 0x1ca93,
108 0x1c995,
109 0x00000, // 30
110 0x1c897,
111 0x1c899,
112 0x00000,
113 0x00000,
114 0x1c79f,
115 0x00000,
116 0x1c7a5,
117 0x1c6ab,
118 0x00000,
119 0x00000, // 40
120 0x00000,
121 0x00000,
122 0x1c63f,
123 0x00000,
124 0x1c52b,
125 0x1c525,
126 0x1c523,
127 0x00000,
128 0x00000,
129 0x00000, // 50
130 0x00000,
131 0x00000,
132 0x1c617,
133 0x00000,
134 0x1c615,
135 0x1c613,
136 0x00000,
137 0x00000,
138 0x00000,
139 0x00000, // 60
140 0x1c80f,
141 0x1c90f,
142 0x1c90f,
143 0x1ca0f,
144 0x1ca0d,
145 0x1cb0d,
146 0x00000,
147 0x00000,
148 0x00000,
149 0x00000, // 70
150 0x1d00d,
151 0x00000,
152 0x00000,
153 0x00000,
154 0x00000,
155 0x00000,
156 0x00000,
157 0x00000
158 };
159 #endif
160
161 static void
ar9300_aic_gain_table(struct ath_hal * ah)162 ar9300_aic_gain_table(struct ath_hal *ah)
163 {
164 u_int32_t aic_atten_word[19], i;
165
166 /* Program gain table */
167 aic_atten_word[0] = (0x1 & 0xf)<<14 | (0x1f & 0x1f)<<9 | (0x0 & 0xf)<<5 |
168 (0x1f & 0x1f); // -01 dB: 4'd1, 5'd31, 00 dB: 4'd0, 5'd31;
169 aic_atten_word[1] = (0x3 & 0xf)<<14 | (0x1f & 0x1f)<<9 | (0x2 & 0xf)<<5 |
170 (0x1f & 0x1f); // -03 dB: 4'd3, 5'd31, -02 dB: 4'd2, 5'd31;
171 aic_atten_word[2] = (0x5 & 0xf)<<14 | (0x1f & 0x1f)<<9 | (0x4 & 0xf)<<5 |
172 (0x1f & 0x1f); // -05 dB: 4'd5, 5'd31, -04 dB: 4'd4, 5'd31;
173 aic_atten_word[3] = (0x1 & 0xf)<<14 | (0x1e & 0x1f)<<9 | (0x0 & 0xf)<<5 |
174 (0x1e & 0x1f); // -07 dB: 4'd1, 5'd30, -06 dB: 4'd0, 5'd30;
175 aic_atten_word[4] = (0x3 & 0xf)<<14 | (0x1e & 0x1f)<<9 | (0x2 & 0xf)<<5 |
176 (0x1e & 0x1f); // -09 dB: 4'd3, 5'd30, -08 dB: 4'd2, 5'd30;
177 aic_atten_word[5] = (0x5 & 0xf)<<14 | (0x1e & 0x1f)<<9 | (0x4 & 0xf)<<5 |
178 (0x1e & 0x1f); // -11 dB: 4'd5, 5'd30, -10 dB: 4'd4, 5'd30;
179 aic_atten_word[6] = (0x1 & 0xf)<<14 | (0xf & 0x1f)<<9 | (0x0 & 0xf)<<5 |
180 (0xf & 0x1f); // -13 dB: 4'd1, 5'd15, -12 dB: 4'd0, 5'd15;
181 aic_atten_word[7] = (0x3 & 0xf)<<14 | (0xf & 0x1f)<<9 | (0x2 & 0xf)<<5 |
182 (0xf & 0x1f); // -15 dB: 4'd3, 5'd15, -14 dB: 4'd2, 5'd15;
183 aic_atten_word[8] = (0x5 & 0xf)<<14 | (0xf & 0x1f)<<9 | (0x4 & 0xf)<<5 |
184 (0xf & 0x1f); // -17 dB: 4'd5, 5'd15, -16 dB: 4'd4, 5'd15;
185 aic_atten_word[9] = (0x1 & 0xf)<<14 | (0x7 & 0x1f)<<9 | (0x0 & 0xf)<<5 |
186 (0x7 & 0x1f); // -19 dB: 4'd1, 5'd07, -18 dB: 4'd0, 5'd07;
187 aic_atten_word[10] =(0x3 & 0xf)<<14 | (0x7 & 0x1f)<<9 | (0x2 & 0xf)<<5 |
188 (0x7 & 0x1f); // -21 dB: 4'd3, 5'd07, -20 dB: 4'd2, 5'd07;
189 aic_atten_word[11] =(0x5 & 0xf)<<14 | (0x7 & 0x1f)<<9 | (0x4 & 0xf)<<5 |
190 (0x7 & 0x1f); // -23 dB: 4'd5, 5'd07, -22 dB: 4'd4, 5'd07;
191 aic_atten_word[12] =(0x7 & 0xf)<<14 | (0x7 & 0x1f)<<9 | (0x6 & 0xf)<<5 |
192 (0x7 & 0x1f); // -25 dB: 4'd7, 5'd07, -24 dB: 4'd6, 5'd07;
193 aic_atten_word[13] =(0x3 & 0xf)<<14 | (0x3 & 0x1f)<<9 | (0x2 & 0xf)<<5 |
194 (0x3 & 0x1f); // -27 dB: 4'd3, 5'd03, -26 dB: 4'd2, 5'd03;
195 aic_atten_word[14] =(0x5 & 0xf)<<14 | (0x3 & 0x1f)<<9 | (0x4 & 0xf)<<5 |
196 (0x3 & 0x1f); // -29 dB: 4'd5, 5'd03, -28 dB: 4'd4, 5'd03;
197 aic_atten_word[15] =(0x1 & 0xf)<<14 | (0x1 & 0x1f)<<9 | (0x0 & 0xf)<<5 |
198 (0x1 & 0x1f); // -31 dB: 4'd1, 5'd01, -30 dB: 4'd0, 5'd01;
199 aic_atten_word[16] =(0x3 & 0xf)<<14 | (0x1 & 0x1f)<<9 | (0x2 & 0xf)<<5 |
200 (0x1 & 0x1f); // -33 dB: 4'd3, 5'd01, -32 dB: 4'd2, 5'd01;
201 aic_atten_word[17] =(0x5 & 0xf)<<14 | (0x1 & 0x1f)<<9 | (0x4 & 0xf)<<5 |
202 (0x1 & 0x1f); // -35 dB: 4'd5, 5'd01, -34 dB: 4'd4, 5'd01;
203 aic_atten_word[18] =(0x7 & 0xf)<<14 | (0x1 & 0x1f)<<9 | (0x6 & 0xf)<<5 |
204 (0x1 & 0x1f); // -37 dB: 4'd7, 5'd01, -36 dB: 4'd6, 5'd01;
205
206 /* Write to Gain table with auto increment enabled. */
207 OS_REG_WRITE(ah, (AR_PHY_AIC_SRAM_ADDR_B0 + 0x3000),
208 (ATH_AIC_SRAM_AUTO_INCREMENT |
209 ATH_AIC_SRAM_GAIN_TABLE_OFFSET));
210
211 for (i = 0; i < 19; i++) {
212 OS_REG_WRITE(ah, (AR_PHY_AIC_SRAM_DATA_B0 + 0x3000),
213 aic_atten_word[i]);
214 }
215
216 }
217
218 static int16_t
ar9300_aic_find_valid(struct ath_aic_sram_info * cal_sram,HAL_BOOL dir,u_int8_t index)219 ar9300_aic_find_valid (struct ath_aic_sram_info *cal_sram,
220 HAL_BOOL dir,
221 u_int8_t index)
222 {
223 int16_t i;
224
225 if (dir) {
226 /* search forward */
227 for (i = index + 1; i < ATH_AIC_MAX_BT_CHANNEL; i++) {
228 if (cal_sram[i].valid) {
229 break;
230 }
231 }
232 }
233 else {
234 /* search backword */
235 for (i = index - 1; i >= 0; i--) {
236 if (cal_sram[i].valid) {
237 break;
238 }
239 }
240 }
241 if ((i >= ATH_AIC_MAX_BT_CHANNEL) || (i < 0)) {
242 i = -1;
243 }
244
245 return i;
246 }
247
248 static int16_t
ar9300_aic_find_index(u_int8_t type,int16_t value)249 ar9300_aic_find_index (u_int8_t type, int16_t value)
250 {
251 int16_t i = -1;
252
253 /*
254 * type 0: aic_lin_table, 1: com_att_db_table
255 */
256
257 if (type == 0) {
258 /* Find in aic_lin_table */
259 for (i = ATH_AIC_MAX_AIC_LIN_TABLE - 1; i >= 0; i--) {
260 if (aic_lin_table[i] >= value) {
261 break;
262 }
263 }
264 }
265 else if (type == 1) {
266 /* find in com_att_db_table */
267 for (i = 0; i < ATH_AIC_MAX_COM_ATT_DB_TABLE; i++) {
268 if (com_att_db_table[i] > value) {
269 i--;
270 break;
271 }
272 }
273 if (i >= ATH_AIC_MAX_COM_ATT_DB_TABLE) {
274 i = -1;
275 }
276 }
277
278 return i;
279 }
280
281 static HAL_BOOL
ar9300_aic_cal_post_process(struct ath_hal * ah)282 ar9300_aic_cal_post_process (struct ath_hal *ah)
283 {
284 struct ath_hal_9300 *ahp = AH9300(ah);
285 struct ath_aic_sram_info cal_sram[ATH_AIC_MAX_BT_CHANNEL];
286 struct ath_aic_out_info aic_sram[ATH_AIC_MAX_BT_CHANNEL];
287 u_int32_t dir_path_gain_idx, quad_path_gain_idx, value;
288 u_int32_t fixed_com_att_db;
289 int8_t dir_path_sign, quad_path_sign;
290 int16_t i;
291 HAL_BOOL ret = AH_TRUE;
292
293 /* Read CAL_SRAM and get valid values. */
294 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(AIC) CAL_SRAM:\n");
295
296 for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) {
297 OS_REG_WRITE(ah, AR_PHY_AIC_SRAM_ADDR_B1,
298 (ATH_AIC_SRAM_CAL_OFFSET + i*4));
299 #if ATH_AIC_TEST_PATTERN
300 value = aic_test_pattern[i];
301 #else
302 value = OS_REG_READ(ah, AR_PHY_AIC_SRAM_DATA_B1);
303 #endif
304 cal_sram[i].valid = MS(value, AR_PHY_AIC_SRAM_VALID);
305 cal_sram[i].rot_quad_att_db = MS(value,
306 AR_PHY_AIC_SRAM_ROT_QUAD_ATT_DB);
307 cal_sram[i].vga_quad_sign = MS(value, AR_PHY_AIC_SRAM_VGA_QUAD_SIGN);
308 cal_sram[i].rot_dir_att_db = MS(value, AR_PHY_AIC_SRAM_ROT_DIR_ATT_DB);
309 cal_sram[i].vga_dir_sign = MS(value, AR_PHY_AIC_SRAM_VGA_DIR_SIGN);
310 cal_sram[i].com_att_6db = MS(value, AR_PHY_AIC_SRAM_COM_ATT_6DB);
311
312 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
313 "(AIC) %2d %2d %2d %2d %2d %2d %2d 0x%05x\n",
314 i, cal_sram[i].vga_quad_sign,
315 cal_sram[i].vga_dir_sign,
316 cal_sram[i].rot_dir_att_db,
317 cal_sram[i].rot_quad_att_db,
318 cal_sram[i].com_att_6db,
319 cal_sram[i].valid,
320 value);
321
322 if (cal_sram[i].valid) {
323 dir_path_gain_idx = cal_sram[i].rot_dir_att_db +
324 com_att_db_table[cal_sram[i].com_att_6db];
325 quad_path_gain_idx = cal_sram[i].rot_quad_att_db +
326 com_att_db_table[cal_sram[i].com_att_6db];
327 dir_path_sign = (cal_sram[i].vga_dir_sign) ? 1 : -1;
328 quad_path_sign = (cal_sram[i].vga_quad_sign) ? 1 : -1;
329 aic_sram[i].dir_path_gain_lin = dir_path_sign *
330 aic_lin_table[dir_path_gain_idx];
331 aic_sram[i].quad_path_gain_lin = quad_path_sign *
332 aic_lin_table[quad_path_gain_idx];
333 }
334 }
335
336 for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) {
337 int16_t start_idx, end_idx;
338
339 if (cal_sram[i].valid) {
340 continue;
341 }
342
343 start_idx = ar9300_aic_find_valid(cal_sram, 0, i);
344 end_idx = ar9300_aic_find_valid(cal_sram, 1, i);
345
346 if (start_idx < 0)
347 {
348 /* extrapolation */
349 start_idx = end_idx;
350 end_idx = ar9300_aic_find_valid(cal_sram, 1, start_idx);
351
352 if (end_idx < 0) {
353 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
354 "(AIC) Error (1): i = %d, start_idx = %d \n",
355 i, start_idx);
356 ret = AH_FALSE;
357 break;
358 }
359 aic_sram[i].dir_path_gain_lin =
360 ((aic_sram[start_idx].dir_path_gain_lin -
361 aic_sram[end_idx].dir_path_gain_lin) *
362 (start_idx - i) + ((end_idx - i) >> 1)) /
363 (end_idx - i) +
364 aic_sram[start_idx].dir_path_gain_lin;
365 aic_sram[i].quad_path_gain_lin =
366 ((aic_sram[start_idx].quad_path_gain_lin -
367 aic_sram[end_idx].quad_path_gain_lin) *
368 (start_idx - i) + ((end_idx - i) >> 1)) /
369 (end_idx - i) +
370 aic_sram[start_idx].quad_path_gain_lin;
371 }
372 if (end_idx < 0)
373 {
374 /* extrapolation */
375 end_idx = ar9300_aic_find_valid(cal_sram, 0, start_idx);
376
377 if (end_idx < 0) {
378 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
379 "(AIC) Error (2): i = %d, start_idx = %d\n",
380 i, start_idx);
381 ret = AH_FALSE;
382 break;
383 }
384 aic_sram[i].dir_path_gain_lin =
385 ((aic_sram[start_idx].dir_path_gain_lin -
386 aic_sram[end_idx].dir_path_gain_lin) *
387 (i - start_idx) + ((start_idx - end_idx) >> 1)) /
388 (start_idx - end_idx) +
389 aic_sram[start_idx].dir_path_gain_lin;
390 aic_sram[i].quad_path_gain_lin =
391 ((aic_sram[start_idx].quad_path_gain_lin -
392 aic_sram[end_idx].quad_path_gain_lin) *
393 (i - start_idx) + ((start_idx - end_idx) >> 1)) /
394 (start_idx - end_idx) +
395 aic_sram[start_idx].quad_path_gain_lin;
396
397 }
398 else {
399 /* interpolation */
400 aic_sram[i].dir_path_gain_lin =
401 (((end_idx - i) * aic_sram[start_idx].dir_path_gain_lin) +
402 ((i - start_idx) * aic_sram[end_idx].dir_path_gain_lin) +
403 ((end_idx - start_idx) >> 1)) /
404 (end_idx - start_idx);
405 aic_sram[i].quad_path_gain_lin =
406 (((end_idx - i) * aic_sram[start_idx].quad_path_gain_lin) +
407 ((i - start_idx) * aic_sram[end_idx].quad_path_gain_lin) +
408 ((end_idx - start_idx) >> 1))/
409 (end_idx - start_idx);
410 }
411 }
412
413 /* From dir/quad_path_gain_lin to sram. */
414 i = ar9300_aic_find_valid(cal_sram, 1, 0);
415 if (i < 0) {
416 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
417 "(AIC) Error (3): can't find valid. Force it to 0.\n");
418 i = 0;
419 ret = AH_FALSE;
420 }
421 fixed_com_att_db = com_att_db_table[cal_sram[i].com_att_6db];
422
423 for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) {
424 int16_t rot_dir_path_att_db, rot_quad_path_att_db;
425
426 aic_sram[i].sram.vga_dir_sign = (aic_sram[i].dir_path_gain_lin >= 0)
427 ? 1 : 0;
428 aic_sram[i].sram.vga_quad_sign= (aic_sram[i].quad_path_gain_lin >= 0)
429 ? 1 : 0;
430
431 rot_dir_path_att_db =
432 ar9300_aic_find_index(0, abs(aic_sram[i].dir_path_gain_lin)) -
433 fixed_com_att_db;
434 rot_quad_path_att_db =
435 ar9300_aic_find_index(0, abs(aic_sram[i].quad_path_gain_lin)) -
436 fixed_com_att_db;
437
438 aic_sram[i].sram.com_att_6db = ar9300_aic_find_index(1,
439 fixed_com_att_db);
440
441 aic_sram[i].sram.valid = 1;
442 aic_sram[i].sram.rot_dir_att_db =
443 MIN(MAX(rot_dir_path_att_db, ATH_AIC_MIN_ROT_DIR_ATT_DB),
444 ATH_AIC_MAX_ROT_DIR_ATT_DB);
445 aic_sram[i].sram.rot_quad_att_db =
446 MIN(MAX(rot_quad_path_att_db, ATH_AIC_MIN_ROT_QUAD_ATT_DB),
447 ATH_AIC_MAX_ROT_QUAD_ATT_DB);
448 }
449
450 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(AIC) Post processing results:\n");
451
452 for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) {
453 ahp->ah_aic_sram[i] = (SM(aic_sram[i].sram.vga_dir_sign,
454 AR_PHY_AIC_SRAM_VGA_DIR_SIGN) |
455 SM(aic_sram[i].sram.vga_quad_sign,
456 AR_PHY_AIC_SRAM_VGA_QUAD_SIGN) |
457 SM(aic_sram[i].sram.com_att_6db,
458 AR_PHY_AIC_SRAM_COM_ATT_6DB) |
459 SM(aic_sram[i].sram.valid,
460 AR_PHY_AIC_SRAM_VALID) |
461 SM(aic_sram[i].sram.rot_dir_att_db,
462 AR_PHY_AIC_SRAM_ROT_DIR_ATT_DB) |
463 SM(aic_sram[i].sram.rot_quad_att_db,
464 AR_PHY_AIC_SRAM_ROT_QUAD_ATT_DB));
465
466
467 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
468 "(AIC) ch%02d 0x%05x %2d %2d %2d %2d %2d %2d %d %d\n",
469 i,
470 ahp->ah_aic_sram[i],
471 aic_sram[i].sram.vga_quad_sign,
472 aic_sram[i].sram.vga_dir_sign,
473 aic_sram[i].sram.rot_dir_att_db,
474 aic_sram[i].sram.rot_quad_att_db,
475 aic_sram[i].sram.com_att_6db,
476 aic_sram[i].sram.valid,
477 aic_sram[i].dir_path_gain_lin,
478 aic_sram[i].quad_path_gain_lin);
479 }
480
481 return ret;
482 }
483
484 u_int32_t
ar9300_aic_calibration(struct ath_hal * ah)485 ar9300_aic_calibration(struct ath_hal *ah)
486 {
487 u_int32_t aic_ctrl_b0[5], aic_ctrl_b1[5];
488 u_int32_t aic_stat_b0[2], aic_stat_b1[2];
489 u_int32_t aic_stat, value;
490 u_int32_t i, cal_count = ATH_AIC_MAX_CAL_COUNT;
491 struct ath_hal_9300 *ahp = AH9300(ah);
492
493 if (AR_SREV_JUPITER_10(ah)) {
494 aic_ctrl_b0[0] = AR_PHY_AIC_CTRL_0_B0_10;
495 aic_ctrl_b0[1] = AR_PHY_AIC_CTRL_1_B0_10;
496 aic_ctrl_b0[2] = AR_PHY_AIC_CTRL_2_B0_10;
497 aic_ctrl_b0[3] = AR_PHY_AIC_CTRL_3_B0_10;
498 aic_ctrl_b1[0] = AR_PHY_AIC_CTRL_0_B1_10;
499 aic_ctrl_b1[1] = AR_PHY_AIC_CTRL_1_B1_10;
500 aic_stat_b0[0] = AR_PHY_AIC_STAT_0_B0_10;
501 aic_stat_b0[1] = AR_PHY_AIC_STAT_1_B0_10;
502 aic_stat_b1[0] = AR_PHY_AIC_STAT_0_B1_10;
503 aic_stat_b1[1] = AR_PHY_AIC_STAT_1_B1_10;
504 }
505 else {
506 aic_ctrl_b0[0] = AR_PHY_AIC_CTRL_0_B0_20;
507 aic_ctrl_b0[1] = AR_PHY_AIC_CTRL_1_B0_20;
508 aic_ctrl_b0[2] = AR_PHY_AIC_CTRL_2_B0_20;
509 aic_ctrl_b0[3] = AR_PHY_AIC_CTRL_3_B0_20;
510 aic_ctrl_b0[4] = AR_PHY_AIC_CTRL_4_B0_20;
511 aic_ctrl_b1[0] = AR_PHY_AIC_CTRL_0_B1_20;
512 aic_ctrl_b1[1] = AR_PHY_AIC_CTRL_1_B1_20;
513 aic_ctrl_b1[4] = AR_PHY_AIC_CTRL_4_B1_20;
514 aic_stat_b0[0] = AR_PHY_AIC_STAT_0_B0_20;
515 aic_stat_b0[1] = AR_PHY_AIC_STAT_1_B0_20;
516 aic_stat_b1[0] = AR_PHY_AIC_STAT_0_B1_20;
517 aic_stat_b1[1] = AR_PHY_AIC_STAT_1_B1_20;
518 }
519
520 /* Config LNA gain difference */
521 OS_REG_WRITE(ah, AR_PHY_BT_COEX_4, 0x22180600);
522 OS_REG_WRITE(ah, AR_PHY_BT_COEX_5, 0x52443a2e);
523
524 OS_REG_WRITE(ah, aic_ctrl_b0[0],
525 (SM(0, AR_PHY_AIC_MON_ENABLE) |
526 SM(40, AR_PHY_AIC_CAL_MAX_HOP_COUNT) |
527 SM(1, AR_PHY_AIC_CAL_MIN_VALID_COUNT) | //26
528 SM(37, AR_PHY_AIC_F_WLAN) |
529 SM(1, AR_PHY_AIC_CAL_CH_VALID_RESET) |
530 SM(0, AR_PHY_AIC_CAL_ENABLE) |
531 SM(0x40, AR_PHY_AIC_BTTX_PWR_THR) |
532 SM(0, AR_PHY_AIC_ENABLE)));
533
534 OS_REG_WRITE(ah, aic_ctrl_b1[0],
535 (SM(0, AR_PHY_AIC_MON_ENABLE) |
536 SM(1, AR_PHY_AIC_CAL_CH_VALID_RESET) |
537 SM(0, AR_PHY_AIC_CAL_ENABLE) |
538 SM(0x40, AR_PHY_AIC_BTTX_PWR_THR) |
539 SM(0, AR_PHY_AIC_ENABLE)));
540
541 OS_REG_WRITE(ah, aic_ctrl_b0[1],
542 (SM(8, AR_PHY_AIC_CAL_BT_REF_DELAY) |
543 SM(6, AR_PHY_AIC_CAL_ROT_ATT_DB_EST_ISO) |
544 SM(3, AR_PHY_AIC_CAL_COM_ATT_DB_EST_ISO) |
545 SM(0, AR_PHY_AIC_BT_IDLE_CFG) |
546 SM(1, AR_PHY_AIC_STDBY_COND) |
547 SM(37, AR_PHY_AIC_STDBY_ROT_ATT_DB) |
548 SM(5, AR_PHY_AIC_STDBY_COM_ATT_DB) |
549 SM(15, AR_PHY_AIC_RSSI_MAX) |
550 SM(0, AR_PHY_AIC_RSSI_MIN)));
551
552 OS_REG_WRITE(ah, aic_ctrl_b1[1],
553 (SM(6, AR_PHY_AIC_CAL_ROT_ATT_DB_EST_ISO) |
554 SM(3, AR_PHY_AIC_CAL_COM_ATT_DB_EST_ISO) |
555 SM(15, AR_PHY_AIC_RSSI_MAX) |
556 SM(0, AR_PHY_AIC_RSSI_MIN)));
557
558 OS_REG_WRITE(ah, aic_ctrl_b0[2],
559 (SM(44, AR_PHY_AIC_RADIO_DELAY) |
560 SM(7, AR_PHY_AIC_CAL_STEP_SIZE_CORR) |
561 SM(12, AR_PHY_AIC_CAL_ROT_IDX_CORR) |
562 SM(2, AR_PHY_AIC_CAL_CONV_CHECK_FACTOR) |
563 SM(5, AR_PHY_AIC_ROT_IDX_COUNT_MAX) |
564 SM(1, AR_PHY_AIC_CAL_SYNTH_TOGGLE) |
565 SM(1, AR_PHY_AIC_CAL_SYNTH_AFTER_BTRX) |
566 SM(200, AR_PHY_AIC_CAL_SYNTH_SETTLING)));
567
568 OS_REG_WRITE(ah, aic_ctrl_b0[3],
569 (SM(20, AR_PHY_AIC_MON_MAX_HOP_COUNT) |
570 SM(10, AR_PHY_AIC_MON_MIN_STALE_COUNT) |
571 SM(1, AR_PHY_AIC_MON_PWR_EST_LONG) |
572 SM(2, AR_PHY_AIC_MON_PD_TALLY_SCALING) |
573 SM(18, AR_PHY_AIC_MON_PERF_THR) |
574 SM(1, AR_PHY_AIC_CAL_COM_ATT_DB_FIXED) |
575 SM(2, AR_PHY_AIC_CAL_TARGET_MAG_SETTING) |
576 SM(3, AR_PHY_AIC_CAL_PERF_CHECK_FACTOR) |
577 SM(1, AR_PHY_AIC_CAL_PWR_EST_LONG)));
578
579 ar9300_aic_gain_table(ah);
580
581 /* Need to enable AIC reference signal in BT modem. */
582 OS_REG_WRITE(ah, ATH_AIC_BT_JUPITER_CTRL,
583 (OS_REG_READ(ah, ATH_AIC_BT_JUPITER_CTRL) |
584 ATH_AIC_BT_AIC_ENABLE));
585
586 while (cal_count)
587 {
588 /* Start calibration */
589 OS_REG_CLR_BIT(ah, aic_ctrl_b1[0], AR_PHY_AIC_CAL_ENABLE);
590 OS_REG_SET_BIT(ah, aic_ctrl_b1[0], AR_PHY_AIC_CAL_CH_VALID_RESET);
591 OS_REG_SET_BIT(ah, aic_ctrl_b1[0], AR_PHY_AIC_CAL_ENABLE);
592
593 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(AIC) Start calibration #%d\n",
594 (ATH_AIC_MAX_CAL_COUNT - cal_count));
595
596 /* Wait until calibration is completed. */
597 for (i = 0; i < 10000; i++) {
598 /*
599 * Use AR_PHY_AIC_CAL_ENABLE bit instead of AR_PHY_AIC_CAL_DONE.
600 * Sometimes CAL_DONE bit is not asserted.
601 */
602 if ((OS_REG_READ(ah, aic_ctrl_b1[0]) & AR_PHY_AIC_CAL_ENABLE) == 0)
603 {
604 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(AIC) Cal is done at #%d\n", i);
605 break;
606 }
607 OS_DELAY(1);
608 }
609
610 /* print out status registers */
611 aic_stat = OS_REG_READ(ah, aic_stat_b1[0]);
612 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
613 "(AIC) CAL_DONE = %d, CAL_ACTIVE = %d, MEAS_COUNT = %d\n",
614 MS(aic_stat, AR_PHY_AIC_CAL_DONE),
615 MS(aic_stat, AR_PHY_AIC_CAL_ACTIVE),
616 MS(aic_stat, AR_PHY_AIC_MEAS_COUNT));
617 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
618 "(AIC) ANT_ISO = %d, HOP_COUNT = %d, VALID_COUNT = %d\n",
619 MS(aic_stat, AR_PHY_AIC_CAL_ANT_ISO_EST),
620 MS(aic_stat, AR_PHY_AIC_CAL_HOP_COUNT),
621 MS(aic_stat, AR_PHY_AIC_CAL_VALID_COUNT));
622 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
623 "(AIC) BT_WEAK = %d, BT_STRONG = %d, , \n",
624 MS(aic_stat, AR_PHY_AIC_CAL_BT_TOO_WEAK_ERR),
625 MS(aic_stat, AR_PHY_AIC_CAL_BT_TOO_STRONG_ERR));
626
627 aic_stat = OS_REG_READ(ah, aic_stat_b1[1]);
628 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
629 "(AIC) MEAS_MAG_MIN = %d, CAL_AIC_SM = %d, AIC_SM = %d\n",
630 MS(aic_stat, AR_PHY_AIC_MEAS_MAG_MIN),
631 MS(aic_stat, AR_PHY_AIC_CAL_AIC_SM),
632 MS(aic_stat, AR_PHY_AIC_SM));
633
634 if (i >= 10000) {
635 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(AIC) Calibration failed.\n");
636 break;
637 }
638
639 /* print out calibration result */
640 if (MS(aic_stat, AR_PHY_AIC_MEAS_MAG_MIN) < ATH_AIC_MEAS_MAG_THRESH) {
641 for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) {
642 OS_REG_WRITE(ah, AR_PHY_AIC_SRAM_ADDR_B1,
643 (ATH_AIC_SRAM_CAL_OFFSET + i*4));
644 value = OS_REG_READ(ah, AR_PHY_AIC_SRAM_DATA_B1);
645 if (value & 0x01) {
646 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
647 "(AIC) BT chan %02d: 0x%08x\n", i, value);
648 }
649 }
650 break;
651 }
652 cal_count--;
653 }
654
655 if (!cal_count) {
656 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(AIC) Calibration failed2.\n");
657 }
658
659 /* Disable AIC reference signal in BT modem. */
660 OS_REG_WRITE(ah, ATH_AIC_BT_JUPITER_CTRL,
661 (OS_REG_READ(ah, ATH_AIC_BT_JUPITER_CTRL) &
662 ~ATH_AIC_BT_AIC_ENABLE));
663
664 ahp->ah_aic_enabled = ar9300_aic_cal_post_process(ah) ? AH_TRUE : AH_FALSE;
665
666 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(AIC) ah_aic_enable = %d\n",
667 ahp->ah_aic_enabled);
668 return 0;
669 }
670
671
672 u_int32_t
ar9300_aic_start_normal(struct ath_hal * ah)673 ar9300_aic_start_normal (struct ath_hal *ah)
674 {
675 struct ath_hal_9300 *ahp = AH9300(ah);
676 u_int32_t aic_ctrl0_b1, aic_ctrl1_b0, aic_ctrl1_b1;
677 int16_t i;
678
679 /* Config LNA gain difference */
680 OS_REG_WRITE(ah, AR_PHY_BT_COEX_4, 0x22180600);
681 OS_REG_WRITE(ah, AR_PHY_BT_COEX_5, 0x52443a2e);
682
683 ar9300_aic_gain_table(ah);
684
685 OS_REG_WRITE(ah, AR_PHY_AIC_SRAM_ADDR_B1, ATH_AIC_SRAM_AUTO_INCREMENT);
686
687 for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) {
688 OS_REG_WRITE(ah, AR_PHY_AIC_SRAM_DATA_B1, ahp->ah_aic_sram[i]);
689 }
690
691 if (AR_SREV_JUPITER_10(ah)) {
692 aic_ctrl0_b1 = AR_PHY_AIC_CTRL_0_B1_10;
693 aic_ctrl1_b0 = AR_PHY_AIC_CTRL_1_B0_10;
694 aic_ctrl1_b1 = AR_PHY_AIC_CTRL_1_B1_10;
695 }
696 else {
697 aic_ctrl0_b1 = AR_PHY_AIC_CTRL_0_B1_20;
698 aic_ctrl1_b0 = AR_PHY_AIC_CTRL_1_B0_20;
699 aic_ctrl1_b1 = AR_PHY_AIC_CTRL_1_B1_20;
700 }
701
702 OS_REG_WRITE(ah, aic_ctrl1_b0,
703 (SM(0, AR_PHY_AIC_BT_IDLE_CFG) |
704 SM(1, AR_PHY_AIC_STDBY_COND) |
705 SM(37, AR_PHY_AIC_STDBY_ROT_ATT_DB) |
706 SM(5, AR_PHY_AIC_STDBY_COM_ATT_DB) |
707 SM(15, AR_PHY_AIC_RSSI_MAX) |
708 SM(0, AR_PHY_AIC_RSSI_MIN)));
709
710 OS_REG_WRITE(ah, aic_ctrl1_b1,
711 (SM(15, AR_PHY_AIC_RSSI_MAX) |
712 SM(0, AR_PHY_AIC_RSSI_MIN)));
713
714 OS_REG_WRITE(ah, aic_ctrl0_b1,
715 (SM(0x40, AR_PHY_AIC_BTTX_PWR_THR) |
716 SM(1, AR_PHY_AIC_ENABLE)));
717
718 ahp->ah_aic_enabled = AH_TRUE;
719
720 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(AIC) Start normal operation mode.\n");
721 return 0;
722 }
723 #endif
724
725 #endif
726
727
728