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(bool *cal_sram_valid
,
62 for (i
= index
+ 1; i
< ATH_AIC_MAX_BT_CHANNEL
; i
++) {
63 if (cal_sram_valid
[i
])
67 for (i
= index
- 1; i
>= 0; i
--) {
68 if (cal_sram_valid
[i
])
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 bool cal_sram_valid
[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_valid
, 0, sizeof(cal_sram_valid
));
276 memset(&aic_sram
, 0, sizeof(aic_sram
));
278 for (i
= 0; i
< ATH_AIC_MAX_BT_CHANNEL
; i
++) {
279 struct ath_aic_sram_info sram
;
280 value
= aic
->aic_sram
[i
];
282 cal_sram_valid
[i
] = sram
.valid
=
283 MS(value
, AR_PHY_AIC_SRAM_VALID
);
284 sram
.rot_quad_att_db
=
285 MS(value
, AR_PHY_AIC_SRAM_ROT_QUAD_ATT_DB
);
287 MS(value
, AR_PHY_AIC_SRAM_VGA_QUAD_SIGN
);
288 sram
.rot_dir_att_db
=
289 MS(value
, AR_PHY_AIC_SRAM_ROT_DIR_ATT_DB
);
291 MS(value
, AR_PHY_AIC_SRAM_VGA_DIR_SIGN
);
293 MS(value
, AR_PHY_AIC_SRAM_COM_ATT_6DB
);
296 dir_path_gain_idx
= sram
.rot_dir_att_db
+
297 com_att_db_table
[sram
.com_att_6db
];
298 quad_path_gain_idx
= sram
.rot_quad_att_db
+
299 com_att_db_table
[sram
.com_att_6db
];
301 dir_path_sign
= (sram
.vga_dir_sign
) ? 1 : -1;
302 quad_path_sign
= (sram
.vga_quad_sign
) ? 1 : -1;
304 aic_sram
[i
].dir_path_gain_lin
= dir_path_sign
*
305 aic_lin_table
[dir_path_gain_idx
];
306 aic_sram
[i
].quad_path_gain_lin
= quad_path_sign
*
307 aic_lin_table
[quad_path_gain_idx
];
311 for (i
= 0; i
< ATH_AIC_MAX_BT_CHANNEL
; i
++) {
312 int16_t start_idx
, end_idx
;
314 if (cal_sram_valid
[i
])
317 start_idx
= ar9003_aic_find_valid(cal_sram_valid
, 0, i
);
318 end_idx
= ar9003_aic_find_valid(cal_sram_valid
, 1, i
);
323 end_idx
= ar9003_aic_find_valid(cal_sram_valid
, 1, start_idx
);
330 aic_sram
[i
].dir_path_gain_lin
=
331 ((aic_sram
[start_idx
].dir_path_gain_lin
-
332 aic_sram
[end_idx
].dir_path_gain_lin
) *
333 (start_idx
- i
) + ((end_idx
- i
) >> 1)) /
335 aic_sram
[start_idx
].dir_path_gain_lin
;
336 aic_sram
[i
].quad_path_gain_lin
=
337 ((aic_sram
[start_idx
].quad_path_gain_lin
-
338 aic_sram
[end_idx
].quad_path_gain_lin
) *
339 (start_idx
- i
) + ((end_idx
- i
) >> 1)) /
341 aic_sram
[start_idx
].quad_path_gain_lin
;
346 end_idx
= ar9003_aic_find_valid(cal_sram_valid
, 0, start_idx
);
353 aic_sram
[i
].dir_path_gain_lin
=
354 ((aic_sram
[start_idx
].dir_path_gain_lin
-
355 aic_sram
[end_idx
].dir_path_gain_lin
) *
356 (i
- start_idx
) + ((start_idx
- end_idx
) >> 1)) /
357 (start_idx
- end_idx
) +
358 aic_sram
[start_idx
].dir_path_gain_lin
;
359 aic_sram
[i
].quad_path_gain_lin
=
360 ((aic_sram
[start_idx
].quad_path_gain_lin
-
361 aic_sram
[end_idx
].quad_path_gain_lin
) *
362 (i
- start_idx
) + ((start_idx
- end_idx
) >> 1)) /
363 (start_idx
- end_idx
) +
364 aic_sram
[start_idx
].quad_path_gain_lin
;
366 } else if (start_idx
>= 0){
368 aic_sram
[i
].dir_path_gain_lin
=
369 (((end_idx
- i
) * aic_sram
[start_idx
].dir_path_gain_lin
) +
370 ((i
- start_idx
) * aic_sram
[end_idx
].dir_path_gain_lin
) +
371 ((end_idx
- start_idx
) >> 1)) /
372 (end_idx
- start_idx
);
373 aic_sram
[i
].quad_path_gain_lin
=
374 (((end_idx
- i
) * aic_sram
[start_idx
].quad_path_gain_lin
) +
375 ((i
- start_idx
) * aic_sram
[end_idx
].quad_path_gain_lin
) +
376 ((end_idx
- start_idx
) >> 1))/
377 (end_idx
- start_idx
);
381 /* From dir/quad_path_gain_lin to sram. */
382 i
= ar9003_aic_find_valid(cal_sram_valid
, 1, 0);
387 fixed_com_att_db
= com_att_db_table
[MS(aic
->aic_sram
[i
],
388 AR_PHY_AIC_SRAM_COM_ATT_6DB
)];
390 for (i
= 0; i
< ATH_AIC_MAX_BT_CHANNEL
; i
++) {
391 int16_t rot_dir_path_att_db
, rot_quad_path_att_db
;
392 struct ath_aic_sram_info sram
;
395 (aic_sram
[i
].dir_path_gain_lin
>= 0) ? 1 : 0;
397 (aic_sram
[i
].quad_path_gain_lin
>= 0) ? 1 : 0;
399 rot_dir_path_att_db
=
400 ar9003_aic_find_index(0, abs(aic_sram
[i
].dir_path_gain_lin
)) -
402 rot_quad_path_att_db
=
403 ar9003_aic_find_index(0, abs(aic_sram
[i
].quad_path_gain_lin
)) -
407 ar9003_aic_find_index(1, fixed_com_att_db
);
411 sram
.rot_dir_att_db
=
412 min(max(rot_dir_path_att_db
,
413 (int16_t)ATH_AIC_MIN_ROT_DIR_ATT_DB
),
414 ATH_AIC_MAX_ROT_DIR_ATT_DB
);
415 sram
.rot_quad_att_db
=
416 min(max(rot_quad_path_att_db
,
417 (int16_t)ATH_AIC_MIN_ROT_QUAD_ATT_DB
),
418 ATH_AIC_MAX_ROT_QUAD_ATT_DB
);
420 aic
->aic_sram
[i
] = (SM(sram
.vga_dir_sign
,
421 AR_PHY_AIC_SRAM_VGA_DIR_SIGN
) |
422 SM(sram
.vga_quad_sign
,
423 AR_PHY_AIC_SRAM_VGA_QUAD_SIGN
) |
425 AR_PHY_AIC_SRAM_COM_ATT_6DB
) |
427 AR_PHY_AIC_SRAM_VALID
) |
428 SM(sram
.rot_dir_att_db
,
429 AR_PHY_AIC_SRAM_ROT_DIR_ATT_DB
) |
430 SM(sram
.rot_quad_att_db
,
431 AR_PHY_AIC_SRAM_ROT_QUAD_ATT_DB
));
437 static void ar9003_aic_cal_done(struct ath_hw
*ah
)
439 struct ath9k_hw_aic
*aic
= &ah
->btcoex_hw
.aic
;
441 /* Disable AIC reference signal in BT modem. */
442 REG_WRITE(ah
, ATH_AIC_BT_JUPITER_CTRL
,
443 (REG_READ(ah
, ATH_AIC_BT_JUPITER_CTRL
) &
444 ~ATH_AIC_BT_AIC_ENABLE
));
446 if (ar9003_aic_cal_post_process(ah
))
447 aic
->aic_cal_state
= AIC_CAL_STATE_DONE
;
449 aic
->aic_cal_state
= AIC_CAL_STATE_ERROR
;
452 static u8
ar9003_aic_cal_continue(struct ath_hw
*ah
, bool cal_once
)
454 struct ath_common
*common
= ath9k_hw_common(ah
);
455 struct ath9k_hw_mci
*mci_hw
= &ah
->btcoex_hw
.mci
;
456 struct ath9k_hw_aic
*aic
= &ah
->btcoex_hw
.aic
;
459 num_chan
= MS(mci_hw
->config
, ATH_MCI_CONFIG_AIC_CAL_NUM_CHAN
);
462 aic
->aic_cal_state
= AIC_CAL_STATE_ERROR
;
463 return aic
->aic_cal_state
;
467 for (i
= 0; i
< 10000; i
++) {
468 if ((REG_READ(ah
, AR_PHY_AIC_CTRL_0_B1
) &
469 AR_PHY_AIC_CAL_ENABLE
) == 0)
477 * Use AR_PHY_AIC_CAL_ENABLE bit instead of AR_PHY_AIC_CAL_DONE.
478 * Sometimes CAL_DONE bit is not asserted.
480 if ((REG_READ(ah
, AR_PHY_AIC_CTRL_0_B1
) &
481 AR_PHY_AIC_CAL_ENABLE
) != 0) {
482 ath_dbg(common
, MCI
, "AIC cal is not done after 40ms");
486 REG_WRITE(ah
, AR_PHY_AIC_SRAM_ADDR_B1
,
487 (ATH_AIC_SRAM_CAL_OFFSET
| ATH_AIC_SRAM_AUTO_INCREMENT
));
489 for (i
= 0; i
< ATH_AIC_MAX_BT_CHANNEL
; i
++) {
492 value
= REG_READ(ah
, AR_PHY_AIC_SRAM_DATA_B1
);
495 if (aic
->aic_sram
[i
] == 0)
496 aic
->aic_caled_chan
++;
498 aic
->aic_sram
[i
] = value
;
505 if ((aic
->aic_caled_chan
>= num_chan
) || cal_once
) {
506 ar9003_aic_cal_done(ah
);
508 /* Start calibration */
509 REG_CLR_BIT(ah
, AR_PHY_AIC_CTRL_0_B1
, AR_PHY_AIC_CAL_ENABLE
);
510 REG_SET_BIT(ah
, AR_PHY_AIC_CTRL_0_B1
,
511 AR_PHY_AIC_CAL_CH_VALID_RESET
);
512 REG_SET_BIT(ah
, AR_PHY_AIC_CTRL_0_B1
, AR_PHY_AIC_CAL_ENABLE
);
515 return aic
->aic_cal_state
;
519 u8
ar9003_aic_calibration(struct ath_hw
*ah
)
521 struct ath9k_hw_aic
*aic
= &ah
->btcoex_hw
.aic
;
522 u8 cal_ret
= AIC_CAL_STATE_ERROR
;
524 switch (aic
->aic_cal_state
) {
525 case AIC_CAL_STATE_IDLE
:
526 cal_ret
= ar9003_aic_cal_start(ah
, 1);
528 case AIC_CAL_STATE_STARTED
:
529 cal_ret
= ar9003_aic_cal_continue(ah
, false);
531 case AIC_CAL_STATE_DONE
:
532 cal_ret
= AIC_CAL_STATE_DONE
;
541 u8
ar9003_aic_start_normal(struct ath_hw
*ah
)
543 struct ath9k_hw_aic
*aic
= &ah
->btcoex_hw
.aic
;
546 if (aic
->aic_cal_state
!= AIC_CAL_STATE_DONE
)
549 ar9003_aic_gain_table(ah
);
551 REG_WRITE(ah
, AR_PHY_AIC_SRAM_ADDR_B1
, ATH_AIC_SRAM_AUTO_INCREMENT
);
553 for (i
= 0; i
< ATH_AIC_MAX_BT_CHANNEL
; i
++) {
554 REG_WRITE(ah
, AR_PHY_AIC_SRAM_DATA_B1
, aic
->aic_sram
[i
]);
557 /* FIXME: Replace these with proper register names */
558 REG_WRITE(ah
, 0xa6b0, 0x80);
559 REG_WRITE(ah
, 0xa6b4, 0x5b2df0);
560 REG_WRITE(ah
, 0xa6b8, 0x10762cc8);
561 REG_WRITE(ah
, 0xa6bc, 0x1219a4b);
562 REG_WRITE(ah
, 0xa6c0, 0x1e01);
563 REG_WRITE(ah
, 0xb6b4, 0xf0);
564 REG_WRITE(ah
, 0xb6c0, 0x1e01);
565 REG_WRITE(ah
, 0xb6b0, 0x81);
566 REG_WRITE(ah
, AR_PHY_65NM_CH1_RXTX4
, 0x40000000);
568 aic
->aic_enabled
= true;
573 u8
ar9003_aic_cal_reset(struct ath_hw
*ah
)
575 struct ath9k_hw_aic
*aic
= &ah
->btcoex_hw
.aic
;
577 aic
->aic_cal_state
= AIC_CAL_STATE_IDLE
;
578 return aic
->aic_cal_state
;
581 u8
ar9003_aic_calibration_single(struct ath_hw
*ah
)
583 struct ath9k_hw_mci
*mci_hw
= &ah
->btcoex_hw
.mci
;
587 num_chan
= MS(mci_hw
->config
, ATH_MCI_CONFIG_AIC_CAL_NUM_CHAN
);
589 (void) ar9003_aic_cal_start(ah
, num_chan
);
590 cal_ret
= ar9003_aic_cal_continue(ah
, true);
595 void ar9003_hw_attach_aic_ops(struct ath_hw
*ah
)
597 struct ath_hw_private_ops
*priv_ops
= ath9k_hw_private_ops(ah
);
599 priv_ops
->is_aic_enabled
= ar9003_hw_is_aic_enabled
;