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