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
33struct 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
42struct 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
63static const u_int8_t com_att_db_table[ATH_AIC_MAX_COM_ATT_DB_TABLE] = {
64        0, 3, 9, 15, 21, 27};
65
66static 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
78static const u_int32_t aic_test_pattern[ATH_AIC_MAX_BT_CHANNEL] = {
790x00000,    // 0
800x00000,
810x00000,
820x00000,
830x00000,
840x00000,
850x00000,
860x00000,
870x00000,
880x1918d,
890x1938d,    // 10
900x00000,
910x1978d,
920x19e8d,
930x00000,
940x00000,
950x00000,
960x00000,
970x00000,
980x00000,
990x00000,    // 20
1000x00000,
1010x00000,
1020x1ce8f,
1030x00000,
1040x00000,
1050x00000,
1060x00000,
1070x1ca93,
1080x1c995,
1090x00000,    // 30
1100x1c897,
1110x1c899,
1120x00000,
1130x00000,
1140x1c79f,
1150x00000,
1160x1c7a5,
1170x1c6ab,
1180x00000,
1190x00000,    // 40
1200x00000,
1210x00000,
1220x1c63f,
1230x00000,
1240x1c52b,
1250x1c525,
1260x1c523,
1270x00000,
1280x00000,
1290x00000,    // 50
1300x00000,
1310x00000,
1320x1c617,
1330x00000,
1340x1c615,
1350x1c613,
1360x00000,
1370x00000,
1380x00000,
1390x00000,    // 60
1400x1c80f,
1410x1c90f,
1420x1c90f,
1430x1ca0f,
1440x1ca0d,
1450x1cb0d,
1460x00000,
1470x00000,
1480x00000,
1490x00000,    // 70
1500x1d00d,
1510x00000,
1520x00000,
1530x00000,
1540x00000,
1550x00000,
1560x00000,
1570x00000
158};
159#endif
160
161static void
162ar9300_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
218static int16_t
219ar9300_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
248static int16_t
249ar9300_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
281static HAL_BOOL
282ar9300_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
484u_int32_t
485ar9300_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
672u_int32_t
673ar9300_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