1 /* $OpenBSD: ar9285.c,v 1.18 2011/01/15 11:39:28 damien Exp $ */ 2 3 /*- 4 * Copyright (c) 2009-2010 Damien Bergamini <damien.bergamini@free.fr> 5 * Copyright (c) 2008-2010 Atheros Communications Inc. 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /* 21 * Driver for Atheros 802.11a/g/n chipsets. 22 * Routines for AR9285 and AR9271 chipsets. 23 */ 24 25 #include "athn_usb.h" 26 #include "bpfilter.h" 27 28 #include <sys/param.h> 29 #include <sys/sockio.h> 30 #include <sys/mbuf.h> 31 #include <sys/kernel.h> 32 #include <sys/socket.h> 33 #include <sys/systm.h> 34 #include <sys/malloc.h> 35 #include <sys/queue.h> 36 #include <sys/timeout.h> 37 #include <sys/conf.h> 38 #include <sys/device.h> 39 40 #include <machine/bus.h> 41 #include <machine/endian.h> 42 #include <machine/intr.h> 43 44 #if NBPFILTER > 0 45 #include <net/bpf.h> 46 #endif 47 #include <net/if.h> 48 #include <net/if_arp.h> 49 #include <net/if_dl.h> 50 #include <net/if_media.h> 51 #include <net/if_types.h> 52 53 #include <netinet/in.h> 54 #include <netinet/in_systm.h> 55 #include <netinet/in_var.h> 56 #include <netinet/if_ether.h> 57 #include <netinet/ip.h> 58 59 #include <net80211/ieee80211_var.h> 60 #include <net80211/ieee80211_amrr.h> 61 #include <net80211/ieee80211_radiotap.h> 62 63 #include <dev/ic/athnreg.h> 64 #include <dev/ic/athnvar.h> 65 66 #include <dev/ic/ar5008reg.h> 67 #include <dev/ic/ar9280reg.h> 68 #include <dev/ic/ar9285reg.h> 69 70 int ar9285_attach(struct athn_softc *); 71 void ar9285_setup(struct athn_softc *); 72 void ar9285_swap_rom(struct athn_softc *); 73 const struct ar_spur_chan *ar9285_get_spur_chans(struct athn_softc *, int); 74 void ar9285_init_from_rom(struct athn_softc *, struct ieee80211_channel *, 75 struct ieee80211_channel *); 76 void ar9285_pa_calib(struct athn_softc *); 77 void ar9271_pa_calib(struct athn_softc *); 78 int ar9285_cl_cal(struct athn_softc *, struct ieee80211_channel *, 79 struct ieee80211_channel *); 80 void ar9271_load_ani(struct athn_softc *); 81 int ar9285_init_calib(struct athn_softc *, struct ieee80211_channel *, 82 struct ieee80211_channel *); 83 void ar9285_get_pdadcs(struct athn_softc *, struct ieee80211_channel *, 84 int, uint8_t, uint8_t *, uint8_t *); 85 void ar9285_set_power_calib(struct athn_softc *, 86 struct ieee80211_channel *); 87 void ar9285_set_txpower(struct athn_softc *, struct ieee80211_channel *, 88 struct ieee80211_channel *); 89 90 /* Extern functions. */ 91 uint8_t athn_chan2fbin(struct ieee80211_channel *); 92 void athn_get_pier_ival(uint8_t, const uint8_t *, int, int *, int *); 93 int ar5008_attach(struct athn_softc *); 94 void ar5008_write_txpower(struct athn_softc *, int16_t power[]); 95 void ar5008_get_pdadcs(struct athn_softc *, uint8_t, struct athn_pier *, 96 struct athn_pier *, int, int, uint8_t, uint8_t *, uint8_t *); 97 void ar5008_get_lg_tpow(struct athn_softc *, struct ieee80211_channel *, 98 uint8_t, const struct ar_cal_target_power_leg *, int, uint8_t[]); 99 void ar5008_get_ht_tpow(struct athn_softc *, struct ieee80211_channel *, 100 uint8_t, const struct ar_cal_target_power_ht *, int, uint8_t[]); 101 int ar9280_set_synth(struct athn_softc *, struct ieee80211_channel *, 102 struct ieee80211_channel *); 103 void ar9280_spur_mitigate(struct athn_softc *, struct ieee80211_channel *, 104 struct ieee80211_channel *); 105 106 107 int 108 ar9285_attach(struct athn_softc *sc) 109 { 110 sc->eep_base = AR9285_EEP_START_LOC; 111 sc->eep_size = sizeof(struct ar9285_eeprom); 112 sc->def_nf = AR9285_PHY_CCA_MAX_GOOD_VALUE; 113 sc->ngpiopins = (sc->flags & ATHN_FLAG_USB) ? 16 : 12; 114 sc->led_pin = (sc->flags & ATHN_FLAG_USB) ? 15 : 1; 115 sc->workaround = AR9285_WA_DEFAULT; 116 sc->ops.setup = ar9285_setup; 117 sc->ops.swap_rom = ar9285_swap_rom; 118 sc->ops.init_from_rom = ar9285_init_from_rom; 119 sc->ops.set_txpower = ar9285_set_txpower; 120 sc->ops.set_synth = ar9280_set_synth; 121 sc->ops.spur_mitigate = ar9280_spur_mitigate; 122 sc->ops.get_spur_chans = ar9285_get_spur_chans; 123 #if NATHN_USB > 0 124 if (AR_SREV_9271(sc)) 125 sc->ini = &ar9271_ini; 126 else 127 #endif 128 sc->ini = &ar9285_1_2_ini; 129 sc->serdes = ar9280_2_0_serdes; 130 131 return (ar5008_attach(sc)); 132 } 133 134 void 135 ar9285_setup(struct athn_softc *sc) 136 { 137 const struct ar9285_eeprom *eep = sc->eep; 138 uint8_t type; 139 140 /* Select initialization values based on ROM. */ 141 type = eep->baseEepHeader.txGainType; 142 DPRINTF(("Tx gain type=0x%x\n", type)); 143 #if NATHN_USB > 0 144 if (AR_SREV_9271(sc)) { 145 if (type == AR_EEP_TXGAIN_HIGH_POWER) 146 sc->tx_gain = &ar9271_tx_gain_high_power; 147 else 148 sc->tx_gain = &ar9271_tx_gain; 149 } else 150 #endif /* NATHN_USB */ 151 if ((AR_READ(sc, AR_AN_SYNTH9) & 0x7) == 0x1) { /* XE rev. */ 152 if (type == AR_EEP_TXGAIN_HIGH_POWER) 153 sc->tx_gain = &ar9285_2_0_tx_gain_high_power; 154 else 155 sc->tx_gain = &ar9285_2_0_tx_gain; 156 } else { 157 if (type == AR_EEP_TXGAIN_HIGH_POWER) 158 sc->tx_gain = &ar9285_1_2_tx_gain_high_power; 159 else 160 sc->tx_gain = &ar9285_1_2_tx_gain; 161 } 162 } 163 164 void 165 ar9285_swap_rom(struct athn_softc *sc) 166 { 167 struct ar9285_eeprom *eep = sc->eep; 168 int i; 169 170 eep->modalHeader.antCtrlCommon = 171 swap32(eep->modalHeader.antCtrlCommon); 172 eep->modalHeader.antCtrlChain = 173 swap32(eep->modalHeader.antCtrlChain); 174 175 for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { 176 eep->modalHeader.spurChans[i].spurChan = 177 swap16(eep->modalHeader.spurChans[i].spurChan); 178 } 179 } 180 181 const struct ar_spur_chan * 182 ar9285_get_spur_chans(struct athn_softc *sc, int is2ghz) 183 { 184 const struct ar9285_eeprom *eep = sc->eep; 185 186 KASSERT(is2ghz); 187 return (eep->modalHeader.spurChans); 188 } 189 190 void 191 ar9285_init_from_rom(struct athn_softc *sc, struct ieee80211_channel *c, 192 struct ieee80211_channel *extc) 193 { 194 const struct ar9285_eeprom *eep = sc->eep; 195 const struct ar9285_modal_eep_header *modal = &eep->modalHeader; 196 uint32_t reg, offset = 0x1000; 197 uint8_t ob[5], db1[5], db2[5]; 198 uint8_t txRxAtten; 199 200 AR_WRITE(sc, AR_PHY_SWITCH_COM, modal->antCtrlCommon); 201 AR_WRITE(sc, AR_PHY_SWITCH_CHAIN_0, modal->antCtrlChain); 202 203 reg = AR_READ(sc, AR_PHY_TIMING_CTRL4_0); 204 reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, modal->iqCalI); 205 reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, modal->iqCalQ); 206 AR_WRITE(sc, AR_PHY_TIMING_CTRL4_0, reg); 207 208 if (sc->eep_rev >= AR_EEP_MINOR_VER_3) { 209 reg = AR_READ(sc, AR_PHY_GAIN_2GHZ); 210 reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, 211 modal->bswMargin); 212 reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_DB, 213 modal->bswAtten); 214 reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, 215 modal->xatten2Margin); 216 reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_DB, 217 modal->xatten2Db); 218 AR_WRITE(sc, AR_PHY_GAIN_2GHZ, reg); 219 220 /* Duplicate values of chain 0 for chain 1. */ 221 reg = AR_READ(sc, AR_PHY_GAIN_2GHZ + offset); 222 reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, 223 modal->bswMargin); 224 reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_DB, 225 modal->bswAtten); 226 reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, 227 modal->xatten2Margin); 228 reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_DB, 229 modal->xatten2Db); 230 AR_WRITE(sc, AR_PHY_GAIN_2GHZ + offset, reg); 231 } 232 if (sc->eep_rev >= AR_EEP_MINOR_VER_3) 233 txRxAtten = modal->txRxAtten; 234 else /* Workaround for ROM versions < 14.3. */ 235 txRxAtten = 23; 236 reg = AR_READ(sc, AR_PHY_RXGAIN); 237 reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAtten); 238 reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_MARGIN, modal->rxTxMargin); 239 AR_WRITE(sc, AR_PHY_RXGAIN, reg); 240 241 /* Duplicate values of chain 0 for chain 1. */ 242 reg = AR_READ(sc, AR_PHY_RXGAIN + offset); 243 reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAtten); 244 reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_MARGIN, modal->rxTxMargin); 245 AR_WRITE(sc, AR_PHY_RXGAIN + offset, reg); 246 247 if (modal->version >= 3) { 248 /* Setup antenna diversity from ROM. */ 249 reg = AR_READ(sc, AR_PHY_MULTICHAIN_GAIN_CTL); 250 reg = RW(reg, AR9285_PHY_ANT_DIV_CTL_ALL, 0); 251 reg = RW(reg, AR9285_PHY_ANT_DIV_CTL, 252 (modal->ob_234 >> 12) & 0x1); 253 reg = RW(reg, AR9285_PHY_ANT_DIV_ALT_LNACONF, 254 (modal->db1_234 >> 12) & 0x3); 255 reg = RW(reg, AR9285_PHY_ANT_DIV_MAIN_LNACONF, 256 (modal->db1_234 >> 14) & 0x3); 257 reg = RW(reg, AR9285_PHY_ANT_DIV_ALT_GAINTB, 258 (modal->ob_234 >> 13) & 0x1); 259 reg = RW(reg, AR9285_PHY_ANT_DIV_MAIN_GAINTB, 260 (modal->ob_234 >> 14) & 0x1); 261 AR_WRITE(sc, AR_PHY_MULTICHAIN_GAIN_CTL, reg); 262 reg = AR_READ(sc, AR_PHY_MULTICHAIN_GAIN_CTL); /* Flush. */ 263 264 reg = AR_READ(sc, AR_PHY_CCK_DETECT); 265 if (modal->ob_234 & (1 << 15)) 266 reg |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; 267 else 268 reg &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; 269 AR_WRITE(sc, AR_PHY_CCK_DETECT, reg); 270 reg = AR_READ(sc, AR_PHY_CCK_DETECT); /* Flush. */ 271 } 272 if (modal->version >= 2) { 273 ob [0] = (modal->ob_01 >> 0) & 0xf; 274 ob [1] = (modal->ob_01 >> 4) & 0xf; 275 ob [2] = (modal->ob_234 >> 0) & 0xf; 276 ob [3] = (modal->ob_234 >> 4) & 0xf; 277 ob [4] = (modal->ob_234 >> 8) & 0xf; 278 279 db1[0] = (modal->db1_01 >> 0) & 0xf; 280 db1[1] = (modal->db1_01 >> 4) & 0xf; 281 db1[2] = (modal->db1_234 >> 0) & 0xf; 282 db1[3] = (modal->db1_234 >> 4) & 0xf; 283 db1[4] = (modal->db1_234 >> 8) & 0xf; 284 285 db2[0] = (modal->db2_01 >> 0) & 0xf; 286 db2[1] = (modal->db2_01 >> 4) & 0xf; 287 db2[2] = (modal->db2_234 >> 0) & 0xf; 288 db2[3] = (modal->db2_234 >> 4) & 0xf; 289 db2[4] = (modal->db2_234 >> 8) & 0xf; 290 291 } else if (modal->version == 1) { 292 ob [0] = (modal->ob_01 >> 0) & 0xf; 293 ob [1] = (modal->ob_01 >> 4) & 0xf; 294 /* Field ob_234 does not exist, use ob_01. */ 295 ob [2] = ob [3] = ob [4] = ob [1]; 296 297 db1[0] = (modal->db1_01 >> 0) & 0xf; 298 db1[1] = (modal->db1_01 >> 4) & 0xf; 299 /* Field db1_234 does not exist, use db1_01. */ 300 db1[2] = db1[3] = db1[4] = db1[1]; 301 302 db2[0] = (modal->db2_01 >> 0) & 0xf; 303 db2[1] = (modal->db2_01 >> 4) & 0xf; 304 /* Field db2_234 does not exist, use db2_01. */ 305 db2[2] = db2[3] = db2[4] = db2[1]; 306 307 } else { 308 ob [0] = modal->ob_01; 309 ob [1] = ob [2] = ob [3] = ob [4] = ob [0]; 310 311 db1[0] = modal->db1_01; 312 db1[1] = db1[2] = db1[3] = db1[4] = db1[0]; 313 314 /* Field db2_01 does not exist, use db1_01. */ 315 db2[0] = modal->db1_01; 316 db2[1] = db2[2] = db2[3] = db2[4] = db2[0]; 317 } 318 #if NATHN_USB > 0 319 if (AR_SREV_9271(sc)) { 320 reg = AR_READ(sc, AR9285_AN_RF2G3); 321 reg = RW(reg, AR9271_AN_RF2G3_OB_CCK, ob [0]); 322 reg = RW(reg, AR9271_AN_RF2G3_OB_PSK, ob [1]); 323 reg = RW(reg, AR9271_AN_RF2G3_OB_QAM, ob [2]); 324 reg = RW(reg, AR9271_AN_RF2G3_DB1, db1[0]); 325 AR_WRITE(sc, AR9285_AN_RF2G3, reg); 326 AR_WRITE_BARRIER(sc); 327 DELAY(100); 328 reg = AR_READ(sc, AR9285_AN_RF2G4); 329 reg = RW(reg, AR9271_AN_RF2G4_DB2, db2[0]); 330 AR_WRITE(sc, AR9285_AN_RF2G4, reg); 331 AR_WRITE_BARRIER(sc); 332 DELAY(100); 333 } else 334 #endif /* ATHN_USB */ 335 { 336 reg = AR_READ(sc, AR9285_AN_RF2G3); 337 reg = RW(reg, AR9285_AN_RF2G3_OB_0, ob [0]); 338 reg = RW(reg, AR9285_AN_RF2G3_OB_1, ob [1]); 339 reg = RW(reg, AR9285_AN_RF2G3_OB_2, ob [2]); 340 reg = RW(reg, AR9285_AN_RF2G3_OB_3, ob [3]); 341 reg = RW(reg, AR9285_AN_RF2G3_OB_4, ob [4]); 342 reg = RW(reg, AR9285_AN_RF2G3_DB1_0, db1[0]); 343 reg = RW(reg, AR9285_AN_RF2G3_DB1_1, db1[1]); 344 reg = RW(reg, AR9285_AN_RF2G3_DB1_2, db1[2]); 345 AR_WRITE(sc, AR9285_AN_RF2G3, reg); 346 AR_WRITE_BARRIER(sc); 347 DELAY(100); 348 reg = AR_READ(sc, AR9285_AN_RF2G4); 349 reg = RW(reg, AR9285_AN_RF2G4_DB1_3, db1[3]); 350 reg = RW(reg, AR9285_AN_RF2G4_DB1_4, db1[4]); 351 reg = RW(reg, AR9285_AN_RF2G4_DB2_0, db2[0]); 352 reg = RW(reg, AR9285_AN_RF2G4_DB2_1, db2[1]); 353 reg = RW(reg, AR9285_AN_RF2G4_DB2_2, db2[2]); 354 reg = RW(reg, AR9285_AN_RF2G4_DB2_3, db2[3]); 355 reg = RW(reg, AR9285_AN_RF2G4_DB2_4, db2[4]); 356 AR_WRITE(sc, AR9285_AN_RF2G4, reg); 357 AR_WRITE_BARRIER(sc); 358 DELAY(100); 359 } 360 361 reg = AR_READ(sc, AR_PHY_SETTLING); 362 reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->switchSettling); 363 AR_WRITE(sc, AR_PHY_SETTLING, reg); 364 365 reg = AR_READ(sc, AR_PHY_DESIRED_SZ); 366 reg = RW(reg, AR_PHY_DESIRED_SZ_ADC, modal->adcDesiredSize); 367 AR_WRITE(sc, AR_PHY_DESIRED_SZ, reg); 368 369 reg = SM(AR_PHY_RF_CTL4_TX_END_XPAA_OFF, modal->txEndToXpaOff); 370 reg |= SM(AR_PHY_RF_CTL4_TX_END_XPAB_OFF, modal->txEndToXpaOff); 371 reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAA_ON, modal->txFrameToXpaOn); 372 reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAB_ON, modal->txFrameToXpaOn); 373 AR_WRITE(sc, AR_PHY_RF_CTL4, reg); 374 375 reg = AR_READ(sc, AR_PHY_RF_CTL3); 376 reg = RW(reg, AR_PHY_TX_END_TO_A2_RX_ON, modal->txEndToRxOn); 377 AR_WRITE(sc, AR_PHY_RF_CTL3, reg); 378 379 reg = AR_READ(sc, AR_PHY_CCA(0)); 380 reg = RW(reg, AR9280_PHY_CCA_THRESH62, modal->thresh62); 381 AR_WRITE(sc, AR_PHY_CCA(0), reg); 382 383 reg = AR_READ(sc, AR_PHY_EXT_CCA0); 384 reg = RW(reg, AR_PHY_EXT_CCA0_THRESH62, modal->thresh62); 385 AR_WRITE(sc, AR_PHY_EXT_CCA0, reg); 386 387 if (sc->eep_rev >= AR_EEP_MINOR_VER_2) { 388 reg = AR_READ(sc, AR_PHY_RF_CTL2); 389 reg = RW(reg, AR_PHY_TX_END_PA_ON, 390 modal->txFrameToPaOn); 391 reg = RW(reg, AR_PHY_TX_END_DATA_START, 392 modal->txFrameToDataStart); 393 AR_WRITE(sc, AR_PHY_RF_CTL2, reg); 394 } 395 #ifndef IEEE80211_NO_HT 396 if (sc->eep_rev >= AR_EEP_MINOR_VER_3 && extc != NULL) { 397 reg = AR_READ(sc, AR_PHY_SETTLING); 398 reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->swSettleHt40); 399 AR_WRITE(sc, AR_PHY_SETTLING, reg); 400 } 401 #endif 402 AR_WRITE_BARRIER(sc); 403 } 404 405 void 406 ar9285_pa_calib(struct athn_softc *sc) 407 { 408 /* List of registers that need to be saved/restored. */ 409 static const uint16_t regs[] = { 410 AR9285_AN_TOP3, 411 AR9285_AN_RXTXBB1, 412 AR9285_AN_RF2G1, 413 AR9285_AN_RF2G2, 414 AR9285_AN_TOP2, 415 AR9285_AN_RF2G8, 416 AR9285_AN_RF2G7 417 }; 418 uint32_t svg[7], reg, ccomp_svg; 419 int i; 420 421 /* No PA calibration needed for high power solutions. */ 422 if (AR_SREV_9285(sc) && 423 ((struct ar9285_base_eep_header *)sc->eep)->txGainType == 424 AR_EEP_TXGAIN_HIGH_POWER) /* XXX AR9287? */ 425 return; 426 427 /* Save registers. */ 428 for (i = 0; i < nitems(regs); i++) 429 svg[i] = AR_READ(sc, regs[i]); 430 431 AR_CLRBITS(sc, AR9285_AN_RF2G6, 1); 432 AR_SETBITS(sc, AR_PHY(2), 1 << 27); 433 434 AR_SETBITS(sc, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC); 435 AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1); 436 AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I); 437 AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF); 438 AR_CLRBITS(sc, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL); 439 AR_CLRBITS(sc, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB); 440 AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL); 441 /* Power down PA drivers. */ 442 AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1); 443 AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2); 444 AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT); 445 446 reg = AR_READ(sc, AR9285_AN_RF2G8); 447 reg = RW(reg, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); 448 AR_WRITE(sc, AR9285_AN_RF2G8, reg); 449 450 reg = AR_READ(sc, AR9285_AN_RF2G7); 451 reg = RW(reg, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); 452 AR_WRITE(sc, AR9285_AN_RF2G7, reg); 453 454 reg = AR_READ(sc, AR9285_AN_RF2G6); 455 /* Save compensation capacitor value. */ 456 ccomp_svg = MS(reg, AR9285_AN_RF2G6_CCOMP); 457 /* Program compensation capacitor for dynamic PA. */ 458 reg = RW(reg, AR9285_AN_RF2G6_CCOMP, 0xf); 459 AR_WRITE(sc, AR9285_AN_RF2G6, reg); 460 461 AR_WRITE(sc, AR9285_AN_TOP2, AR9285_AN_TOP2_DEFAULT); 462 AR_WRITE_BARRIER(sc); 463 DELAY(30); 464 465 /* Clear offsets 6-1. */ 466 AR_CLRBITS(sc, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS_6_1); 467 /* Clear offset 0. */ 468 AR_CLRBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP); 469 /* Set offsets 6-1. */ 470 for (i = 6; i >= 1; i--) { 471 AR_SETBITS(sc, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS(i)); 472 AR_WRITE_BARRIER(sc); 473 DELAY(1); 474 if (AR_READ(sc, AR9285_AN_RF2G9) & AR9285_AN_RXTXBB1_SPARE9) { 475 AR_SETBITS(sc, AR9285_AN_RF2G6, 476 AR9285_AN_RF2G6_OFFS(i)); 477 } else { 478 AR_CLRBITS(sc, AR9285_AN_RF2G6, 479 AR9285_AN_RF2G6_OFFS(i)); 480 } 481 } 482 /* Set offset 0. */ 483 AR_SETBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP); 484 AR_WRITE_BARRIER(sc); 485 DELAY(1); 486 if (AR_READ(sc, AR9285_AN_RF2G9) & AR9285_AN_RXTXBB1_SPARE9) 487 AR_SETBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP); 488 else 489 AR_CLRBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP); 490 491 AR_WRITE_BARRIER(sc); 492 493 AR_SETBITS(sc, AR9285_AN_RF2G6, 1); 494 AR_CLRBITS(sc, AR_PHY(2), 1 << 27); 495 496 /* Restore registers. */ 497 for (i = 0; i < nitems(regs); i++) 498 AR_WRITE(sc, regs[i], svg[i]); 499 500 /* Restore compensation capacitor value. */ 501 reg = AR_READ(sc, AR9285_AN_RF2G6); 502 reg = RW(reg, AR9285_AN_RF2G6_CCOMP, ccomp_svg); 503 AR_WRITE(sc, AR9285_AN_RF2G6, reg); 504 AR_WRITE_BARRIER(sc); 505 } 506 507 void 508 ar9271_pa_calib(struct athn_softc *sc) 509 { 510 #if NATHN_USB > 0 511 /* List of registers that need to be saved/restored. */ 512 static const uint16_t regs[] = { 513 AR9285_AN_TOP3, 514 AR9285_AN_RXTXBB1, 515 AR9285_AN_RF2G1, 516 AR9285_AN_RF2G2, 517 AR9285_AN_TOP2, 518 AR9285_AN_RF2G8, 519 AR9285_AN_RF2G7 520 }; 521 uint32_t svg[7], reg, rf2g3_svg; 522 int i; 523 524 /* Save registers. */ 525 for (i = 0; i < nitems(regs); i++) 526 svg[i] = AR_READ(sc, regs[i]); 527 528 AR_CLRBITS(sc, AR9285_AN_RF2G6, 1); 529 AR_SETBITS(sc, AR_PHY(2), 1 << 27); 530 531 AR_SETBITS(sc, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC); 532 AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1); 533 AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I); 534 AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF); 535 AR_CLRBITS(sc, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL); 536 AR_CLRBITS(sc, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB); 537 AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL); 538 /* Power down PA drivers. */ 539 AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1); 540 AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2); 541 AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT); 542 543 reg = AR_READ(sc, AR9285_AN_RF2G8); 544 reg = RW(reg, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); 545 AR_WRITE(sc, AR9285_AN_RF2G8, reg); 546 547 reg = AR_READ(sc, AR9285_AN_RF2G7); 548 reg = RW(reg, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); 549 AR_WRITE(sc, AR9285_AN_RF2G7, reg); 550 551 /* Save compensation capacitor value. */ 552 reg = rf2g3_svg = AR_READ(sc, AR9285_AN_RF2G3); 553 /* Program compensation capacitor for dynamic PA. */ 554 reg = RW(reg, AR9271_AN_RF2G3_CCOMP, 0xfff); 555 AR_WRITE(sc, AR9285_AN_RF2G3, reg); 556 557 AR_WRITE(sc, AR9285_AN_TOP2, AR9285_AN_TOP2_DEFAULT); 558 AR_WRITE_BARRIER(sc); 559 DELAY(30); 560 561 /* Clear offsets 6-0. */ 562 AR_CLRBITS(sc, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS_6_0); 563 /* Set offsets 6-1. */ 564 for (i = 6; i >= 1; i--) { 565 reg = AR_READ(sc, AR9285_AN_RF2G6); 566 reg |= AR9271_AN_RF2G6_OFFS(i); 567 AR_WRITE(sc, AR9285_AN_RF2G6, reg); 568 AR_WRITE_BARRIER(sc); 569 DELAY(1); 570 if (!(AR_READ(sc, AR9285_AN_RF2G9) & AR9285_AN_RXTXBB1_SPARE9)) 571 reg &= ~AR9271_AN_RF2G6_OFFS(i); 572 AR_WRITE(sc, AR9285_AN_RF2G6, reg); 573 } 574 AR_WRITE_BARRIER(sc); 575 576 AR_SETBITS(sc, AR9285_AN_RF2G6, 1); 577 AR_CLRBITS(sc, AR_PHY(2), 1 << 27); 578 579 /* Restore registers. */ 580 for (i = 0; i < nitems(regs); i++) 581 AR_WRITE(sc, regs[i], svg[i]); 582 583 /* Restore compensation capacitor value. */ 584 AR_WRITE(sc, AR9285_AN_RF2G3, rf2g3_svg); 585 AR_WRITE_BARRIER(sc); 586 #endif /* NATHN_USB */ 587 } 588 589 /* 590 * Carrier Leakage Calibration. 591 */ 592 int 593 ar9285_cl_cal(struct athn_softc *sc, struct ieee80211_channel *c, 594 struct ieee80211_channel *extc) 595 { 596 int ntries; 597 598 AR_SETBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); 599 #ifndef IEEE80211_NO_HT 600 if (0 && extc == NULL) { /* XXX IS_CHAN_HT20!! */ 601 AR_SETBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); 602 AR_SETBITS(sc, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); 603 AR_CLRBITS(sc, AR_PHY_AGC_CONTROL, 604 AR_PHY_AGC_CONTROL_FLTR_CAL); 605 AR_CLRBITS(sc, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); 606 AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); 607 for (ntries = 0; ntries < 10000; ntries++) { 608 if (!(AR_READ(sc, AR_PHY_AGC_CONTROL) & 609 AR_PHY_AGC_CONTROL_CAL)) 610 break; 611 DELAY(10); 612 } 613 if (ntries == 10000) 614 return (ETIMEDOUT); 615 AR_CLRBITS(sc, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); 616 AR_CLRBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); 617 AR_CLRBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); 618 } 619 #endif 620 AR_CLRBITS(sc, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); 621 AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); 622 AR_SETBITS(sc, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); 623 AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); 624 for (ntries = 0; ntries < 10000; ntries++) { 625 if (!(AR_READ(sc, AR_PHY_AGC_CONTROL) & 626 AR_PHY_AGC_CONTROL_CAL)) 627 break; 628 DELAY(10); 629 } 630 if (ntries == 10000) 631 return (ETIMEDOUT); 632 AR_SETBITS(sc, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); 633 AR_CLRBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); 634 AR_CLRBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); 635 AR_WRITE_BARRIER(sc); 636 return (0); 637 } 638 639 void 640 ar9271_load_ani(struct athn_softc *sc) 641 { 642 #if NATHN_USB > 0 643 /* Write ANI registers. */ 644 AR_WRITE(sc, AR_PHY_DESIRED_SZ, 0x6d4000e2); 645 AR_WRITE(sc, AR_PHY_AGC_CTL1, 0x3139605e); 646 AR_WRITE(sc, AR_PHY_FIND_SIG, 0x7ec84d2e); 647 AR_WRITE(sc, AR_PHY_SFCORR_LOW, 0x06903881); 648 AR_WRITE(sc, AR_PHY_SFCORR, 0x5ac640d0); 649 AR_WRITE(sc, AR_PHY_CCK_DETECT, 0x803e68c8); 650 AR_WRITE(sc, AR_PHY_TIMING5, 0xd00a8007); 651 AR_WRITE(sc, AR_PHY_SFCORR_EXT, 0x05eea6d4); 652 AR_WRITE_BARRIER(sc); 653 #endif /* NATHN_USB */ 654 } 655 656 int 657 ar9285_init_calib(struct athn_softc *sc, struct ieee80211_channel *c, 658 struct ieee80211_channel *extc) 659 { 660 uint32_t reg, mask, clcgain, rf2g5_svg; 661 int i, maxgain, nclcs, thresh, error; 662 663 /* Do carrier leakage calibration. */ 664 if ((error = ar9285_cl_cal(sc, c, extc)) != 0) 665 return (error); 666 667 /* Workaround for high temperature is not applicable on AR9271. */ 668 if (AR_SREV_9271(sc)) 669 return (0); 670 671 mask = 0; 672 nclcs = 0; 673 reg = AR_READ(sc, AR_PHY_TX_PWRCTRL7); 674 maxgain = MS(reg, AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX); 675 for (i = 0; i <= maxgain; i++) { 676 reg = AR_READ(sc, AR_PHY_TX_GAIN_TBL(i)); 677 clcgain = MS(reg, AR_PHY_TX_GAIN_CLC); 678 /* NB: clcgain <= 0xf. */ 679 if (!(mask & (1 << clcgain))) { 680 mask |= 1 << clcgain; 681 nclcs++; 682 } 683 } 684 thresh = 0; 685 for (i = 0; i < nclcs; i++) { 686 reg = AR_READ(sc, AR_PHY_CLC_TBL(i)); 687 if (MS(reg, AR_PHY_CLC_I0) == 0) 688 thresh++; 689 if (MS(reg, AR_PHY_CLC_Q0) == 0) 690 thresh++; 691 } 692 if (thresh <= AR9285_CL_CAL_REDO_THRESH) 693 return (0); /* No need to redo. */ 694 695 /* Threshold reached, redo carrier leakage calibration. */ 696 DPRINTFN(2, ("CLC threshold=%d\n", thresh)); 697 rf2g5_svg = reg = AR_READ(sc, AR9285_AN_RF2G5); 698 if ((AR_READ(sc, AR_AN_SYNTH9) & 0x7) == 0x1) /* XE rev. */ 699 reg = RW(reg, AR9285_AN_RF2G5_IC50TX, 0x5); 700 else 701 reg = RW(reg, AR9285_AN_RF2G5_IC50TX, 0x4); 702 AR_WRITE(sc, AR9285_AN_RF2G5, reg); 703 AR_WRITE_BARRIER(sc); 704 error = ar9285_cl_cal(sc, c, extc); 705 AR_WRITE(sc, AR9285_AN_RF2G5, rf2g5_svg); 706 AR_WRITE_BARRIER(sc); 707 return (error); 708 } 709 710 void 711 ar9285_get_pdadcs(struct athn_softc *sc, struct ieee80211_channel *c, 712 int nxpdgains, uint8_t overlap, uint8_t *boundaries, uint8_t *pdadcs) 713 { 714 const struct ar9285_eeprom *eep = sc->eep; 715 const struct ar9285_cal_data_per_freq *pierdata; 716 const uint8_t *pierfreq; 717 struct athn_pier lopier, hipier; 718 uint8_t fbin; 719 int i, lo, hi, npiers; 720 721 pierfreq = eep->calFreqPier2G; 722 pierdata = eep->calPierData2G; 723 npiers = AR9285_NUM_2G_CAL_PIERS; 724 725 /* Find channel in ROM pier table. */ 726 fbin = athn_chan2fbin(c); 727 athn_get_pier_ival(fbin, pierfreq, npiers, &lo, &hi); 728 729 lopier.fbin = pierfreq[lo]; 730 hipier.fbin = pierfreq[hi]; 731 for (i = 0; i < nxpdgains; i++) { 732 lopier.pwr[i] = pierdata[lo].pwrPdg[i]; 733 lopier.vpd[i] = pierdata[lo].vpdPdg[i]; 734 hipier.pwr[i] = pierdata[lo].pwrPdg[i]; 735 hipier.vpd[i] = pierdata[lo].vpdPdg[i]; 736 } 737 ar5008_get_pdadcs(sc, fbin, &lopier, &hipier, nxpdgains, 738 AR9285_PD_GAIN_ICEPTS, overlap, boundaries, pdadcs); 739 } 740 741 void 742 ar9285_set_power_calib(struct athn_softc *sc, struct ieee80211_channel *c) 743 { 744 const struct ar9285_eeprom *eep = sc->eep; 745 uint8_t boundaries[AR_PD_GAINS_IN_MASK]; 746 uint8_t pdadcs[AR_NUM_PDADC_VALUES]; 747 uint8_t xpdgains[AR9285_NUM_PD_GAINS]; 748 uint8_t overlap; 749 uint32_t reg; 750 int i, nxpdgains; 751 752 if (sc->eep_rev < AR_EEP_MINOR_VER_2) { 753 overlap = MS(AR_READ(sc, AR_PHY_TPCRG5), 754 AR_PHY_TPCRG5_PD_GAIN_OVERLAP); 755 } else 756 overlap = eep->modalHeader.pdGainOverlap; 757 758 nxpdgains = 0; 759 memset(xpdgains, 0, sizeof(xpdgains)); 760 for (i = AR9285_PD_GAINS_IN_MASK - 1; i >= 0; i--) { 761 if (nxpdgains >= AR9285_NUM_PD_GAINS) 762 break; 763 if (eep->modalHeader.xpdGain & (1 << i)) 764 xpdgains[nxpdgains++] = i; 765 } 766 reg = AR_READ(sc, AR_PHY_TPCRG1); 767 reg = RW(reg, AR_PHY_TPCRG1_NUM_PD_GAIN, nxpdgains - 1); 768 reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_1, xpdgains[0]); 769 reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_2, xpdgains[1]); 770 AR_WRITE(sc, AR_PHY_TPCRG1, reg); 771 772 /* NB: No open loop power control for AR9285. */ 773 ar9285_get_pdadcs(sc, c, nxpdgains, overlap, boundaries, pdadcs); 774 775 /* Write boundaries. */ 776 reg = SM(AR_PHY_TPCRG5_PD_GAIN_OVERLAP, overlap); 777 reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1, boundaries[0]); 778 reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2, boundaries[1]); 779 reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3, boundaries[2]); 780 reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4, boundaries[3]); 781 AR_WRITE(sc, AR_PHY_TPCRG5, reg); 782 783 /* Write PDADC values. */ 784 for (i = 0; i < AR_NUM_PDADC_VALUES; i += 4) { 785 AR_WRITE(sc, AR_PHY_PDADC_TBL_BASE + i, 786 pdadcs[i + 0] << 0 | 787 pdadcs[i + 1] << 8 | 788 pdadcs[i + 2] << 16 | 789 pdadcs[i + 3] << 24); 790 } 791 AR_WRITE_BARRIER(sc); 792 } 793 794 void 795 ar9285_set_txpower(struct athn_softc *sc, struct ieee80211_channel *c, 796 struct ieee80211_channel *extc) 797 { 798 const struct ar9285_eeprom *eep = sc->eep; 799 const struct ar9285_modal_eep_header *modal = &eep->modalHeader; 800 uint8_t tpow_cck[4], tpow_ofdm[4]; 801 #ifndef IEEE80211_NO_HT 802 uint8_t tpow_cck_ext[4], tpow_ofdm_ext[4]; 803 uint8_t tpow_ht20[8], tpow_ht40[8]; 804 uint8_t ht40inc; 805 #endif 806 int16_t max_ant_gain, power[ATHN_POWER_COUNT]; 807 int i; 808 809 ar9285_set_power_calib(sc, c); 810 811 /* Compute transmit power reduction due to antenna gain. */ 812 max_ant_gain = modal->antennaGain; 813 /* XXX */ 814 815 /* Get CCK target powers. */ 816 ar5008_get_lg_tpow(sc, c, AR_CTL_11B, eep->calTargetPowerCck, 817 AR9285_NUM_2G_CCK_TARGET_POWERS, tpow_cck); 818 819 /* Get OFDM target powers. */ 820 ar5008_get_lg_tpow(sc, c, AR_CTL_11G, eep->calTargetPower2G, 821 AR9285_NUM_2G_20_TARGET_POWERS, tpow_ofdm); 822 823 #ifndef IEEE80211_NO_HT 824 /* Get HT-20 target powers. */ 825 ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT20, eep->calTargetPower2GHT20, 826 AR9285_NUM_2G_20_TARGET_POWERS, tpow_ht20); 827 828 if (extc != NULL) { 829 /* Get HT-40 target powers. */ 830 ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT40, 831 eep->calTargetPower2GHT40, AR9285_NUM_2G_40_TARGET_POWERS, 832 tpow_ht40); 833 834 /* Get secondary channel CCK target powers. */ 835 ar5008_get_lg_tpow(sc, extc, AR_CTL_11B, 836 eep->calTargetPowerCck, AR9285_NUM_2G_CCK_TARGET_POWERS, 837 tpow_cck_ext); 838 839 /* Get secondary channel OFDM target powers. */ 840 ar5008_get_lg_tpow(sc, extc, AR_CTL_11G, 841 eep->calTargetPower2G, AR9285_NUM_2G_20_TARGET_POWERS, 842 tpow_ofdm_ext); 843 } 844 #endif 845 846 memset(power, 0, sizeof(power)); 847 /* Shuffle target powers accross transmit rates. */ 848 power[ATHN_POWER_OFDM6 ] = 849 power[ATHN_POWER_OFDM9 ] = 850 power[ATHN_POWER_OFDM12 ] = 851 power[ATHN_POWER_OFDM18 ] = 852 power[ATHN_POWER_OFDM24 ] = tpow_ofdm[0]; 853 power[ATHN_POWER_OFDM36 ] = tpow_ofdm[1]; 854 power[ATHN_POWER_OFDM48 ] = tpow_ofdm[2]; 855 power[ATHN_POWER_OFDM54 ] = tpow_ofdm[3]; 856 power[ATHN_POWER_XR ] = tpow_ofdm[0]; 857 power[ATHN_POWER_CCK1_LP ] = tpow_cck[0]; 858 power[ATHN_POWER_CCK2_LP ] = 859 power[ATHN_POWER_CCK2_SP ] = tpow_cck[1]; 860 power[ATHN_POWER_CCK55_LP] = 861 power[ATHN_POWER_CCK55_SP] = tpow_cck[2]; 862 power[ATHN_POWER_CCK11_LP] = 863 power[ATHN_POWER_CCK11_SP] = tpow_cck[3]; 864 #ifndef IEEE80211_NO_HT 865 for (i = 0; i < nitems(tpow_ht20); i++) 866 power[ATHN_POWER_HT20(i)] = tpow_ht20[i]; 867 if (extc != NULL) { 868 /* Correct PAR difference between HT40 and HT20/Legacy. */ 869 if (sc->eep_rev >= AR_EEP_MINOR_VER_2) 870 ht40inc = modal->ht40PowerIncForPdadc; 871 else 872 ht40inc = AR_HT40_POWER_INC_FOR_PDADC; 873 for (i = 0; i < nitems(tpow_ht40); i++) 874 power[ATHN_POWER_HT40(i)] = tpow_ht40[i] + ht40inc; 875 power[ATHN_POWER_OFDM_DUP] = tpow_ht40[0]; 876 power[ATHN_POWER_CCK_DUP ] = tpow_ht40[0]; 877 power[ATHN_POWER_OFDM_EXT] = tpow_ofdm_ext[0]; 878 power[ATHN_POWER_CCK_EXT ] = tpow_cck_ext[0]; 879 } 880 #endif 881 882 for (i = 0; i < ATHN_POWER_COUNT; i++) { 883 power[i] -= AR_PWR_TABLE_OFFSET_DB * 2; /* In half dB. */ 884 if (power[i] > AR_MAX_RATE_POWER) 885 power[i] = AR_MAX_RATE_POWER; 886 } 887 888 /* Commit transmit power values to hardware. */ 889 ar5008_write_txpower(sc, power); 890 } 891