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