1 /* 2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 2008 Atheros Communications Inc. 8 * 9 * Permission to use, copy, modify, and/or distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 #include "arn_core.h" 23 #include "arn_hw.h" 24 #include "arn_reg.h" 25 #include "arn_phy.h" 26 27 /* ARGSUSED */ 28 void 29 ath9k_hw_write_regs(struct ath_hal *ah, uint32_t modesIndex, uint32_t freqIndex, 30 int regWrites) 31 { 32 struct ath_hal_5416 *ahp = AH5416(ah); 33 34 /* LINTED: E_CONSTANT_CONDITION */ 35 REG_WRITE_ARRAY(&ahp->ah_iniBB_RfGain, freqIndex, regWrites); 36 } 37 38 boolean_t 39 ath9k_hw_set_channel(struct ath_hal *ah, struct ath9k_channel *chan) 40 { 41 uint32_t channelSel = 0; 42 uint32_t bModeSynth = 0; 43 uint32_t aModeRefSel = 0; 44 uint32_t reg32 = 0; 45 uint16_t freq; 46 struct chan_centers centers; 47 48 ath9k_hw_get_channel_centers(ah, chan, ¢ers); 49 freq = centers.synth_center; 50 51 if (freq < 4800) { 52 uint32_t txctl; 53 54 if (((freq - 2192) % 5) == 0) { 55 channelSel = ((freq - 672) * 2 - 3040) / 10; 56 bModeSynth = 0; 57 } else if (((freq - 2224) % 5) == 0) { 58 channelSel = ((freq - 704) * 2 - 3040) / 10; 59 bModeSynth = 1; 60 } else { 61 arn_problem("%s: invalid channel %u MHz\n", 62 __func__, freq); 63 return (B_FALSE); 64 } 65 66 channelSel = (channelSel << 2) & 0xff; 67 channelSel = ath9k_hw_reverse_bits(channelSel, 8); 68 69 txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); 70 if (freq == 2484) { 71 72 REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, 73 txctl | AR_PHY_CCK_TX_CTRL_JAPAN); 74 } else { 75 REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, 76 txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); 77 } 78 79 } else if ((freq % 20) == 0 && freq >= 5120) { 80 channelSel = 81 ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8); 82 aModeRefSel = ath9k_hw_reverse_bits(1, 2); 83 } else if ((freq % 10) == 0) { 84 channelSel = 85 ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8); 86 if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) 87 aModeRefSel = ath9k_hw_reverse_bits(2, 2); 88 else 89 aModeRefSel = ath9k_hw_reverse_bits(1, 2); 90 } else if ((freq % 5) == 0) { 91 channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8); 92 aModeRefSel = ath9k_hw_reverse_bits(1, 2); 93 } else { 94 arn_problem("%s: invalid channel %u MHz\n", __func__, freq); 95 return (B_FALSE); 96 } 97 98 reg32 = 99 (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | 100 (1 << 5) | 0x1; 101 102 REG_WRITE(ah, AR_PHY(0x37), reg32); 103 104 ah->ah_curchan = chan; 105 106 AH5416(ah)->ah_curchanRadIndex = -1; 107 108 return (B_TRUE); 109 } 110 111 boolean_t 112 ath9k_hw_ar9280_set_channel(struct ath_hal *ah, 113 struct ath9k_channel *chan) 114 { 115 uint16_t bMode, fracMode, aModeRefSel = 0; 116 uint32_t freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0; 117 struct chan_centers centers; 118 uint32_t refDivA = 24; 119 120 ath9k_hw_get_channel_centers(ah, chan, ¢ers); 121 freq = centers.synth_center; 122 123 reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL); 124 reg32 &= 0xc0000000; 125 126 if (freq < 4800) { 127 uint32_t txctl; 128 129 bMode = 1; 130 fracMode = 1; 131 aModeRefSel = 0; 132 channelSel = (freq * 0x10000) / 15; 133 134 txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); 135 if (freq == 2484) { 136 137 REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, 138 txctl | AR_PHY_CCK_TX_CTRL_JAPAN); 139 } else { 140 REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, 141 txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); 142 } 143 } else { 144 bMode = 0; 145 fracMode = 0; 146 147 if ((freq % 20) == 0) { 148 aModeRefSel = 3; 149 } else if ((freq % 10) == 0) { 150 aModeRefSel = 2; 151 } else { 152 aModeRefSel = 0; 153 154 fracMode = 1; 155 refDivA = 1; 156 channelSel = (freq * 0x8000) / 15; 157 158 REG_RMW_FIELD(ah, AR_AN_SYNTH9, 159 AR_AN_SYNTH9_REFDIVA, refDivA); 160 } 161 if (!fracMode) { 162 ndiv = (freq * (refDivA >> aModeRefSel)) / 60; 163 channelSel = ndiv & 0x1ff; 164 channelFrac = (ndiv & 0xfffffe00) * 2; 165 channelSel = (channelSel << 17) | channelFrac; 166 } 167 } 168 169 reg32 = reg32 | 170 (bMode << 29) | 171 (fracMode << 28) | (aModeRefSel << 26) | (channelSel); 172 173 REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32); 174 175 ah->ah_curchan = chan; 176 177 AH5416(ah)->ah_curchanRadIndex = -1; 178 179 return (B_TRUE); 180 } 181 182 static void 183 ath9k_phy_modify_rx_buffer(uint32_t *rfBuf, uint32_t reg32, 184 uint32_t numBits, uint32_t firstBit, uint32_t column) 185 { 186 uint32_t tmp32, mask, arrayEntry, lastBit; 187 int32_t bitPosition, bitsLeft; 188 189 tmp32 = ath9k_hw_reverse_bits(reg32, numBits); 190 arrayEntry = (firstBit - 1) / 8; 191 bitPosition = (firstBit - 1) % 8; 192 bitsLeft = numBits; 193 while (bitsLeft > 0) { 194 lastBit = (bitPosition + bitsLeft > 8) ? 195 8 : bitPosition + bitsLeft; 196 mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) << 197 (column * 8); 198 rfBuf[arrayEntry] &= ~mask; 199 rfBuf[arrayEntry] |= ((tmp32 << bitPosition) << 200 (column * 8)) & mask; 201 bitsLeft -= 8 - bitPosition; 202 tmp32 = tmp32 >> (8 - bitPosition); 203 bitPosition = 0; 204 arrayEntry++; 205 } 206 } 207 208 boolean_t 209 ath9k_hw_set_rf_regs(struct ath_hal *ah, struct ath9k_channel *chan, 210 uint16_t modesIndex) 211 { 212 struct ath_hal_5416 *ahp = AH5416(ah); 213 214 uint32_t eepMinorRev; 215 uint32_t ob5GHz = 0, db5GHz = 0; 216 uint32_t ob2GHz = 0, db2GHz = 0; 217 /* LINTED E_FUNC_SET_NOT_USED */ 218 int regWrites = 0; 219 220 if (AR_SREV_9280_10_OR_LATER(ah)) 221 return (B_TRUE); 222 223 eepMinorRev = ath9k_hw_get_eeprom(ah, EEP_MINOR_REV); 224 225 RF_BANK_SETUP(ahp->ah_analogBank0Data, &ahp->ah_iniBank0, 1); 226 227 RF_BANK_SETUP(ahp->ah_analogBank1Data, &ahp->ah_iniBank1, 1); 228 229 RF_BANK_SETUP(ahp->ah_analogBank2Data, &ahp->ah_iniBank2, 1); 230 231 RF_BANK_SETUP(ahp->ah_analogBank3Data, &ahp->ah_iniBank3, 232 modesIndex); 233 { 234 int i; 235 for (i = 0; i < ahp->ah_iniBank6TPC.ia_rows; i++) { 236 ahp->ah_analogBank6Data[i] = 237 INI_RA(&ahp->ah_iniBank6TPC, i, modesIndex); 238 } 239 } 240 241 if (eepMinorRev >= 2) { 242 if (IS_CHAN_2GHZ(chan)) { 243 ob2GHz = ath9k_hw_get_eeprom(ah, EEP_OB_2); 244 db2GHz = ath9k_hw_get_eeprom(ah, EEP_DB_2); 245 ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data, 246 ob2GHz, 3, 197, 0); 247 ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data, 248 db2GHz, 3, 194, 0); 249 } else { 250 ob5GHz = ath9k_hw_get_eeprom(ah, EEP_OB_5); 251 db5GHz = ath9k_hw_get_eeprom(ah, EEP_DB_5); 252 ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data, 253 ob5GHz, 3, 203, 0); 254 ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data, 255 db5GHz, 3, 200, 0); 256 } 257 } 258 259 RF_BANK_SETUP(ahp->ah_analogBank7Data, &ahp->ah_iniBank7, 1); 260 261 REG_WRITE_RF_ARRAY(&ahp->ah_iniBank0, ahp->ah_analogBank0Data, 262 regWrites); 263 264 REG_WRITE_RF_ARRAY(&ahp->ah_iniBank1, ahp->ah_analogBank1Data, 265 regWrites); 266 267 REG_WRITE_RF_ARRAY(&ahp->ah_iniBank2, ahp->ah_analogBank2Data, 268 regWrites); 269 270 REG_WRITE_RF_ARRAY(&ahp->ah_iniBank3, ahp->ah_analogBank3Data, 271 regWrites); 272 273 REG_WRITE_RF_ARRAY(&ahp->ah_iniBank6TPC, ahp->ah_analogBank6Data, 274 regWrites); 275 276 REG_WRITE_RF_ARRAY(&ahp->ah_iniBank7, ahp->ah_analogBank7Data, 277 regWrites); 278 279 return (B_TRUE); 280 } 281 282 void 283 ath9k_hw_rfdetach(struct ath_hal *ah) 284 { 285 struct ath_hal_5416 *ahp = AH5416(ah); 286 287 if (ahp->ah_analogBank0Data != NULL) { 288 kmem_free(ahp->ah_analogBank0Data, 289 (sizeof (uint32_t) * ahp->ah_iniBank0.ia_rows)); 290 ahp->ah_analogBank0Data = NULL; 291 } 292 if (ahp->ah_analogBank1Data != NULL) { 293 kmem_free(ahp->ah_analogBank1Data, 294 (sizeof (uint32_t) * ahp->ah_iniBank1.ia_rows)); 295 ahp->ah_analogBank1Data = NULL; 296 } 297 if (ahp->ah_analogBank2Data != NULL) { 298 kmem_free(ahp->ah_analogBank2Data, 299 (sizeof (uint32_t) * ahp->ah_iniBank2.ia_rows)); 300 ahp->ah_analogBank2Data = NULL; 301 } 302 if (ahp->ah_analogBank3Data != NULL) { 303 kmem_free(ahp->ah_analogBank3Data, 304 (sizeof (uint32_t) * ahp->ah_iniBank3.ia_rows)); 305 ahp->ah_analogBank3Data = NULL; 306 } 307 if (ahp->ah_analogBank6Data != NULL) { 308 kmem_free(ahp->ah_analogBank6Data, 309 (sizeof (uint32_t) * ahp->ah_iniBank6.ia_rows)); 310 ahp->ah_analogBank6Data = NULL; 311 } 312 if (ahp->ah_analogBank6TPCData != NULL) { 313 kmem_free(ahp->ah_analogBank6TPCData, 314 (sizeof (uint32_t) * ahp->ah_iniBank6TPC.ia_rows)); 315 ahp->ah_analogBank6TPCData = NULL; 316 } 317 if (ahp->ah_analogBank7Data != NULL) { 318 kmem_free(ahp->ah_analogBank7Data, 319 (sizeof (uint32_t) * ahp->ah_iniBank7.ia_rows)); 320 ahp->ah_analogBank7Data = NULL; 321 } 322 if (ahp->ah_addac5416_21 != NULL) { 323 kmem_free(ahp->ah_addac5416_21, 324 (sizeof (uint32_t) * ahp->ah_iniAddac.ia_rows * 325 ahp->ah_iniAddac.ia_columns)); 326 ahp->ah_addac5416_21 = NULL; 327 } 328 if (ahp->ah_bank6Temp != NULL) { 329 kmem_free(ahp->ah_bank6Temp, 330 (sizeof (uint32_t) * ahp->ah_iniBank6.ia_rows)); 331 ahp->ah_bank6Temp = NULL; 332 } 333 } 334 335 boolean_t 336 ath9k_hw_init_rf(struct ath_hal *ah, int *status) 337 { 338 struct ath_hal_5416 *ahp = AH5416(ah); 339 340 if (!AR_SREV_9280_10_OR_LATER(ah)) { 341 342 ahp->ah_analogBank0Data = 343 kmem_zalloc((sizeof (uint32_t) * 344 ahp->ah_iniBank0.ia_rows), KM_SLEEP); 345 ahp->ah_analogBank1Data = 346 kmem_zalloc((sizeof (uint32_t) * 347 ahp->ah_iniBank1.ia_rows), KM_SLEEP); 348 ahp->ah_analogBank2Data = 349 kmem_zalloc((sizeof (uint32_t) * 350 ahp->ah_iniBank2.ia_rows), KM_SLEEP); 351 ahp->ah_analogBank3Data = 352 kmem_zalloc((sizeof (uint32_t) * 353 ahp->ah_iniBank3.ia_rows), KM_SLEEP); 354 ahp->ah_analogBank6Data = 355 kmem_zalloc((sizeof (uint32_t) * 356 ahp->ah_iniBank6.ia_rows), KM_SLEEP); 357 ahp->ah_analogBank6TPCData = 358 kmem_zalloc((sizeof (uint32_t) * 359 ahp->ah_iniBank6TPC.ia_rows), KM_SLEEP); 360 ahp->ah_analogBank7Data = 361 kmem_zalloc((sizeof (uint32_t) * 362 ahp->ah_iniBank7.ia_rows), KM_SLEEP); 363 364 if (ahp->ah_analogBank0Data == NULL || 365 ahp->ah_analogBank1Data == NULL || 366 ahp->ah_analogBank2Data == NULL || 367 ahp->ah_analogBank3Data == NULL || 368 ahp->ah_analogBank6Data == NULL || 369 ahp->ah_analogBank6TPCData == NULL || 370 ahp->ah_analogBank7Data == NULL) { 371 ARN_DBG((ARN_DBG_FATAL, "arn: ath9k_hw_init_rf(): " 372 "cannot allocate RF banks\n")); 373 *status = ENOMEM; 374 return (B_FALSE); 375 } 376 377 ahp->ah_addac5416_21 = 378 kmem_zalloc((sizeof (uint32_t) * 379 ahp->ah_iniAddac.ia_rows * 380 ahp->ah_iniAddac.ia_columns), KM_SLEEP); 381 if (ahp->ah_addac5416_21 == NULL) { 382 ARN_DBG((ARN_DBG_FATAL, "arn: ath9k_hw_init_rf(): " 383 "cannot allocate ah_addac5416_21\n")); 384 *status = ENOMEM; 385 return (B_FALSE); 386 } 387 388 ahp->ah_bank6Temp = 389 kmem_zalloc((sizeof (uint32_t) * 390 ahp->ah_iniBank6.ia_rows), KM_SLEEP); 391 if (ahp->ah_bank6Temp == NULL) { 392 ARN_DBG((ARN_DBG_FATAL, "arn: ath9k_hw_init_rf(): " 393 "cannot allocate ah_bank6Temp\n")); 394 *status = ENOMEM; 395 return (B_FALSE); 396 } 397 } 398 399 return (B_TRUE); 400 } 401 402 /* ARGSUSED */ 403 void 404 ath9k_hw_decrease_chain_power(struct ath_hal *ah, struct ath9k_channel *chan) 405 { 406 /* LINTED E_FUNC_SET_NOT_USED */ 407 int i, regWrites = 0; 408 struct ath_hal_5416 *ahp = AH5416(ah); 409 uint32_t bank6SelMask; 410 uint32_t *bank6Temp = ahp->ah_bank6Temp; 411 412 switch (ahp->ah_diversityControl) { 413 case ATH9K_ANT_FIXED_A: 414 bank6SelMask = 415 (ahp-> ah_antennaSwitchSwap & ANTSWAP_AB) ? REDUCE_CHAIN_0 : 416 REDUCE_CHAIN_1; 417 break; 418 case ATH9K_ANT_FIXED_B: 419 bank6SelMask = 420 (ahp-> ah_antennaSwitchSwap & ANTSWAP_AB) ? REDUCE_CHAIN_1 : 421 REDUCE_CHAIN_0; 422 break; 423 case ATH9K_ANT_VARIABLE: 424 default: 425 return; 426 } 427 428 for (i = 0; i < ahp->ah_iniBank6.ia_rows; i++) 429 bank6Temp[i] = ahp->ah_analogBank6Data[i]; 430 431 REG_WRITE(ah, AR_PHY_BASE + 0xD8, bank6SelMask); 432 433 ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 189, 0); 434 ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 190, 0); 435 ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 191, 0); 436 ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 192, 0); 437 ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 193, 0); 438 ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 222, 0); 439 ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 245, 0); 440 ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 246, 0); 441 ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 247, 0); 442 443 REG_WRITE_RF_ARRAY(&ahp->ah_iniBank6, bank6Temp, regWrites); 444 445 REG_WRITE(ah, AR_PHY_BASE + 0xD8, 0x00000053); 446 #ifdef ALTER_SWITCH 447 REG_WRITE(ah, PHY_SWITCH_CHAIN_0, 448 (REG_READ(ah, PHY_SWITCH_CHAIN_0) & ~0x38) 449 | ((REG_READ(ah, PHY_SWITCH_CHAIN_0) >> 3) & 0x38)); 450 #endif 451 } 452