0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include "hw.h"
0018 #include "hw-ops.h"
0019 #include "ar9003_mci.h"
0020 #include "ar9003_aic.h"
0021 #include "ar9003_phy.h"
0022 #include "reg_aic.h"
0023
0024 static const u8 com_att_db_table[ATH_AIC_MAX_COM_ATT_DB_TABLE] = {
0025 0, 3, 9, 15, 21, 27
0026 };
0027
0028 static const u16 aic_lin_table[ATH_AIC_MAX_AIC_LIN_TABLE] = {
0029 8191, 7300, 6506, 5799, 5168, 4606, 4105, 3659,
0030 3261, 2906, 2590, 2309, 2057, 1834, 1634, 1457,
0031 1298, 1157, 1031, 919, 819, 730, 651, 580,
0032 517, 461, 411, 366, 326, 291, 259, 231,
0033 206, 183, 163, 146, 130, 116, 103, 92,
0034 82, 73, 65, 58, 52, 46, 41, 37,
0035 33, 29, 26, 23, 21, 18, 16, 15,
0036 13, 12, 10, 9, 8, 7, 7, 6,
0037 5, 5, 4, 4, 3
0038 };
0039
0040 static bool ar9003_hw_is_aic_enabled(struct ath_hw *ah)
0041 {
0042 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
0043
0044
0045
0046
0047
0048 return false;
0049
0050 if (mci_hw->config & ATH_MCI_CONFIG_DISABLE_AIC)
0051 return false;
0052
0053 return true;
0054 }
0055
0056 static int16_t ar9003_aic_find_valid(bool *cal_sram_valid,
0057 bool dir, u8 index)
0058 {
0059 int16_t i;
0060
0061 if (dir) {
0062 for (i = index + 1; i < ATH_AIC_MAX_BT_CHANNEL; i++) {
0063 if (cal_sram_valid[i])
0064 break;
0065 }
0066 } else {
0067 for (i = index - 1; i >= 0; i--) {
0068 if (cal_sram_valid[i])
0069 break;
0070 }
0071 }
0072
0073 if ((i >= ATH_AIC_MAX_BT_CHANNEL) || (i < 0))
0074 i = -1;
0075
0076 return i;
0077 }
0078
0079
0080
0081
0082 static int16_t ar9003_aic_find_index(u8 type, int16_t value)
0083 {
0084 int16_t i = -1;
0085
0086 if (type == 0) {
0087 for (i = ATH_AIC_MAX_AIC_LIN_TABLE - 1; i >= 0; i--) {
0088 if (aic_lin_table[i] >= value)
0089 break;
0090 }
0091 } else if (type == 1) {
0092 for (i = 0; i < ATH_AIC_MAX_COM_ATT_DB_TABLE; i++) {
0093 if (com_att_db_table[i] > value) {
0094 i--;
0095 break;
0096 }
0097 }
0098
0099 if (i >= ATH_AIC_MAX_COM_ATT_DB_TABLE)
0100 i = -1;
0101 }
0102
0103 return i;
0104 }
0105
0106 static void ar9003_aic_gain_table(struct ath_hw *ah)
0107 {
0108 u32 aic_atten_word[19], i;
0109
0110
0111 REG_WRITE(ah, AR_PHY_BT_COEX_4, 0x2c200a00);
0112 REG_WRITE(ah, AR_PHY_BT_COEX_5, 0x5c4e4438);
0113
0114
0115 aic_atten_word[0] = (0x1 & 0xf) << 14 | (0x1f & 0x1f) << 9 | (0x0 & 0xf) << 5 |
0116 (0x1f & 0x1f);
0117 aic_atten_word[1] = (0x3 & 0xf) << 14 | (0x1f & 0x1f) << 9 | (0x2 & 0xf) << 5 |
0118 (0x1f & 0x1f);
0119 aic_atten_word[2] = (0x5 & 0xf) << 14 | (0x1f & 0x1f) << 9 | (0x4 & 0xf) << 5 |
0120 (0x1f & 0x1f);
0121 aic_atten_word[3] = (0x1 & 0xf) << 14 | (0x1e & 0x1f) << 9 | (0x0 & 0xf) << 5 |
0122 (0x1e & 0x1f);
0123 aic_atten_word[4] = (0x3 & 0xf) << 14 | (0x1e & 0x1f) << 9 | (0x2 & 0xf) << 5 |
0124 (0x1e & 0x1f);
0125 aic_atten_word[5] = (0x5 & 0xf) << 14 | (0x1e & 0x1f) << 9 | (0x4 & 0xf) << 5 |
0126 (0x1e & 0x1f);
0127 aic_atten_word[6] = (0x1 & 0xf) << 14 | (0xf & 0x1f) << 9 | (0x0 & 0xf) << 5 |
0128 (0xf & 0x1f);
0129 aic_atten_word[7] = (0x3 & 0xf) << 14 | (0xf & 0x1f) << 9 | (0x2 & 0xf) << 5 |
0130 (0xf & 0x1f);
0131 aic_atten_word[8] = (0x5 & 0xf) << 14 | (0xf & 0x1f) << 9 | (0x4 & 0xf) << 5 |
0132 (0xf & 0x1f);
0133 aic_atten_word[9] = (0x1 & 0xf) << 14 | (0x7 & 0x1f) << 9 | (0x0 & 0xf) << 5 |
0134 (0x7 & 0x1f);
0135 aic_atten_word[10] = (0x3 & 0xf) << 14 | (0x7 & 0x1f) << 9 | (0x2 & 0xf) << 5 |
0136 (0x7 & 0x1f);
0137 aic_atten_word[11] = (0x5 & 0xf) << 14 | (0x7 & 0x1f) << 9 | (0x4 & 0xf) << 5 |
0138 (0x7 & 0x1f);
0139 aic_atten_word[12] = (0x7 & 0xf) << 14 | (0x7 & 0x1f) << 9 | (0x6 & 0xf) << 5 |
0140 (0x7 & 0x1f);
0141 aic_atten_word[13] = (0x3 & 0xf) << 14 | (0x3 & 0x1f) << 9 | (0x2 & 0xf) << 5 |
0142 (0x3 & 0x1f);
0143 aic_atten_word[14] = (0x5 & 0xf) << 14 | (0x3 & 0x1f) << 9 | (0x4 & 0xf) << 5 |
0144 (0x3 & 0x1f);
0145 aic_atten_word[15] = (0x1 & 0xf) << 14 | (0x1 & 0x1f) << 9 | (0x0 & 0xf) << 5 |
0146 (0x1 & 0x1f);
0147 aic_atten_word[16] = (0x3 & 0xf) << 14 | (0x1 & 0x1f) << 9 | (0x2 & 0xf) << 5 |
0148 (0x1 & 0x1f);
0149 aic_atten_word[17] = (0x5 & 0xf) << 14 | (0x1 & 0x1f) << 9 | (0x4 & 0xf) << 5 |
0150 (0x1 & 0x1f);
0151 aic_atten_word[18] = (0x7 & 0xf) << 14 | (0x1 & 0x1f) << 9 | (0x6 & 0xf) << 5 |
0152 (0x1 & 0x1f);
0153
0154
0155 REG_WRITE(ah, (AR_PHY_AIC_SRAM_ADDR_B0 + 0x3000),
0156 (ATH_AIC_SRAM_AUTO_INCREMENT |
0157 ATH_AIC_SRAM_GAIN_TABLE_OFFSET));
0158
0159 for (i = 0; i < 19; i++) {
0160 REG_WRITE(ah, (AR_PHY_AIC_SRAM_DATA_B0 + 0x3000),
0161 aic_atten_word[i]);
0162 }
0163 }
0164
0165 static u8 ar9003_aic_cal_start(struct ath_hw *ah, u8 min_valid_count)
0166 {
0167 struct ath9k_hw_aic *aic = &ah->btcoex_hw.aic;
0168 int i;
0169
0170
0171 REG_WRITE(ah, (AR_PHY_AIC_SRAM_ADDR_B0 + 0x3000),
0172 (ATH_AIC_SRAM_AUTO_INCREMENT |
0173 ATH_AIC_SRAM_CAL_OFFSET));
0174
0175 for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) {
0176 REG_WRITE(ah, (AR_PHY_AIC_SRAM_DATA_B0 + 0x3000), 0);
0177 aic->aic_sram[i] = 0;
0178 }
0179
0180 REG_WRITE(ah, AR_PHY_AIC_CTRL_0_B0,
0181 (SM(0, AR_PHY_AIC_MON_ENABLE) |
0182 SM(127, AR_PHY_AIC_CAL_MAX_HOP_COUNT) |
0183 SM(min_valid_count, AR_PHY_AIC_CAL_MIN_VALID_COUNT) |
0184 SM(37, AR_PHY_AIC_F_WLAN) |
0185 SM(1, AR_PHY_AIC_CAL_CH_VALID_RESET) |
0186 SM(0, AR_PHY_AIC_CAL_ENABLE) |
0187 SM(0x40, AR_PHY_AIC_BTTX_PWR_THR) |
0188 SM(0, AR_PHY_AIC_ENABLE)));
0189
0190 REG_WRITE(ah, AR_PHY_AIC_CTRL_0_B1,
0191 (SM(0, AR_PHY_AIC_MON_ENABLE) |
0192 SM(1, AR_PHY_AIC_CAL_CH_VALID_RESET) |
0193 SM(0, AR_PHY_AIC_CAL_ENABLE) |
0194 SM(0x40, AR_PHY_AIC_BTTX_PWR_THR) |
0195 SM(0, AR_PHY_AIC_ENABLE)));
0196
0197 REG_WRITE(ah, AR_PHY_AIC_CTRL_1_B0,
0198 (SM(8, AR_PHY_AIC_CAL_BT_REF_DELAY) |
0199 SM(0, AR_PHY_AIC_BT_IDLE_CFG) |
0200 SM(1, AR_PHY_AIC_STDBY_COND) |
0201 SM(37, AR_PHY_AIC_STDBY_ROT_ATT_DB) |
0202 SM(5, AR_PHY_AIC_STDBY_COM_ATT_DB) |
0203 SM(15, AR_PHY_AIC_RSSI_MAX) |
0204 SM(0, AR_PHY_AIC_RSSI_MIN)));
0205
0206 REG_WRITE(ah, AR_PHY_AIC_CTRL_1_B1,
0207 (SM(15, AR_PHY_AIC_RSSI_MAX) |
0208 SM(0, AR_PHY_AIC_RSSI_MIN)));
0209
0210 REG_WRITE(ah, AR_PHY_AIC_CTRL_2_B0,
0211 (SM(44, AR_PHY_AIC_RADIO_DELAY) |
0212 SM(8, AR_PHY_AIC_CAL_STEP_SIZE_CORR) |
0213 SM(12, AR_PHY_AIC_CAL_ROT_IDX_CORR) |
0214 SM(2, AR_PHY_AIC_CAL_CONV_CHECK_FACTOR) |
0215 SM(5, AR_PHY_AIC_ROT_IDX_COUNT_MAX) |
0216 SM(0, AR_PHY_AIC_CAL_SYNTH_TOGGLE) |
0217 SM(0, AR_PHY_AIC_CAL_SYNTH_AFTER_BTRX) |
0218 SM(200, AR_PHY_AIC_CAL_SYNTH_SETTLING)));
0219
0220 REG_WRITE(ah, AR_PHY_AIC_CTRL_3_B0,
0221 (SM(2, AR_PHY_AIC_MON_MAX_HOP_COUNT) |
0222 SM(1, AR_PHY_AIC_MON_MIN_STALE_COUNT) |
0223 SM(1, AR_PHY_AIC_MON_PWR_EST_LONG) |
0224 SM(2, AR_PHY_AIC_MON_PD_TALLY_SCALING) |
0225 SM(10, AR_PHY_AIC_MON_PERF_THR) |
0226 SM(2, AR_PHY_AIC_CAL_TARGET_MAG_SETTING) |
0227 SM(1, AR_PHY_AIC_CAL_PERF_CHECK_FACTOR) |
0228 SM(1, AR_PHY_AIC_CAL_PWR_EST_LONG)));
0229
0230 REG_WRITE(ah, AR_PHY_AIC_CTRL_4_B0,
0231 (SM(2, AR_PHY_AIC_CAL_ROT_ATT_DB_EST_ISO) |
0232 SM(3, AR_PHY_AIC_CAL_COM_ATT_DB_EST_ISO) |
0233 SM(0, AR_PHY_AIC_CAL_ISO_EST_INIT_SETTING) |
0234 SM(2, AR_PHY_AIC_CAL_COM_ATT_DB_BACKOFF) |
0235 SM(1, AR_PHY_AIC_CAL_COM_ATT_DB_FIXED)));
0236
0237 REG_WRITE(ah, AR_PHY_AIC_CTRL_4_B1,
0238 (SM(2, AR_PHY_AIC_CAL_ROT_ATT_DB_EST_ISO) |
0239 SM(3, AR_PHY_AIC_CAL_COM_ATT_DB_EST_ISO) |
0240 SM(0, AR_PHY_AIC_CAL_ISO_EST_INIT_SETTING) |
0241 SM(2, AR_PHY_AIC_CAL_COM_ATT_DB_BACKOFF) |
0242 SM(1, AR_PHY_AIC_CAL_COM_ATT_DB_FIXED)));
0243
0244 ar9003_aic_gain_table(ah);
0245
0246
0247 REG_WRITE(ah, ATH_AIC_BT_JUPITER_CTRL,
0248 (REG_READ(ah, ATH_AIC_BT_JUPITER_CTRL) |
0249 ATH_AIC_BT_AIC_ENABLE));
0250
0251 aic->aic_cal_start_time = REG_READ(ah, AR_TSF_L32);
0252
0253
0254 REG_CLR_BIT(ah, AR_PHY_AIC_CTRL_0_B1, AR_PHY_AIC_CAL_ENABLE);
0255 REG_SET_BIT(ah, AR_PHY_AIC_CTRL_0_B1, AR_PHY_AIC_CAL_CH_VALID_RESET);
0256 REG_SET_BIT(ah, AR_PHY_AIC_CTRL_0_B1, AR_PHY_AIC_CAL_ENABLE);
0257
0258 aic->aic_caled_chan = 0;
0259 aic->aic_cal_state = AIC_CAL_STATE_STARTED;
0260
0261 return aic->aic_cal_state;
0262 }
0263
0264 static bool ar9003_aic_cal_post_process(struct ath_hw *ah)
0265 {
0266 struct ath9k_hw_aic *aic = &ah->btcoex_hw.aic;
0267 bool cal_sram_valid[ATH_AIC_MAX_BT_CHANNEL];
0268 struct ath_aic_out_info aic_sram[ATH_AIC_MAX_BT_CHANNEL];
0269 u32 dir_path_gain_idx, quad_path_gain_idx, value;
0270 u32 fixed_com_att_db;
0271 int8_t dir_path_sign, quad_path_sign;
0272 int16_t i;
0273 bool ret = true;
0274
0275 memset(&cal_sram_valid, 0, sizeof(cal_sram_valid));
0276 memset(&aic_sram, 0, sizeof(aic_sram));
0277
0278 for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) {
0279 struct ath_aic_sram_info sram;
0280 value = aic->aic_sram[i];
0281
0282 cal_sram_valid[i] = sram.valid =
0283 MS(value, AR_PHY_AIC_SRAM_VALID);
0284 sram.rot_quad_att_db =
0285 MS(value, AR_PHY_AIC_SRAM_ROT_QUAD_ATT_DB);
0286 sram.vga_quad_sign =
0287 MS(value, AR_PHY_AIC_SRAM_VGA_QUAD_SIGN);
0288 sram.rot_dir_att_db =
0289 MS(value, AR_PHY_AIC_SRAM_ROT_DIR_ATT_DB);
0290 sram.vga_dir_sign =
0291 MS(value, AR_PHY_AIC_SRAM_VGA_DIR_SIGN);
0292 sram.com_att_6db =
0293 MS(value, AR_PHY_AIC_SRAM_COM_ATT_6DB);
0294
0295 if (sram.valid) {
0296 dir_path_gain_idx = sram.rot_dir_att_db +
0297 com_att_db_table[sram.com_att_6db];
0298 quad_path_gain_idx = sram.rot_quad_att_db +
0299 com_att_db_table[sram.com_att_6db];
0300
0301 dir_path_sign = (sram.vga_dir_sign) ? 1 : -1;
0302 quad_path_sign = (sram.vga_quad_sign) ? 1 : -1;
0303
0304 aic_sram[i].dir_path_gain_lin = dir_path_sign *
0305 aic_lin_table[dir_path_gain_idx];
0306 aic_sram[i].quad_path_gain_lin = quad_path_sign *
0307 aic_lin_table[quad_path_gain_idx];
0308 }
0309 }
0310
0311 for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) {
0312 int16_t start_idx, end_idx;
0313
0314 if (cal_sram_valid[i])
0315 continue;
0316
0317 start_idx = ar9003_aic_find_valid(cal_sram_valid, 0, i);
0318 end_idx = ar9003_aic_find_valid(cal_sram_valid, 1, i);
0319
0320 if (start_idx < 0) {
0321
0322 start_idx = end_idx;
0323 end_idx = ar9003_aic_find_valid(cal_sram_valid, 1, start_idx);
0324
0325 if (end_idx < 0) {
0326 ret = false;
0327 break;
0328 }
0329
0330 aic_sram[i].dir_path_gain_lin =
0331 ((aic_sram[start_idx].dir_path_gain_lin -
0332 aic_sram[end_idx].dir_path_gain_lin) *
0333 (start_idx - i) + ((end_idx - i) >> 1)) /
0334 (end_idx - i) +
0335 aic_sram[start_idx].dir_path_gain_lin;
0336 aic_sram[i].quad_path_gain_lin =
0337 ((aic_sram[start_idx].quad_path_gain_lin -
0338 aic_sram[end_idx].quad_path_gain_lin) *
0339 (start_idx - i) + ((end_idx - i) >> 1)) /
0340 (end_idx - i) +
0341 aic_sram[start_idx].quad_path_gain_lin;
0342 }
0343
0344 if (end_idx < 0) {
0345
0346 end_idx = ar9003_aic_find_valid(cal_sram_valid, 0, start_idx);
0347
0348 if (end_idx < 0) {
0349 ret = false;
0350 break;
0351 }
0352
0353 aic_sram[i].dir_path_gain_lin =
0354 ((aic_sram[start_idx].dir_path_gain_lin -
0355 aic_sram[end_idx].dir_path_gain_lin) *
0356 (i - start_idx) + ((start_idx - end_idx) >> 1)) /
0357 (start_idx - end_idx) +
0358 aic_sram[start_idx].dir_path_gain_lin;
0359 aic_sram[i].quad_path_gain_lin =
0360 ((aic_sram[start_idx].quad_path_gain_lin -
0361 aic_sram[end_idx].quad_path_gain_lin) *
0362 (i - start_idx) + ((start_idx - end_idx) >> 1)) /
0363 (start_idx - end_idx) +
0364 aic_sram[start_idx].quad_path_gain_lin;
0365
0366 } else if (start_idx >= 0){
0367
0368 aic_sram[i].dir_path_gain_lin =
0369 (((end_idx - i) * aic_sram[start_idx].dir_path_gain_lin) +
0370 ((i - start_idx) * aic_sram[end_idx].dir_path_gain_lin) +
0371 ((end_idx - start_idx) >> 1)) /
0372 (end_idx - start_idx);
0373 aic_sram[i].quad_path_gain_lin =
0374 (((end_idx - i) * aic_sram[start_idx].quad_path_gain_lin) +
0375 ((i - start_idx) * aic_sram[end_idx].quad_path_gain_lin) +
0376 ((end_idx - start_idx) >> 1))/
0377 (end_idx - start_idx);
0378 }
0379 }
0380
0381
0382 i = ar9003_aic_find_valid(cal_sram_valid, 1, 0);
0383 if (i < 0) {
0384 i = 0;
0385 ret = false;
0386 }
0387 fixed_com_att_db = com_att_db_table[MS(aic->aic_sram[i],
0388 AR_PHY_AIC_SRAM_COM_ATT_6DB)];
0389
0390 for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) {
0391 int16_t rot_dir_path_att_db, rot_quad_path_att_db;
0392 struct ath_aic_sram_info sram;
0393
0394 sram.vga_dir_sign =
0395 (aic_sram[i].dir_path_gain_lin >= 0) ? 1 : 0;
0396 sram.vga_quad_sign =
0397 (aic_sram[i].quad_path_gain_lin >= 0) ? 1 : 0;
0398
0399 rot_dir_path_att_db =
0400 ar9003_aic_find_index(0, abs(aic_sram[i].dir_path_gain_lin)) -
0401 fixed_com_att_db;
0402 rot_quad_path_att_db =
0403 ar9003_aic_find_index(0, abs(aic_sram[i].quad_path_gain_lin)) -
0404 fixed_com_att_db;
0405
0406 sram.com_att_6db =
0407 ar9003_aic_find_index(1, fixed_com_att_db);
0408
0409 sram.valid = true;
0410
0411 sram.rot_dir_att_db =
0412 min(max(rot_dir_path_att_db,
0413 (int16_t)ATH_AIC_MIN_ROT_DIR_ATT_DB),
0414 ATH_AIC_MAX_ROT_DIR_ATT_DB);
0415 sram.rot_quad_att_db =
0416 min(max(rot_quad_path_att_db,
0417 (int16_t)ATH_AIC_MIN_ROT_QUAD_ATT_DB),
0418 ATH_AIC_MAX_ROT_QUAD_ATT_DB);
0419
0420 aic->aic_sram[i] = (SM(sram.vga_dir_sign,
0421 AR_PHY_AIC_SRAM_VGA_DIR_SIGN) |
0422 SM(sram.vga_quad_sign,
0423 AR_PHY_AIC_SRAM_VGA_QUAD_SIGN) |
0424 SM(sram.com_att_6db,
0425 AR_PHY_AIC_SRAM_COM_ATT_6DB) |
0426 SM(sram.valid,
0427 AR_PHY_AIC_SRAM_VALID) |
0428 SM(sram.rot_dir_att_db,
0429 AR_PHY_AIC_SRAM_ROT_DIR_ATT_DB) |
0430 SM(sram.rot_quad_att_db,
0431 AR_PHY_AIC_SRAM_ROT_QUAD_ATT_DB));
0432 }
0433
0434 return ret;
0435 }
0436
0437 static void ar9003_aic_cal_done(struct ath_hw *ah)
0438 {
0439 struct ath9k_hw_aic *aic = &ah->btcoex_hw.aic;
0440
0441
0442 REG_WRITE(ah, ATH_AIC_BT_JUPITER_CTRL,
0443 (REG_READ(ah, ATH_AIC_BT_JUPITER_CTRL) &
0444 ~ATH_AIC_BT_AIC_ENABLE));
0445
0446 if (ar9003_aic_cal_post_process(ah))
0447 aic->aic_cal_state = AIC_CAL_STATE_DONE;
0448 else
0449 aic->aic_cal_state = AIC_CAL_STATE_ERROR;
0450 }
0451
0452 static u8 ar9003_aic_cal_continue(struct ath_hw *ah, bool cal_once)
0453 {
0454 struct ath_common *common = ath9k_hw_common(ah);
0455 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
0456 struct ath9k_hw_aic *aic = &ah->btcoex_hw.aic;
0457 int i, num_chan;
0458
0459 num_chan = MS(mci_hw->config, ATH_MCI_CONFIG_AIC_CAL_NUM_CHAN);
0460
0461 if (!num_chan) {
0462 aic->aic_cal_state = AIC_CAL_STATE_ERROR;
0463 return aic->aic_cal_state;
0464 }
0465
0466 if (cal_once) {
0467 for (i = 0; i < 10000; i++) {
0468 if ((REG_READ(ah, AR_PHY_AIC_CTRL_0_B1) &
0469 AR_PHY_AIC_CAL_ENABLE) == 0)
0470 break;
0471
0472 udelay(100);
0473 }
0474 }
0475
0476
0477
0478
0479
0480 if ((REG_READ(ah, AR_PHY_AIC_CTRL_0_B1) &
0481 AR_PHY_AIC_CAL_ENABLE) != 0) {
0482 ath_dbg(common, MCI, "AIC cal is not done after 40ms");
0483 goto exit;
0484 }
0485
0486 REG_WRITE(ah, AR_PHY_AIC_SRAM_ADDR_B1,
0487 (ATH_AIC_SRAM_CAL_OFFSET | ATH_AIC_SRAM_AUTO_INCREMENT));
0488
0489 for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) {
0490 u32 value;
0491
0492 value = REG_READ(ah, AR_PHY_AIC_SRAM_DATA_B1);
0493
0494 if (value & 0x01) {
0495 if (aic->aic_sram[i] == 0)
0496 aic->aic_caled_chan++;
0497
0498 aic->aic_sram[i] = value;
0499
0500 if (!cal_once)
0501 break;
0502 }
0503 }
0504
0505 if ((aic->aic_caled_chan >= num_chan) || cal_once) {
0506 ar9003_aic_cal_done(ah);
0507 } else {
0508
0509 REG_CLR_BIT(ah, AR_PHY_AIC_CTRL_0_B1, AR_PHY_AIC_CAL_ENABLE);
0510 REG_SET_BIT(ah, AR_PHY_AIC_CTRL_0_B1,
0511 AR_PHY_AIC_CAL_CH_VALID_RESET);
0512 REG_SET_BIT(ah, AR_PHY_AIC_CTRL_0_B1, AR_PHY_AIC_CAL_ENABLE);
0513 }
0514 exit:
0515 return aic->aic_cal_state;
0516
0517 }
0518
0519 u8 ar9003_aic_calibration(struct ath_hw *ah)
0520 {
0521 struct ath9k_hw_aic *aic = &ah->btcoex_hw.aic;
0522 u8 cal_ret = AIC_CAL_STATE_ERROR;
0523
0524 switch (aic->aic_cal_state) {
0525 case AIC_CAL_STATE_IDLE:
0526 cal_ret = ar9003_aic_cal_start(ah, 1);
0527 break;
0528 case AIC_CAL_STATE_STARTED:
0529 cal_ret = ar9003_aic_cal_continue(ah, false);
0530 break;
0531 case AIC_CAL_STATE_DONE:
0532 cal_ret = AIC_CAL_STATE_DONE;
0533 break;
0534 default:
0535 break;
0536 }
0537
0538 return cal_ret;
0539 }
0540
0541 u8 ar9003_aic_start_normal(struct ath_hw *ah)
0542 {
0543 struct ath9k_hw_aic *aic = &ah->btcoex_hw.aic;
0544 int16_t i;
0545
0546 if (aic->aic_cal_state != AIC_CAL_STATE_DONE)
0547 return 1;
0548
0549 ar9003_aic_gain_table(ah);
0550
0551 REG_WRITE(ah, AR_PHY_AIC_SRAM_ADDR_B1, ATH_AIC_SRAM_AUTO_INCREMENT);
0552
0553 for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) {
0554 REG_WRITE(ah, AR_PHY_AIC_SRAM_DATA_B1, aic->aic_sram[i]);
0555 }
0556
0557
0558 REG_WRITE(ah, 0xa6b0, 0x80);
0559 REG_WRITE(ah, 0xa6b4, 0x5b2df0);
0560 REG_WRITE(ah, 0xa6b8, 0x10762cc8);
0561 REG_WRITE(ah, 0xa6bc, 0x1219a4b);
0562 REG_WRITE(ah, 0xa6c0, 0x1e01);
0563 REG_WRITE(ah, 0xb6b4, 0xf0);
0564 REG_WRITE(ah, 0xb6c0, 0x1e01);
0565 REG_WRITE(ah, 0xb6b0, 0x81);
0566 REG_WRITE(ah, AR_PHY_65NM_CH1_RXTX4, 0x40000000);
0567
0568 aic->aic_enabled = true;
0569
0570 return 0;
0571 }
0572
0573 u8 ar9003_aic_cal_reset(struct ath_hw *ah)
0574 {
0575 struct ath9k_hw_aic *aic = &ah->btcoex_hw.aic;
0576
0577 aic->aic_cal_state = AIC_CAL_STATE_IDLE;
0578 return aic->aic_cal_state;
0579 }
0580
0581 u8 ar9003_aic_calibration_single(struct ath_hw *ah)
0582 {
0583 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
0584 u8 cal_ret;
0585 int num_chan;
0586
0587 num_chan = MS(mci_hw->config, ATH_MCI_CONFIG_AIC_CAL_NUM_CHAN);
0588
0589 (void) ar9003_aic_cal_start(ah, num_chan);
0590 cal_ret = ar9003_aic_cal_continue(ah, true);
0591
0592 return cal_ret;
0593 }
0594
0595 void ar9003_hw_attach_aic_ops(struct ath_hw *ah)
0596 {
0597 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
0598
0599 priv_ops->is_aic_enabled = ar9003_hw_is_aic_enabled;
0600 }