ath - Reimport fresh from FreeBSD 01-Jan-2014 for re-port
[dragonfly.git] / sys / contrib / dev / ath / ath_hal / ar9300 / ar9300_aic.c
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
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 
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
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
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
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
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