2 * Copyright (c) 2015 Qualcomm Atheros Inc.
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.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include "ar9003_mci.h"
20 #include "ar9003_aic.h"
21 #include "ar9003_phy.h"
24 static const u8 com_att_db_table
[ATH_AIC_MAX_COM_ATT_DB_TABLE
] = {
28 static const u16 aic_lin_table
[ATH_AIC_MAX_AIC_LIN_TABLE
] = {
29 8191, 7300, 6506, 5799, 5168, 4606, 4105, 3659,
30 3261, 2906, 2590, 2309, 2057, 1834, 1634, 1457,
31 1298, 1157, 1031, 919, 819, 730, 651, 580,
32 517, 461, 411, 366, 326, 291, 259, 231,
33 206, 183, 163, 146, 130, 116, 103, 92,
34 82, 73, 65, 58, 52, 46, 41, 37,
35 33, 29, 26, 23, 21, 18, 16, 15,
36 13, 12, 10, 9, 8, 7, 7, 6,
40 static bool ar9003_hw_is_aic_enabled(struct ath_hw
*ah
)
42 struct ath9k_hw_mci
*mci_hw
= &ah
->btcoex_hw
.mci
;
45 * Disable AIC for now, until we have all the
46 * HW code and the driver-layer support ready.
50 if (mci_hw
->config
& ATH_MCI_CONFIG_DISABLE_AIC
)
56 static int16_t ar9003_aic_find_valid(struct ath_aic_sram_info
*cal_sram
,
62 for (i
= index
+ 1; i
< ATH_AIC_MAX_BT_CHANNEL
; i
++) {
63 if (cal_sram
[i
].valid
)
67 for (i
= index
- 1; i
>= 0; i
--) {
68 if (cal_sram
[i
].valid
)
73 if ((i
>= ATH_AIC_MAX_BT_CHANNEL
) || (i
< 0))
80 * type 0: aic_lin_table, 1: com_att_db_table
82 static int16_t ar9003_aic_find_index(u8 type
, int16_t value
)
87 for (i
= ATH_AIC_MAX_AIC_LIN_TABLE
- 1; i
>= 0; i
--) {
88 if (aic_lin_table
[i
] >= value
)
91 } else if (type
== 1) {
92 for (i
= 0; i
< ATH_AIC_MAX_COM_ATT_DB_TABLE
; i
++) {
93 if (com_att_db_table
[i
] > value
) {
99 if (i
>= ATH_AIC_MAX_COM_ATT_DB_TABLE
)
106 static void ar9003_aic_gain_table(struct ath_hw
*ah
)
108 u32 aic_atten_word
[19], i
;
110 /* Config LNA gain difference */
111 REG_WRITE(ah
, AR_PHY_BT_COEX_4
, 0x2c200a00);
112 REG_WRITE(ah
, AR_PHY_BT_COEX_5
, 0x5c4e4438);
114 /* Program gain table */
115 aic_atten_word
[0] = (0x1 & 0xf) << 14 | (0x1f & 0x1f) << 9 | (0x0 & 0xf) << 5 |
116 (0x1f & 0x1f); /* -01 dB: 4'd1, 5'd31, 00 dB: 4'd0, 5'd31 */
117 aic_atten_word
[1] = (0x3 & 0xf) << 14 | (0x1f & 0x1f) << 9 | (0x2 & 0xf) << 5 |
118 (0x1f & 0x1f); /* -03 dB: 4'd3, 5'd31, -02 dB: 4'd2, 5'd31 */
119 aic_atten_word
[2] = (0x5 & 0xf) << 14 | (0x1f & 0x1f) << 9 | (0x4 & 0xf) << 5 |
120 (0x1f & 0x1f); /* -05 dB: 4'd5, 5'd31, -04 dB: 4'd4, 5'd31 */
121 aic_atten_word
[3] = (0x1 & 0xf) << 14 | (0x1e & 0x1f) << 9 | (0x0 & 0xf) << 5 |
122 (0x1e & 0x1f); /* -07 dB: 4'd1, 5'd30, -06 dB: 4'd0, 5'd30 */
123 aic_atten_word
[4] = (0x3 & 0xf) << 14 | (0x1e & 0x1f) << 9 | (0x2 & 0xf) << 5 |
124 (0x1e & 0x1f); /* -09 dB: 4'd3, 5'd30, -08 dB: 4'd2, 5'd30 */
125 aic_atten_word
[5] = (0x5 & 0xf) << 14 | (0x1e & 0x1f) << 9 | (0x4 & 0xf) << 5 |
126 (0x1e & 0x1f); /* -11 dB: 4'd5, 5'd30, -10 dB: 4'd4, 5'd30 */
127 aic_atten_word
[6] = (0x1 & 0xf) << 14 | (0xf & 0x1f) << 9 | (0x0 & 0xf) << 5 |
128 (0xf & 0x1f); /* -13 dB: 4'd1, 5'd15, -12 dB: 4'd0, 5'd15 */
129 aic_atten_word
[7] = (0x3 & 0xf) << 14 | (0xf & 0x1f) << 9 | (0x2 & 0xf) << 5 |
130 (0xf & 0x1f); /* -15 dB: 4'd3, 5'd15, -14 dB: 4'd2, 5'd15 */
131 aic_atten_word
[8] = (0x5 & 0xf) << 14 | (0xf & 0x1f) << 9 | (0x4 & 0xf) << 5 |
132 (0xf & 0x1f); /* -17 dB: 4'd5, 5'd15, -16 dB: 4'd4, 5'd15 */
133 aic_atten_word
[9] = (0x1 & 0xf) << 14 | (0x7 & 0x1f) << 9 | (0x0 & 0xf) << 5 |
134 (0x7 & 0x1f); /* -19 dB: 4'd1, 5'd07, -18 dB: 4'd0, 5'd07 */
135 aic_atten_word
[10] = (0x3 & 0xf) << 14 | (0x7 & 0x1f) << 9 | (0x2 & 0xf) << 5 |
136 (0x7 & 0x1f); /* -21 dB: 4'd3, 5'd07, -20 dB: 4'd2, 5'd07 */
137 aic_atten_word
[11] = (0x5 & 0xf) << 14 | (0x7 & 0x1f) << 9 | (0x4 & 0xf) << 5 |
138 (0x7 & 0x1f); /* -23 dB: 4'd5, 5'd07, -22 dB: 4'd4, 5'd07 */
139 aic_atten_word
[12] = (0x7 & 0xf) << 14 | (0x7 & 0x1f) << 9 | (0x6 & 0xf) << 5 |
140 (0x7 & 0x1f); /* -25 dB: 4'd7, 5'd07, -24 dB: 4'd6, 5'd07 */
141 aic_atten_word
[13] = (0x3 & 0xf) << 14 | (0x3 & 0x1f) << 9 | (0x2 & 0xf) << 5 |
142 (0x3 & 0x1f); /* -27 dB: 4'd3, 5'd03, -26 dB: 4'd2, 5'd03 */
143 aic_atten_word
[14] = (0x5 & 0xf) << 14 | (0x3 & 0x1f) << 9 | (0x4 & 0xf) << 5 |
144 (0x3 & 0x1f); /* -29 dB: 4'd5, 5'd03, -28 dB: 4'd4, 5'd03 */
145 aic_atten_word
[15] = (0x1 & 0xf) << 14 | (0x1 & 0x1f) << 9 | (0x0 & 0xf) << 5 |
146 (0x1 & 0x1f); /* -31 dB: 4'd1, 5'd01, -30 dB: 4'd0, 5'd01 */
147 aic_atten_word
[16] = (0x3 & 0xf) << 14 | (0x1 & 0x1f) << 9 | (0x2 & 0xf) << 5 |
148 (0x1 & 0x1f); /* -33 dB: 4'd3, 5'd01, -32 dB: 4'd2, 5'd01 */
149 aic_atten_word
[17] = (0x5 & 0xf) << 14 | (0x1 & 0x1f) << 9 | (0x4 & 0xf) << 5 |
150 (0x1 & 0x1f); /* -35 dB: 4'd5, 5'd01, -34 dB: 4'd4, 5'd01 */
151 aic_atten_word
[18] = (0x7 & 0xf) << 14 | (0x1 & 0x1f) << 9 | (0x6 & 0xf) << 5 |
152 (0x1 & 0x1f); /* -37 dB: 4'd7, 5'd01, -36 dB: 4'd6, 5'd01 */
154 /* Write to Gain table with auto increment enabled. */
155 REG_WRITE(ah
, (AR_PHY_AIC_SRAM_ADDR_B0
+ 0x3000),
156 (ATH_AIC_SRAM_AUTO_INCREMENT
|
157 ATH_AIC_SRAM_GAIN_TABLE_OFFSET
));
159 for (i
= 0; i
< 19; i
++) {
160 REG_WRITE(ah
, (AR_PHY_AIC_SRAM_DATA_B0
+ 0x3000),
165 static u8
ar9003_aic_cal_start(struct ath_hw
*ah
, u8 min_valid_count
)
167 struct ath9k_hw_aic
*aic
= &ah
->btcoex_hw
.aic
;
170 /* Write to Gain table with auto increment enabled. */
171 REG_WRITE(ah
, (AR_PHY_AIC_SRAM_ADDR_B0
+ 0x3000),
172 (ATH_AIC_SRAM_AUTO_INCREMENT
|
173 ATH_AIC_SRAM_CAL_OFFSET
));
175 for (i
= 0; i
< ATH_AIC_MAX_BT_CHANNEL
; i
++) {
176 REG_WRITE(ah
, (AR_PHY_AIC_SRAM_DATA_B0
+ 0x3000), 0);
177 aic
->aic_sram
[i
] = 0;
180 REG_WRITE(ah
, AR_PHY_AIC_CTRL_0_B0
,
181 (SM(0, AR_PHY_AIC_MON_ENABLE
) |
182 SM(127, AR_PHY_AIC_CAL_MAX_HOP_COUNT
) |
183 SM(min_valid_count
, AR_PHY_AIC_CAL_MIN_VALID_COUNT
) |
184 SM(37, AR_PHY_AIC_F_WLAN
) |
185 SM(1, AR_PHY_AIC_CAL_CH_VALID_RESET
) |
186 SM(0, AR_PHY_AIC_CAL_ENABLE
) |
187 SM(0x40, AR_PHY_AIC_BTTX_PWR_THR
) |
188 SM(0, AR_PHY_AIC_ENABLE
)));
190 REG_WRITE(ah
, AR_PHY_AIC_CTRL_0_B1
,
191 (SM(0, AR_PHY_AIC_MON_ENABLE
) |
192 SM(1, AR_PHY_AIC_CAL_CH_VALID_RESET
) |
193 SM(0, AR_PHY_AIC_CAL_ENABLE
) |
194 SM(0x40, AR_PHY_AIC_BTTX_PWR_THR
) |
195 SM(0, AR_PHY_AIC_ENABLE
)));
197 REG_WRITE(ah
, AR_PHY_AIC_CTRL_1_B0
,
198 (SM(8, AR_PHY_AIC_CAL_BT_REF_DELAY
) |
199 SM(0, AR_PHY_AIC_BT_IDLE_CFG
) |
200 SM(1, AR_PHY_AIC_STDBY_COND
) |
201 SM(37, AR_PHY_AIC_STDBY_ROT_ATT_DB
) |
202 SM(5, AR_PHY_AIC_STDBY_COM_ATT_DB
) |
203 SM(15, AR_PHY_AIC_RSSI_MAX
) |
204 SM(0, AR_PHY_AIC_RSSI_MIN
)));
206 REG_WRITE(ah
, AR_PHY_AIC_CTRL_1_B1
,
207 (SM(15, AR_PHY_AIC_RSSI_MAX
) |
208 SM(0, AR_PHY_AIC_RSSI_MIN
)));
210 REG_WRITE(ah
, AR_PHY_AIC_CTRL_2_B0
,
211 (SM(44, AR_PHY_AIC_RADIO_DELAY
) |
212 SM(8, AR_PHY_AIC_CAL_STEP_SIZE_CORR
) |
213 SM(12, AR_PHY_AIC_CAL_ROT_IDX_CORR
) |
214 SM(2, AR_PHY_AIC_CAL_CONV_CHECK_FACTOR
) |
215 SM(5, AR_PHY_AIC_ROT_IDX_COUNT_MAX
) |
216 SM(0, AR_PHY_AIC_CAL_SYNTH_TOGGLE
) |
217 SM(0, AR_PHY_AIC_CAL_SYNTH_AFTER_BTRX
) |
218 SM(200, AR_PHY_AIC_CAL_SYNTH_SETTLING
)));
220 REG_WRITE(ah
, AR_PHY_AIC_CTRL_3_B0
,
221 (SM(2, AR_PHY_AIC_MON_MAX_HOP_COUNT
) |
222 SM(1, AR_PHY_AIC_MON_MIN_STALE_COUNT
) |
223 SM(1, AR_PHY_AIC_MON_PWR_EST_LONG
) |
224 SM(2, AR_PHY_AIC_MON_PD_TALLY_SCALING
) |
225 SM(10, AR_PHY_AIC_MON_PERF_THR
) |
226 SM(2, AR_PHY_AIC_CAL_TARGET_MAG_SETTING
) |
227 SM(1, AR_PHY_AIC_CAL_PERF_CHECK_FACTOR
) |
228 SM(1, AR_PHY_AIC_CAL_PWR_EST_LONG
)));
230 REG_WRITE(ah
, AR_PHY_AIC_CTRL_4_B0
,
231 (SM(2, AR_PHY_AIC_CAL_ROT_ATT_DB_EST_ISO
) |
232 SM(3, AR_PHY_AIC_CAL_COM_ATT_DB_EST_ISO
) |
233 SM(0, AR_PHY_AIC_CAL_ISO_EST_INIT_SETTING
) |
234 SM(2, AR_PHY_AIC_CAL_COM_ATT_DB_BACKOFF
) |
235 SM(1, AR_PHY_AIC_CAL_COM_ATT_DB_FIXED
)));
237 REG_WRITE(ah
, AR_PHY_AIC_CTRL_4_B1
,
238 (SM(2, AR_PHY_AIC_CAL_ROT_ATT_DB_EST_ISO
) |
239 SM(3, AR_PHY_AIC_CAL_COM_ATT_DB_EST_ISO
) |
240 SM(0, AR_PHY_AIC_CAL_ISO_EST_INIT_SETTING
) |
241 SM(2, AR_PHY_AIC_CAL_COM_ATT_DB_BACKOFF
) |
242 SM(1, AR_PHY_AIC_CAL_COM_ATT_DB_FIXED
)));
244 ar9003_aic_gain_table(ah
);
246 /* Need to enable AIC reference signal in BT modem. */
247 REG_WRITE(ah
, ATH_AIC_BT_JUPITER_CTRL
,
248 (REG_READ(ah
, ATH_AIC_BT_JUPITER_CTRL
) |
249 ATH_AIC_BT_AIC_ENABLE
));
251 aic
->aic_cal_start_time
= REG_READ(ah
, AR_TSF_L32
);
253 /* Start calibration */
254 REG_CLR_BIT(ah
, AR_PHY_AIC_CTRL_0_B1
, AR_PHY_AIC_CAL_ENABLE
);
255 REG_SET_BIT(ah
, AR_PHY_AIC_CTRL_0_B1
, AR_PHY_AIC_CAL_CH_VALID_RESET
);
256 REG_SET_BIT(ah
, AR_PHY_AIC_CTRL_0_B1
, AR_PHY_AIC_CAL_ENABLE
);
258 aic
->aic_caled_chan
= 0;
259 aic
->aic_cal_state
= AIC_CAL_STATE_STARTED
;
261 return aic
->aic_cal_state
;
264 static bool ar9003_aic_cal_post_process(struct ath_hw
*ah
)
266 struct ath9k_hw_aic
*aic
= &ah
->btcoex_hw
.aic
;
267 struct ath_aic_sram_info cal_sram
[ATH_AIC_MAX_BT_CHANNEL
];
268 struct ath_aic_out_info aic_sram
[ATH_AIC_MAX_BT_CHANNEL
];
269 u32 dir_path_gain_idx
, quad_path_gain_idx
, value
;
270 u32 fixed_com_att_db
;
271 int8_t dir_path_sign
, quad_path_sign
;
275 memset(&cal_sram
, 0, sizeof(cal_sram
));
276 memset(&aic_sram
, 0, sizeof(aic_sram
));
278 for (i
= 0; i
< ATH_AIC_MAX_BT_CHANNEL
; i
++) {
279 value
= aic
->aic_sram
[i
];
282 MS(value
, AR_PHY_AIC_SRAM_VALID
);
283 cal_sram
[i
].rot_quad_att_db
=
284 MS(value
, AR_PHY_AIC_SRAM_ROT_QUAD_ATT_DB
);
285 cal_sram
[i
].vga_quad_sign
=
286 MS(value
, AR_PHY_AIC_SRAM_VGA_QUAD_SIGN
);
287 cal_sram
[i
].rot_dir_att_db
=
288 MS(value
, AR_PHY_AIC_SRAM_ROT_DIR_ATT_DB
);
289 cal_sram
[i
].vga_dir_sign
=
290 MS(value
, AR_PHY_AIC_SRAM_VGA_DIR_SIGN
);
291 cal_sram
[i
].com_att_6db
=
292 MS(value
, AR_PHY_AIC_SRAM_COM_ATT_6DB
);
294 if (cal_sram
[i
].valid
) {
295 dir_path_gain_idx
= cal_sram
[i
].rot_dir_att_db
+
296 com_att_db_table
[cal_sram
[i
].com_att_6db
];
297 quad_path_gain_idx
= cal_sram
[i
].rot_quad_att_db
+
298 com_att_db_table
[cal_sram
[i
].com_att_6db
];
300 dir_path_sign
= (cal_sram
[i
].vga_dir_sign
) ? 1 : -1;
301 quad_path_sign
= (cal_sram
[i
].vga_quad_sign
) ? 1 : -1;
303 aic_sram
[i
].dir_path_gain_lin
= dir_path_sign
*
304 aic_lin_table
[dir_path_gain_idx
];
305 aic_sram
[i
].quad_path_gain_lin
= quad_path_sign
*
306 aic_lin_table
[quad_path_gain_idx
];
310 for (i
= 0; i
< ATH_AIC_MAX_BT_CHANNEL
; i
++) {
311 int16_t start_idx
, end_idx
;
313 if (cal_sram
[i
].valid
)
316 start_idx
= ar9003_aic_find_valid(cal_sram
, 0, i
);
317 end_idx
= ar9003_aic_find_valid(cal_sram
, 1, i
);
322 end_idx
= ar9003_aic_find_valid(cal_sram
, 1, start_idx
);
329 aic_sram
[i
].dir_path_gain_lin
=
330 ((aic_sram
[start_idx
].dir_path_gain_lin
-
331 aic_sram
[end_idx
].dir_path_gain_lin
) *
332 (start_idx
- i
) + ((end_idx
- i
) >> 1)) /
334 aic_sram
[start_idx
].dir_path_gain_lin
;
335 aic_sram
[i
].quad_path_gain_lin
=
336 ((aic_sram
[start_idx
].quad_path_gain_lin
-
337 aic_sram
[end_idx
].quad_path_gain_lin
) *
338 (start_idx
- i
) + ((end_idx
- i
) >> 1)) /
340 aic_sram
[start_idx
].quad_path_gain_lin
;
345 end_idx
= ar9003_aic_find_valid(cal_sram
, 0, start_idx
);
352 aic_sram
[i
].dir_path_gain_lin
=
353 ((aic_sram
[start_idx
].dir_path_gain_lin
-
354 aic_sram
[end_idx
].dir_path_gain_lin
) *
355 (i
- start_idx
) + ((start_idx
- end_idx
) >> 1)) /
356 (start_idx
- end_idx
) +
357 aic_sram
[start_idx
].dir_path_gain_lin
;
358 aic_sram
[i
].quad_path_gain_lin
=
359 ((aic_sram
[start_idx
].quad_path_gain_lin
-
360 aic_sram
[end_idx
].quad_path_gain_lin
) *
361 (i
- start_idx
) + ((start_idx
- end_idx
) >> 1)) /
362 (start_idx
- end_idx
) +
363 aic_sram
[start_idx
].quad_path_gain_lin
;
365 } else if (start_idx
>= 0){
367 aic_sram
[i
].dir_path_gain_lin
=
368 (((end_idx
- i
) * aic_sram
[start_idx
].dir_path_gain_lin
) +
369 ((i
- start_idx
) * aic_sram
[end_idx
].dir_path_gain_lin
) +
370 ((end_idx
- start_idx
) >> 1)) /
371 (end_idx
- start_idx
);
372 aic_sram
[i
].quad_path_gain_lin
=
373 (((end_idx
- i
) * aic_sram
[start_idx
].quad_path_gain_lin
) +
374 ((i
- start_idx
) * aic_sram
[end_idx
].quad_path_gain_lin
) +
375 ((end_idx
- start_idx
) >> 1))/
376 (end_idx
- start_idx
);
380 /* From dir/quad_path_gain_lin to sram. */
381 i
= ar9003_aic_find_valid(cal_sram
, 1, 0);
386 fixed_com_att_db
= com_att_db_table
[cal_sram
[i
].com_att_6db
];
388 for (i
= 0; i
< ATH_AIC_MAX_BT_CHANNEL
; i
++) {
389 int16_t rot_dir_path_att_db
, rot_quad_path_att_db
;
391 aic_sram
[i
].sram
.vga_dir_sign
=
392 (aic_sram
[i
].dir_path_gain_lin
>= 0) ? 1 : 0;
393 aic_sram
[i
].sram
.vga_quad_sign
=
394 (aic_sram
[i
].quad_path_gain_lin
>= 0) ? 1 : 0;
396 rot_dir_path_att_db
=
397 ar9003_aic_find_index(0, abs(aic_sram
[i
].dir_path_gain_lin
)) -
399 rot_quad_path_att_db
=
400 ar9003_aic_find_index(0, abs(aic_sram
[i
].quad_path_gain_lin
)) -
403 aic_sram
[i
].sram
.com_att_6db
=
404 ar9003_aic_find_index(1, fixed_com_att_db
);
406 aic_sram
[i
].sram
.valid
= 1;
408 aic_sram
[i
].sram
.rot_dir_att_db
=
409 min(max(rot_dir_path_att_db
,
410 (int16_t)ATH_AIC_MIN_ROT_DIR_ATT_DB
),
411 ATH_AIC_MAX_ROT_DIR_ATT_DB
);
412 aic_sram
[i
].sram
.rot_quad_att_db
=
413 min(max(rot_quad_path_att_db
,
414 (int16_t)ATH_AIC_MIN_ROT_QUAD_ATT_DB
),
415 ATH_AIC_MAX_ROT_QUAD_ATT_DB
);
418 for (i
= 0; i
< ATH_AIC_MAX_BT_CHANNEL
; i
++) {
419 aic
->aic_sram
[i
] = (SM(aic_sram
[i
].sram
.vga_dir_sign
,
420 AR_PHY_AIC_SRAM_VGA_DIR_SIGN
) |
421 SM(aic_sram
[i
].sram
.vga_quad_sign
,
422 AR_PHY_AIC_SRAM_VGA_QUAD_SIGN
) |
423 SM(aic_sram
[i
].sram
.com_att_6db
,
424 AR_PHY_AIC_SRAM_COM_ATT_6DB
) |
425 SM(aic_sram
[i
].sram
.valid
,
426 AR_PHY_AIC_SRAM_VALID
) |
427 SM(aic_sram
[i
].sram
.rot_dir_att_db
,
428 AR_PHY_AIC_SRAM_ROT_DIR_ATT_DB
) |
429 SM(aic_sram
[i
].sram
.rot_quad_att_db
,
430 AR_PHY_AIC_SRAM_ROT_QUAD_ATT_DB
));
436 static void ar9003_aic_cal_done(struct ath_hw
*ah
)
438 struct ath9k_hw_aic
*aic
= &ah
->btcoex_hw
.aic
;
440 /* Disable AIC reference signal in BT modem. */
441 REG_WRITE(ah
, ATH_AIC_BT_JUPITER_CTRL
,
442 (REG_READ(ah
, ATH_AIC_BT_JUPITER_CTRL
) &
443 ~ATH_AIC_BT_AIC_ENABLE
));
445 if (ar9003_aic_cal_post_process(ah
))
446 aic
->aic_cal_state
= AIC_CAL_STATE_DONE
;
448 aic
->aic_cal_state
= AIC_CAL_STATE_ERROR
;
451 static u8
ar9003_aic_cal_continue(struct ath_hw
*ah
, bool cal_once
)
453 struct ath_common
*common
= ath9k_hw_common(ah
);
454 struct ath9k_hw_mci
*mci_hw
= &ah
->btcoex_hw
.mci
;
455 struct ath9k_hw_aic
*aic
= &ah
->btcoex_hw
.aic
;
458 num_chan
= MS(mci_hw
->config
, ATH_MCI_CONFIG_AIC_CAL_NUM_CHAN
);
461 aic
->aic_cal_state
= AIC_CAL_STATE_ERROR
;
462 return aic
->aic_cal_state
;
466 for (i
= 0; i
< 10000; i
++) {
467 if ((REG_READ(ah
, AR_PHY_AIC_CTRL_0_B1
) &
468 AR_PHY_AIC_CAL_ENABLE
) == 0)
476 * Use AR_PHY_AIC_CAL_ENABLE bit instead of AR_PHY_AIC_CAL_DONE.
477 * Sometimes CAL_DONE bit is not asserted.
479 if ((REG_READ(ah
, AR_PHY_AIC_CTRL_0_B1
) &
480 AR_PHY_AIC_CAL_ENABLE
) != 0) {
481 ath_dbg(common
, MCI
, "AIC cal is not done after 40ms");
485 REG_WRITE(ah
, AR_PHY_AIC_SRAM_ADDR_B1
,
486 (ATH_AIC_SRAM_CAL_OFFSET
| ATH_AIC_SRAM_AUTO_INCREMENT
));
488 for (i
= 0; i
< ATH_AIC_MAX_BT_CHANNEL
; i
++) {
491 value
= REG_READ(ah
, AR_PHY_AIC_SRAM_DATA_B1
);
494 if (aic
->aic_sram
[i
] == 0)
495 aic
->aic_caled_chan
++;
497 aic
->aic_sram
[i
] = value
;
504 if ((aic
->aic_caled_chan
>= num_chan
) || cal_once
) {
505 ar9003_aic_cal_done(ah
);
507 /* Start calibration */
508 REG_CLR_BIT(ah
, AR_PHY_AIC_CTRL_0_B1
, AR_PHY_AIC_CAL_ENABLE
);
509 REG_SET_BIT(ah
, AR_PHY_AIC_CTRL_0_B1
,
510 AR_PHY_AIC_CAL_CH_VALID_RESET
);
511 REG_SET_BIT(ah
, AR_PHY_AIC_CTRL_0_B1
, AR_PHY_AIC_CAL_ENABLE
);
514 return aic
->aic_cal_state
;
518 u8
ar9003_aic_calibration(struct ath_hw
*ah
)
520 struct ath9k_hw_aic
*aic
= &ah
->btcoex_hw
.aic
;
521 u8 cal_ret
= AIC_CAL_STATE_ERROR
;
523 switch (aic
->aic_cal_state
) {
524 case AIC_CAL_STATE_IDLE
:
525 cal_ret
= ar9003_aic_cal_start(ah
, 1);
527 case AIC_CAL_STATE_STARTED
:
528 cal_ret
= ar9003_aic_cal_continue(ah
, false);
530 case AIC_CAL_STATE_DONE
:
531 cal_ret
= AIC_CAL_STATE_DONE
;
540 u8
ar9003_aic_start_normal(struct ath_hw
*ah
)
542 struct ath9k_hw_aic
*aic
= &ah
->btcoex_hw
.aic
;
545 if (aic
->aic_cal_state
!= AIC_CAL_STATE_DONE
)
548 ar9003_aic_gain_table(ah
);
550 REG_WRITE(ah
, AR_PHY_AIC_SRAM_ADDR_B1
, ATH_AIC_SRAM_AUTO_INCREMENT
);
552 for (i
= 0; i
< ATH_AIC_MAX_BT_CHANNEL
; i
++) {
553 REG_WRITE(ah
, AR_PHY_AIC_SRAM_DATA_B1
, aic
->aic_sram
[i
]);
556 /* FIXME: Replace these with proper register names */
557 REG_WRITE(ah
, 0xa6b0, 0x80);
558 REG_WRITE(ah
, 0xa6b4, 0x5b2df0);
559 REG_WRITE(ah
, 0xa6b8, 0x10762cc8);
560 REG_WRITE(ah
, 0xa6bc, 0x1219a4b);
561 REG_WRITE(ah
, 0xa6c0, 0x1e01);
562 REG_WRITE(ah
, 0xb6b4, 0xf0);
563 REG_WRITE(ah
, 0xb6c0, 0x1e01);
564 REG_WRITE(ah
, 0xb6b0, 0x81);
565 REG_WRITE(ah
, AR_PHY_65NM_CH1_RXTX4
, 0x40000000);
567 aic
->aic_enabled
= true;
572 u8
ar9003_aic_cal_reset(struct ath_hw
*ah
)
574 struct ath9k_hw_aic
*aic
= &ah
->btcoex_hw
.aic
;
576 aic
->aic_cal_state
= AIC_CAL_STATE_IDLE
;
577 return aic
->aic_cal_state
;
580 u8
ar9003_aic_calibration_single(struct ath_hw
*ah
)
582 struct ath9k_hw_mci
*mci_hw
= &ah
->btcoex_hw
.mci
;
586 num_chan
= MS(mci_hw
->config
, ATH_MCI_CONFIG_AIC_CAL_NUM_CHAN
);
588 (void) ar9003_aic_cal_start(ah
, num_chan
);
589 cal_ret
= ar9003_aic_cal_continue(ah
, true);
594 void ar9003_hw_attach_aic_ops(struct ath_hw
*ah
)
596 struct ath_hw_private_ops
*priv_ops
= ath9k_hw_private_ops(ah
);
598 priv_ops
->is_aic_enabled
= ar9003_hw_is_aic_enabled
;