File: | dev/ic/ar9285.c |
Warning: | line 810, column 2 Value stored to 'max_ant_gain' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: ar9285.c,v 1.30 2022/01/09 05:42:38 jsg 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 | #include <sys/endian.h> |
40 | |
41 | #include <machine/bus.h> |
42 | #include <machine/intr.h> |
43 | |
44 | #if NBPFILTER1 > 0 |
45 | #include <net/bpf.h> |
46 | #endif |
47 | #include <net/if.h> |
48 | #include <net/if_media.h> |
49 | |
50 | #include <netinet/in.h> |
51 | #include <netinet/if_ether.h> |
52 | |
53 | #include <net80211/ieee80211_var.h> |
54 | #include <net80211/ieee80211_amrr.h> |
55 | #include <net80211/ieee80211_ra.h> |
56 | #include <net80211/ieee80211_radiotap.h> |
57 | |
58 | #include <dev/ic/athnreg.h> |
59 | #include <dev/ic/athnvar.h> |
60 | |
61 | #include <dev/ic/ar5008reg.h> |
62 | #include <dev/ic/ar9280reg.h> |
63 | #include <dev/ic/ar9285reg.h> |
64 | |
65 | int ar9285_attach(struct athn_softc *); |
66 | void ar9285_setup(struct athn_softc *); |
67 | void ar9285_swap_rom(struct athn_softc *); |
68 | const struct ar_spur_chan *ar9285_get_spur_chans(struct athn_softc *, int); |
69 | void ar9285_init_from_rom(struct athn_softc *, struct ieee80211_channel *, |
70 | struct ieee80211_channel *); |
71 | void ar9285_pa_calib(struct athn_softc *); |
72 | void ar9271_pa_calib(struct athn_softc *); |
73 | int ar9285_cl_cal(struct athn_softc *, struct ieee80211_channel *, |
74 | struct ieee80211_channel *); |
75 | void ar9271_load_ani(struct athn_softc *); |
76 | int ar9285_init_calib(struct athn_softc *, struct ieee80211_channel *, |
77 | struct ieee80211_channel *); |
78 | void ar9285_get_pdadcs(struct athn_softc *, struct ieee80211_channel *, |
79 | int, uint8_t, uint8_t *, uint8_t *); |
80 | void ar9285_set_power_calib(struct athn_softc *, |
81 | struct ieee80211_channel *); |
82 | void ar9285_set_txpower(struct athn_softc *, struct ieee80211_channel *, |
83 | struct ieee80211_channel *); |
84 | |
85 | /* Extern functions. */ |
86 | uint8_t athn_chan2fbin(struct ieee80211_channel *); |
87 | void athn_get_pier_ival(uint8_t, const uint8_t *, int, int *, int *); |
88 | int ar5008_attach(struct athn_softc *); |
89 | void ar5008_write_txpower(struct athn_softc *, int16_t power[]); |
90 | void ar5008_get_pdadcs(struct athn_softc *, uint8_t, struct athn_pier *, |
91 | struct athn_pier *, int, int, uint8_t, uint8_t *, uint8_t *); |
92 | void ar5008_get_lg_tpow(struct athn_softc *, struct ieee80211_channel *, |
93 | uint8_t, const struct ar_cal_target_power_leg *, int, uint8_t[]); |
94 | void ar5008_get_ht_tpow(struct athn_softc *, struct ieee80211_channel *, |
95 | uint8_t, const struct ar_cal_target_power_ht *, int, uint8_t[]); |
96 | int ar9280_set_synth(struct athn_softc *, struct ieee80211_channel *, |
97 | struct ieee80211_channel *); |
98 | void ar9280_spur_mitigate(struct athn_softc *, struct ieee80211_channel *, |
99 | struct ieee80211_channel *); |
100 | |
101 | |
102 | int |
103 | ar9285_attach(struct athn_softc *sc) |
104 | { |
105 | sc->eep_base = AR9285_EEP_START_LOC64; |
106 | sc->eep_size = sizeof(struct ar9285_eeprom); |
107 | sc->ngpiopins = (sc->flags & ATHN_FLAG_USB(1 << 1)) ? 16 : 12; |
108 | sc->led_pin = (sc->flags & ATHN_FLAG_USB(1 << 1)) ? 15 : 1; |
109 | sc->workaround = AR9285_WA_DEFAULT0x004a050b; |
110 | sc->ops.setup = ar9285_setup; |
111 | sc->ops.swap_rom = ar9285_swap_rom; |
112 | sc->ops.init_from_rom = ar9285_init_from_rom; |
113 | sc->ops.set_txpower = ar9285_set_txpower; |
114 | sc->ops.set_synth = ar9280_set_synth; |
115 | sc->ops.spur_mitigate = ar9280_spur_mitigate; |
116 | sc->ops.get_spur_chans = ar9285_get_spur_chans; |
117 | #if NATHN_USB1 > 0 |
118 | if (AR_SREV_9271(sc)((sc)->mac_ver == 0x140)) { |
119 | sc->cca_min_2g = AR9271_PHY_CCA_MIN_GOOD_VAL_2GHZ(-127); |
120 | sc->cca_max_2g = AR9271_PHY_CCA_MAX_GOOD_VAL_2GHZ(-116); |
121 | } else |
122 | #endif |
123 | { |
124 | sc->cca_min_2g = AR9285_PHY_CCA_MIN_GOOD_VAL_2GHZ(-127); |
125 | sc->cca_max_2g = AR9285_PHY_CCA_MAX_GOOD_VAL_2GHZ(-108); |
126 | } |
127 | #if NATHN_USB1 > 0 |
128 | if (AR_SREV_9271(sc)((sc)->mac_ver == 0x140)) |
129 | sc->ini = &ar9271_ini; |
130 | else |
131 | #endif |
132 | sc->ini = &ar9285_1_2_ini; |
133 | sc->serdes = &ar9280_2_0_serdes; |
134 | |
135 | return (ar5008_attach(sc)); |
136 | } |
137 | |
138 | void |
139 | ar9285_setup(struct athn_softc *sc) |
140 | { |
141 | const struct ar9285_eeprom *eep = sc->eep; |
142 | uint8_t type; |
143 | |
144 | /* Select initialization values based on ROM. */ |
145 | type = eep->baseEepHeader.txGainType; |
146 | DPRINTF(("Tx gain type=0x%x\n", type)); |
147 | #if NATHN_USB1 > 0 |
148 | if (AR_SREV_9271(sc)((sc)->mac_ver == 0x140)) { |
149 | if (type == AR_EEP_TXGAIN_HIGH_POWER1) |
150 | sc->tx_gain = &ar9271_tx_gain_high_power; |
151 | else |
152 | sc->tx_gain = &ar9271_tx_gain; |
153 | } else |
154 | #endif /* NATHN_USB */ |
155 | if ((AR_READ(sc, AR_AN_SYNTH9)(sc)->ops.read((sc), (0x7868)) & 0x7) == 0x1) { /* XE rev. */ |
156 | if (type == AR_EEP_TXGAIN_HIGH_POWER1) |
157 | sc->tx_gain = &ar9285_2_0_tx_gain_high_power; |
158 | else |
159 | sc->tx_gain = &ar9285_2_0_tx_gain; |
160 | } else { |
161 | if (type == AR_EEP_TXGAIN_HIGH_POWER1) |
162 | sc->tx_gain = &ar9285_1_2_tx_gain_high_power; |
163 | else |
164 | sc->tx_gain = &ar9285_1_2_tx_gain; |
165 | } |
166 | } |
167 | |
168 | void |
169 | ar9285_swap_rom(struct athn_softc *sc) |
170 | { |
171 | struct ar9285_eeprom *eep = sc->eep; |
172 | int i; |
173 | |
174 | eep->modalHeader.antCtrlCommon = |
175 | swap32(eep->modalHeader.antCtrlCommon)(__uint32_t)(__builtin_constant_p(eep->modalHeader.antCtrlCommon ) ? (__uint32_t)(((__uint32_t)(eep->modalHeader.antCtrlCommon ) & 0xff) << 24 | ((__uint32_t)(eep->modalHeader .antCtrlCommon) & 0xff00) << 8 | ((__uint32_t)(eep-> modalHeader.antCtrlCommon) & 0xff0000) >> 8 | ((__uint32_t )(eep->modalHeader.antCtrlCommon) & 0xff000000) >> 24) : __swap32md(eep->modalHeader.antCtrlCommon)); |
176 | eep->modalHeader.antCtrlChain = |
177 | swap32(eep->modalHeader.antCtrlChain)(__uint32_t)(__builtin_constant_p(eep->modalHeader.antCtrlChain ) ? (__uint32_t)(((__uint32_t)(eep->modalHeader.antCtrlChain ) & 0xff) << 24 | ((__uint32_t)(eep->modalHeader .antCtrlChain) & 0xff00) << 8 | ((__uint32_t)(eep-> modalHeader.antCtrlChain) & 0xff0000) >> 8 | ((__uint32_t )(eep->modalHeader.antCtrlChain) & 0xff000000) >> 24) : __swap32md(eep->modalHeader.antCtrlChain)); |
178 | |
179 | for (i = 0; i < AR_EEPROM_MODAL_SPURS5; i++) { |
180 | eep->modalHeader.spurChans[i].spurChan = |
181 | swap16(eep->modalHeader.spurChans[i].spurChan)(__uint16_t)(__builtin_constant_p(eep->modalHeader.spurChans [i].spurChan) ? (__uint16_t)(((__uint16_t)(eep->modalHeader .spurChans[i].spurChan) & 0xffU) << 8 | ((__uint16_t )(eep->modalHeader.spurChans[i].spurChan) & 0xff00U) >> 8) : __swap16md(eep->modalHeader.spurChans[i].spurChan)); |
182 | } |
183 | } |
184 | |
185 | const struct ar_spur_chan * |
186 | ar9285_get_spur_chans(struct athn_softc *sc, int is2ghz) |
187 | { |
188 | const struct ar9285_eeprom *eep = sc->eep; |
189 | |
190 | KASSERT(is2ghz)((is2ghz) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/ar9285.c" , 190, "is2ghz")); |
191 | return (eep->modalHeader.spurChans); |
192 | } |
193 | |
194 | void |
195 | ar9285_init_from_rom(struct athn_softc *sc, struct ieee80211_channel *c, |
196 | struct ieee80211_channel *extc) |
197 | { |
198 | const struct ar9285_eeprom *eep = sc->eep; |
199 | const struct ar9285_modal_eep_header *modal = &eep->modalHeader; |
200 | uint32_t reg, offset = 0x1000; |
201 | uint8_t ob[5], db1[5], db2[5]; |
202 | uint8_t txRxAtten; |
203 | |
204 | AR_WRITE(sc, AR_PHY_SWITCH_COM, modal->antCtrlCommon)(sc)->ops.write((sc), (0x9964), (modal->antCtrlCommon)); |
205 | AR_WRITE(sc, AR_PHY_SWITCH_CHAIN_0, modal->antCtrlChain)(sc)->ops.write((sc), (0x9960), (modal->antCtrlChain)); |
206 | |
207 | reg = AR_READ(sc, AR_PHY_TIMING_CTRL4_0)(sc)->ops.read((sc), (0x9920)); |
208 | reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, modal->iqCalI)(((reg) & ~0x000007e0) | (((uint32_t)(modal->iqCalI) << 5) & 0x000007e0)); |
209 | reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, modal->iqCalQ)(((reg) & ~0x0000001f) | (((uint32_t)(modal->iqCalQ) << 0) & 0x0000001f)); |
210 | AR_WRITE(sc, AR_PHY_TIMING_CTRL4_0, reg)(sc)->ops.write((sc), (0x9920), (reg)); |
211 | |
212 | if (sc->eep_rev >= AR_EEP_MINOR_VER_33) { |
213 | reg = AR_READ(sc, AR_PHY_GAIN_2GHZ)(sc)->ops.read((sc), (0xa20c)); |
214 | reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,(((reg) & ~0x0001f000) | (((uint32_t)(modal->bswMargin ) << 12) & 0x0001f000)) |
215 | modal->bswMargin)(((reg) & ~0x0001f000) | (((uint32_t)(modal->bswMargin ) << 12) & 0x0001f000)); |
216 | reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_DB,(((reg) & ~0x0000003f) | (((uint32_t)(modal->bswAtten) << 0) & 0x0000003f)) |
217 | modal->bswAtten)(((reg) & ~0x0000003f) | (((uint32_t)(modal->bswAtten) << 0) & 0x0000003f)); |
218 | reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,(((reg) & ~0x003e0000) | (((uint32_t)(modal->xatten2Margin ) << 17) & 0x003e0000)) |
219 | modal->xatten2Margin)(((reg) & ~0x003e0000) | (((uint32_t)(modal->xatten2Margin ) << 17) & 0x003e0000)); |
220 | reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_DB,(((reg) & ~0x00000fc0) | (((uint32_t)(modal->xatten2Db ) << 6) & 0x00000fc0)) |
221 | modal->xatten2Db)(((reg) & ~0x00000fc0) | (((uint32_t)(modal->xatten2Db ) << 6) & 0x00000fc0)); |
222 | AR_WRITE(sc, AR_PHY_GAIN_2GHZ, reg)(sc)->ops.write((sc), (0xa20c), (reg)); |
223 | |
224 | /* Duplicate values of chain 0 for chain 1. */ |
225 | reg = AR_READ(sc, AR_PHY_GAIN_2GHZ + offset)(sc)->ops.read((sc), (0xa20c + offset)); |
226 | reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,(((reg) & ~0x0001f000) | (((uint32_t)(modal->bswMargin ) << 12) & 0x0001f000)) |
227 | modal->bswMargin)(((reg) & ~0x0001f000) | (((uint32_t)(modal->bswMargin ) << 12) & 0x0001f000)); |
228 | reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_DB,(((reg) & ~0x0000003f) | (((uint32_t)(modal->bswAtten) << 0) & 0x0000003f)) |
229 | modal->bswAtten)(((reg) & ~0x0000003f) | (((uint32_t)(modal->bswAtten) << 0) & 0x0000003f)); |
230 | reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,(((reg) & ~0x003e0000) | (((uint32_t)(modal->xatten2Margin ) << 17) & 0x003e0000)) |
231 | modal->xatten2Margin)(((reg) & ~0x003e0000) | (((uint32_t)(modal->xatten2Margin ) << 17) & 0x003e0000)); |
232 | reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_DB,(((reg) & ~0x00000fc0) | (((uint32_t)(modal->xatten2Db ) << 6) & 0x00000fc0)) |
233 | modal->xatten2Db)(((reg) & ~0x00000fc0) | (((uint32_t)(modal->xatten2Db ) << 6) & 0x00000fc0)); |
234 | AR_WRITE(sc, AR_PHY_GAIN_2GHZ + offset, reg)(sc)->ops.write((sc), (0xa20c + offset), (reg)); |
235 | } |
236 | if (sc->eep_rev >= AR_EEP_MINOR_VER_33) |
237 | txRxAtten = modal->txRxAtten; |
238 | else /* Workaround for ROM versions < 14.3. */ |
239 | txRxAtten = 23; |
240 | reg = AR_READ(sc, AR_PHY_RXGAIN)(sc)->ops.read((sc), (0x9848)); |
241 | reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAtten)(((reg) & ~0x00003f80) | (((uint32_t)(txRxAtten) << 7) & 0x00003f80)); |
242 | reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_MARGIN, modal->rxTxMargin)(((reg) & ~0x001fc000) | (((uint32_t)(modal->rxTxMargin ) << 14) & 0x001fc000)); |
243 | AR_WRITE(sc, AR_PHY_RXGAIN, reg)(sc)->ops.write((sc), (0x9848), (reg)); |
244 | |
245 | /* Duplicate values of chain 0 for chain 1. */ |
246 | reg = AR_READ(sc, AR_PHY_RXGAIN + offset)(sc)->ops.read((sc), (0x9848 + offset)); |
247 | reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAtten)(((reg) & ~0x00003f80) | (((uint32_t)(txRxAtten) << 7) & 0x00003f80)); |
248 | reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_MARGIN, modal->rxTxMargin)(((reg) & ~0x001fc000) | (((uint32_t)(modal->rxTxMargin ) << 14) & 0x001fc000)); |
249 | AR_WRITE(sc, AR_PHY_RXGAIN + offset, reg)(sc)->ops.write((sc), (0x9848 + offset), (reg)); |
250 | |
251 | if (modal->version >= 3) { |
252 | /* Setup antenna diversity from ROM. */ |
253 | reg = AR_READ(sc, AR_PHY_MULTICHAIN_GAIN_CTL)(sc)->ops.read((sc), (0x99ac)); |
254 | reg = RW(reg, AR9285_PHY_ANT_DIV_CTL_ALL, 0)(((reg) & ~0x7f000000) | (((uint32_t)(0) << 24) & 0x7f000000)); |
255 | reg = RW(reg, AR9285_PHY_ANT_DIV_CTL,(((reg) & ~0x01000000) | (((uint32_t)((modal->ob_234 >> 12) & 0x1) << 24) & 0x01000000)) |
256 | (modal->ob_234 >> 12) & 0x1)(((reg) & ~0x01000000) | (((uint32_t)((modal->ob_234 >> 12) & 0x1) << 24) & 0x01000000)); |
257 | reg = RW(reg, AR9285_PHY_ANT_DIV_ALT_LNACONF,(((reg) & ~0x06000000) | (((uint32_t)((modal->db1_234 >> 12) & 0x3) << 25) & 0x06000000)) |
258 | (modal->db1_234 >> 12) & 0x3)(((reg) & ~0x06000000) | (((uint32_t)((modal->db1_234 >> 12) & 0x3) << 25) & 0x06000000)); |
259 | reg = RW(reg, AR9285_PHY_ANT_DIV_MAIN_LNACONF,(((reg) & ~0x18000000) | (((uint32_t)((modal->db1_234 >> 14) & 0x3) << 27) & 0x18000000)) |
260 | (modal->db1_234 >> 14) & 0x3)(((reg) & ~0x18000000) | (((uint32_t)((modal->db1_234 >> 14) & 0x3) << 27) & 0x18000000)); |
261 | reg = RW(reg, AR9285_PHY_ANT_DIV_ALT_GAINTB,(((reg) & ~0x20000000) | (((uint32_t)((modal->ob_234 >> 13) & 0x1) << 29) & 0x20000000)) |
262 | (modal->ob_234 >> 13) & 0x1)(((reg) & ~0x20000000) | (((uint32_t)((modal->ob_234 >> 13) & 0x1) << 29) & 0x20000000)); |
263 | reg = RW(reg, AR9285_PHY_ANT_DIV_MAIN_GAINTB,(((reg) & ~0x40000000) | (((uint32_t)((modal->ob_234 >> 14) & 0x1) << 30) & 0x40000000)) |
264 | (modal->ob_234 >> 14) & 0x1)(((reg) & ~0x40000000) | (((uint32_t)((modal->ob_234 >> 14) & 0x1) << 30) & 0x40000000)); |
265 | AR_WRITE(sc, AR_PHY_MULTICHAIN_GAIN_CTL, reg)(sc)->ops.write((sc), (0x99ac), (reg)); |
266 | reg = AR_READ(sc, AR_PHY_MULTICHAIN_GAIN_CTL)(sc)->ops.read((sc), (0x99ac)); /* Flush. */ |
267 | |
268 | reg = AR_READ(sc, AR_PHY_CCK_DETECT)(sc)->ops.read((sc), (0xa208)); |
269 | if (modal->ob_234 & (1 << 15)) |
270 | reg |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV0x00002000; |
271 | else |
272 | reg &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV0x00002000; |
273 | AR_WRITE(sc, AR_PHY_CCK_DETECT, reg)(sc)->ops.write((sc), (0xa208), (reg)); |
274 | reg = AR_READ(sc, AR_PHY_CCK_DETECT)(sc)->ops.read((sc), (0xa208)); /* Flush. */ |
275 | } |
276 | if (modal->version >= 2) { |
277 | ob [0] = (modal->ob_01 >> 0) & 0xf; |
278 | ob [1] = (modal->ob_01 >> 4) & 0xf; |
279 | ob [2] = (modal->ob_234 >> 0) & 0xf; |
280 | ob [3] = (modal->ob_234 >> 4) & 0xf; |
281 | ob [4] = (modal->ob_234 >> 8) & 0xf; |
282 | |
283 | db1[0] = (modal->db1_01 >> 0) & 0xf; |
284 | db1[1] = (modal->db1_01 >> 4) & 0xf; |
285 | db1[2] = (modal->db1_234 >> 0) & 0xf; |
286 | db1[3] = (modal->db1_234 >> 4) & 0xf; |
287 | db1[4] = (modal->db1_234 >> 8) & 0xf; |
288 | |
289 | db2[0] = (modal->db2_01 >> 0) & 0xf; |
290 | db2[1] = (modal->db2_01 >> 4) & 0xf; |
291 | db2[2] = (modal->db2_234 >> 0) & 0xf; |
292 | db2[3] = (modal->db2_234 >> 4) & 0xf; |
293 | db2[4] = (modal->db2_234 >> 8) & 0xf; |
294 | |
295 | } else if (modal->version == 1) { |
296 | ob [0] = (modal->ob_01 >> 0) & 0xf; |
297 | ob [1] = (modal->ob_01 >> 4) & 0xf; |
298 | /* Field ob_234 does not exist, use ob_01. */ |
299 | ob [2] = ob [3] = ob [4] = ob [1]; |
300 | |
301 | db1[0] = (modal->db1_01 >> 0) & 0xf; |
302 | db1[1] = (modal->db1_01 >> 4) & 0xf; |
303 | /* Field db1_234 does not exist, use db1_01. */ |
304 | db1[2] = db1[3] = db1[4] = db1[1]; |
305 | |
306 | db2[0] = (modal->db2_01 >> 0) & 0xf; |
307 | db2[1] = (modal->db2_01 >> 4) & 0xf; |
308 | /* Field db2_234 does not exist, use db2_01. */ |
309 | db2[2] = db2[3] = db2[4] = db2[1]; |
310 | |
311 | } else { |
312 | ob [0] = modal->ob_01; |
313 | ob [1] = ob [2] = ob [3] = ob [4] = ob [0]; |
314 | |
315 | db1[0] = modal->db1_01; |
316 | db1[1] = db1[2] = db1[3] = db1[4] = db1[0]; |
317 | |
318 | /* Field db2_01 does not exist, use db1_01. */ |
319 | db2[0] = modal->db1_01; |
320 | db2[1] = db2[2] = db2[3] = db2[4] = db2[0]; |
321 | } |
322 | #if NATHN_USB1 > 0 |
323 | if (AR_SREV_9271(sc)((sc)->mac_ver == 0x140)) { |
324 | reg = AR_READ(sc, AR9285_AN_RF2G3)(sc)->ops.read((sc), (0x7828)); |
325 | reg = RW(reg, AR9271_AN_RF2G3_OB_CCK, ob [0])(((reg) & ~0x001c0000) | (((uint32_t)(ob [0]) << 18 ) & 0x001c0000)); |
326 | reg = RW(reg, AR9271_AN_RF2G3_OB_PSK, ob [1])(((reg) & ~0x00038000) | (((uint32_t)(ob [1]) << 15 ) & 0x00038000)); |
327 | reg = RW(reg, AR9271_AN_RF2G3_OB_QAM, ob [2])(((reg) & ~0x00007000) | (((uint32_t)(ob [2]) << 12 ) & 0x00007000)); |
328 | reg = RW(reg, AR9271_AN_RF2G3_DB1, db1[0])(((reg) & ~0x00e00000) | (((uint32_t)(db1[0]) << 21 ) & 0x00e00000)); |
329 | AR_WRITE(sc, AR9285_AN_RF2G3, reg)(sc)->ops.write((sc), (0x7828), (reg)); |
330 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
331 | DELAY(100)(*delay_func)(100); |
332 | reg = AR_READ(sc, AR9285_AN_RF2G4)(sc)->ops.read((sc), (0x782c)); |
333 | reg = RW(reg, AR9271_AN_RF2G4_DB2, db2[0])(((reg) & ~0xe0000000) | (((uint32_t)(db2[0]) << 29 ) & 0xe0000000)); |
334 | AR_WRITE(sc, AR9285_AN_RF2G4, reg)(sc)->ops.write((sc), (0x782c), (reg)); |
335 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
336 | DELAY(100)(*delay_func)(100); |
337 | } else |
338 | #endif /* ATHN_USB */ |
339 | { |
340 | reg = AR_READ(sc, AR9285_AN_RF2G3)(sc)->ops.read((sc), (0x7828)); |
341 | reg = RW(reg, AR9285_AN_RF2G3_OB_0, ob [0])(((reg) & ~0x00e00000) | (((uint32_t)(ob [0]) << 21 ) & 0x00e00000)); |
342 | reg = RW(reg, AR9285_AN_RF2G3_OB_1, ob [1])(((reg) & ~0x001c0000) | (((uint32_t)(ob [1]) << 18 ) & 0x001c0000)); |
343 | reg = RW(reg, AR9285_AN_RF2G3_OB_2, ob [2])(((reg) & ~0x00038000) | (((uint32_t)(ob [2]) << 15 ) & 0x00038000)); |
344 | reg = RW(reg, AR9285_AN_RF2G3_OB_3, ob [3])(((reg) & ~0x00007000) | (((uint32_t)(ob [3]) << 12 ) & 0x00007000)); |
345 | reg = RW(reg, AR9285_AN_RF2G3_OB_4, ob [4])(((reg) & ~0x00000e00) | (((uint32_t)(ob [4]) << 9) & 0x00000e00)); |
346 | reg = RW(reg, AR9285_AN_RF2G3_DB1_0, db1[0])(((reg) & ~0x000001c0) | (((uint32_t)(db1[0]) << 6) & 0x000001c0)); |
347 | reg = RW(reg, AR9285_AN_RF2G3_DB1_1, db1[1])(((reg) & ~0x00000038) | (((uint32_t)(db1[1]) << 3) & 0x00000038)); |
348 | reg = RW(reg, AR9285_AN_RF2G3_DB1_2, db1[2])(((reg) & ~0x00000007) | (((uint32_t)(db1[2]) << 0) & 0x00000007)); |
349 | AR_WRITE(sc, AR9285_AN_RF2G3, reg)(sc)->ops.write((sc), (0x7828), (reg)); |
350 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
351 | DELAY(100)(*delay_func)(100); |
352 | reg = AR_READ(sc, AR9285_AN_RF2G4)(sc)->ops.read((sc), (0x782c)); |
353 | reg = RW(reg, AR9285_AN_RF2G4_DB1_3, db1[3])(((reg) & ~0xe0000000) | (((uint32_t)(db1[3]) << 29 ) & 0xe0000000)); |
354 | reg = RW(reg, AR9285_AN_RF2G4_DB1_4, db1[4])(((reg) & ~0x1c000000) | (((uint32_t)(db1[4]) << 26 ) & 0x1c000000)); |
355 | reg = RW(reg, AR9285_AN_RF2G4_DB2_0, db2[0])(((reg) & ~0x03800000) | (((uint32_t)(db2[0]) << 23 ) & 0x03800000)); |
356 | reg = RW(reg, AR9285_AN_RF2G4_DB2_1, db2[1])(((reg) & ~0x00700000) | (((uint32_t)(db2[1]) << 20 ) & 0x00700000)); |
357 | reg = RW(reg, AR9285_AN_RF2G4_DB2_2, db2[2])(((reg) & ~0x000e0000) | (((uint32_t)(db2[2]) << 17 ) & 0x000e0000)); |
358 | reg = RW(reg, AR9285_AN_RF2G4_DB2_3, db2[3])(((reg) & ~0x0001c000) | (((uint32_t)(db2[3]) << 14 ) & 0x0001c000)); |
359 | reg = RW(reg, AR9285_AN_RF2G4_DB2_4, db2[4])(((reg) & ~0x00003800) | (((uint32_t)(db2[4]) << 11 ) & 0x00003800)); |
360 | AR_WRITE(sc, AR9285_AN_RF2G4, reg)(sc)->ops.write((sc), (0x782c), (reg)); |
361 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
362 | DELAY(100)(*delay_func)(100); |
363 | } |
364 | |
365 | reg = AR_READ(sc, AR_PHY_SETTLING)(sc)->ops.read((sc), (0x9844)); |
366 | reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->switchSettling)(((reg) & ~0x00003f80) | (((uint32_t)(modal->switchSettling ) << 7) & 0x00003f80)); |
367 | AR_WRITE(sc, AR_PHY_SETTLING, reg)(sc)->ops.write((sc), (0x9844), (reg)); |
368 | |
369 | reg = AR_READ(sc, AR_PHY_DESIRED_SZ)(sc)->ops.read((sc), (0x9850)); |
370 | reg = RW(reg, AR_PHY_DESIRED_SZ_ADC, modal->adcDesiredSize)(((reg) & ~0x000000ff) | (((uint32_t)(modal->adcDesiredSize ) << 0) & 0x000000ff)); |
371 | AR_WRITE(sc, AR_PHY_DESIRED_SZ, reg)(sc)->ops.write((sc), (0x9850), (reg)); |
372 | |
373 | reg = SM(AR_PHY_RF_CTL4_TX_END_XPAA_OFF, modal->txEndToXpaOff)(((uint32_t)(modal->txEndToXpaOff) << 16) & 0x00ff0000 ); |
374 | reg |= SM(AR_PHY_RF_CTL4_TX_END_XPAB_OFF, modal->txEndToXpaOff)(((uint32_t)(modal->txEndToXpaOff) << 24) & 0xff000000 ); |
375 | reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAA_ON, modal->txFrameToXpaOn)(((uint32_t)(modal->txFrameToXpaOn) << 0) & 0x000000ff ); |
376 | reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAB_ON, modal->txFrameToXpaOn)(((uint32_t)(modal->txFrameToXpaOn) << 8) & 0x0000ff00 ); |
377 | AR_WRITE(sc, AR_PHY_RF_CTL4, reg)(sc)->ops.write((sc), (0x9834), (reg)); |
378 | |
379 | reg = AR_READ(sc, AR_PHY_RF_CTL3)(sc)->ops.read((sc), (0x9828)); |
380 | reg = RW(reg, AR_PHY_TX_END_TO_A2_RX_ON, modal->txEndToRxOn)(((reg) & ~0x00ff0000) | (((uint32_t)(modal->txEndToRxOn ) << 16) & 0x00ff0000)); |
381 | AR_WRITE(sc, AR_PHY_RF_CTL3, reg)(sc)->ops.write((sc), (0x9828), (reg)); |
382 | |
383 | reg = AR_READ(sc, AR_PHY_CCA(0))(sc)->ops.read((sc), ((0x9864 + (0) * 0x1000))); |
384 | reg = RW(reg, AR9280_PHY_CCA_THRESH62, modal->thresh62)(((reg) & ~0x000ff000) | (((uint32_t)(modal->thresh62) << 12) & 0x000ff000)); |
385 | AR_WRITE(sc, AR_PHY_CCA(0), reg)(sc)->ops.write((sc), ((0x9864 + (0) * 0x1000)), (reg)); |
386 | |
387 | reg = AR_READ(sc, AR_PHY_EXT_CCA0)(sc)->ops.read((sc), (0x99b8)); |
388 | reg = RW(reg, AR_PHY_EXT_CCA0_THRESH62, modal->thresh62)(((reg) & ~0x000000ff) | (((uint32_t)(modal->thresh62) << 0) & 0x000000ff)); |
389 | AR_WRITE(sc, AR_PHY_EXT_CCA0, reg)(sc)->ops.write((sc), (0x99b8), (reg)); |
390 | |
391 | if (sc->eep_rev >= AR_EEP_MINOR_VER_22) { |
392 | reg = AR_READ(sc, AR_PHY_RF_CTL2)(sc)->ops.read((sc), (0x9824)); |
393 | reg = RW(reg, AR_PHY_TX_END_PA_ON,(((reg) & ~0x0000ff00) | (((uint32_t)(modal->txFrameToPaOn ) << 8) & 0x0000ff00)) |
394 | modal->txFrameToPaOn)(((reg) & ~0x0000ff00) | (((uint32_t)(modal->txFrameToPaOn ) << 8) & 0x0000ff00)); |
395 | reg = RW(reg, AR_PHY_TX_END_DATA_START,(((reg) & ~0x000000ff) | (((uint32_t)(modal->txFrameToDataStart ) << 0) & 0x000000ff)) |
396 | modal->txFrameToDataStart)(((reg) & ~0x000000ff) | (((uint32_t)(modal->txFrameToDataStart ) << 0) & 0x000000ff)); |
397 | AR_WRITE(sc, AR_PHY_RF_CTL2, reg)(sc)->ops.write((sc), (0x9824), (reg)); |
398 | } |
399 | if (sc->eep_rev >= AR_EEP_MINOR_VER_33 && extc != NULL((void *)0)) { |
400 | reg = AR_READ(sc, AR_PHY_SETTLING)(sc)->ops.read((sc), (0x9844)); |
401 | reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->swSettleHt40)(((reg) & ~0x00003f80) | (((uint32_t)(modal->swSettleHt40 ) << 7) & 0x00003f80)); |
402 | AR_WRITE(sc, AR_PHY_SETTLING, reg)(sc)->ops.write((sc), (0x9844), (reg)); |
403 | } |
404 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
405 | } |
406 | |
407 | void |
408 | ar9285_pa_calib(struct athn_softc *sc) |
409 | { |
410 | /* List of registers that need to be saved/restored. */ |
411 | static const uint16_t regs[] = { |
412 | AR9285_AN_TOP30x786c, |
413 | AR9285_AN_RXTXBB10x7854, |
414 | AR9285_AN_RF2G10x7820, |
415 | AR9285_AN_RF2G20x7824, |
416 | AR9285_AN_TOP20x7868, |
417 | AR9285_AN_RF2G80x783c, |
418 | AR9285_AN_RF2G70x7838 |
419 | }; |
420 | uint32_t svg[7], reg, ccomp_svg; |
421 | int i; |
422 | |
423 | /* No PA calibration needed for high power solutions. */ |
424 | if (AR_SREV_9285(sc)((sc)->mac_ver == 0x0c0) && |
425 | ((struct ar9285_base_eep_header *)sc->eep)->txGainType == |
426 | AR_EEP_TXGAIN_HIGH_POWER1) /* XXX AR9287? */ |
427 | return; |
428 | |
429 | /* Save registers. */ |
430 | for (i = 0; i < nitems(regs)(sizeof((regs)) / sizeof((regs)[0])); i++) |
431 | svg[i] = AR_READ(sc, regs[i])(sc)->ops.read((sc), (regs[i])); |
432 | |
433 | AR_CLRBITS(sc, AR9285_AN_RF2G6, 1)(sc)->ops.write((sc), (0x7834), ((sc)->ops.read((sc), ( 0x7834)) & ~(1))); |
434 | AR_SETBITS(sc, AR_PHY(2), 1 << 27)(sc)->ops.write((sc), ((0x9800 + (2) * 4)), ((sc)->ops. read((sc), ((0x9800 + (2) * 4))) | (1 << 27))); |
435 | |
436 | AR_SETBITS(sc, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC)(sc)->ops.write((sc), (0x786c), ((sc)->ops.read((sc), ( 0x786c)) | (0x00800000))); |
437 | AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1)(sc)->ops.write((sc), (0x7854), ((sc)->ops.read((sc), ( 0x7854)) | (0x00000020))); |
438 | AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I)(sc)->ops.write((sc), (0x7854), ((sc)->ops.read((sc), ( 0x7854)) | (0x00000080))); |
439 | AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF)(sc)->ops.write((sc), (0x7854), ((sc)->ops.read((sc), ( 0x7854)) | (0x00000100))); |
440 | AR_CLRBITS(sc, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL)(sc)->ops.write((sc), (0x7824), ((sc)->ops.read((sc), ( 0x7824)) & ~(0x00001000))); |
441 | AR_CLRBITS(sc, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB)(sc)->ops.write((sc), (0x7838), ((sc)->ops.read((sc), ( 0x7838)) & ~(0x00000002))); |
442 | AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL)(sc)->ops.write((sc), (0x7820), ((sc)->ops.read((sc), ( 0x7820)) & ~(0x00000800))); |
443 | /* Power down PA drivers. */ |
444 | AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1)(sc)->ops.write((sc), (0x7820), ((sc)->ops.read((sc), ( 0x7820)) & ~(0x02000000))); |
445 | AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2)(sc)->ops.write((sc), (0x7820), ((sc)->ops.read((sc), ( 0x7820)) & ~(0x01000000))); |
446 | AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT)(sc)->ops.write((sc), (0x7820), ((sc)->ops.read((sc), ( 0x7820)) & ~(0x00800000))); |
447 | |
448 | reg = AR_READ(sc, AR9285_AN_RF2G8)(sc)->ops.read((sc), (0x783c)); |
449 | reg = RW(reg, AR9285_AN_RF2G8_PADRVGN2TAB0, 7)(((reg) & ~0x0001c000) | (((uint32_t)(7) << 14) & 0x0001c000)); |
450 | AR_WRITE(sc, AR9285_AN_RF2G8, reg)(sc)->ops.write((sc), (0x783c), (reg)); |
451 | |
452 | reg = AR_READ(sc, AR9285_AN_RF2G7)(sc)->ops.read((sc), (0x7838)); |
453 | reg = RW(reg, AR9285_AN_RF2G7_PADRVGN2TAB0, 0)(((reg) & ~0xe0000000) | (((uint32_t)(0) << 29) & 0xe0000000)); |
454 | AR_WRITE(sc, AR9285_AN_RF2G7, reg)(sc)->ops.write((sc), (0x7838), (reg)); |
455 | |
456 | reg = AR_READ(sc, AR9285_AN_RF2G6)(sc)->ops.read((sc), (0x7834)); |
457 | /* Save compensation capacitor value. */ |
458 | ccomp_svg = MS(reg, AR9285_AN_RF2G6_CCOMP)(((uint32_t)(reg) & 0x00007800) >> 11); |
459 | /* Program compensation capacitor for dynamic PA. */ |
460 | reg = RW(reg, AR9285_AN_RF2G6_CCOMP, 0xf)(((reg) & ~0x00007800) | (((uint32_t)(0xf) << 11) & 0x00007800)); |
461 | AR_WRITE(sc, AR9285_AN_RF2G6, reg)(sc)->ops.write((sc), (0x7834), (reg)); |
462 | |
463 | AR_WRITE(sc, AR9285_AN_TOP2, AR9285_AN_TOP2_DEFAULT)(sc)->ops.write((sc), (0x7868), (0xca0358a0)); |
464 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
465 | DELAY(30)(*delay_func)(30); |
466 | |
467 | /* Clear offsets 6-1. */ |
468 | AR_CLRBITS(sc, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS_6_1)(sc)->ops.write((sc), (0x7834), ((sc)->ops.read((sc), ( 0x7834)) & ~(0x03f00000))); |
469 | /* Clear offset 0. */ |
470 | AR_CLRBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP)(sc)->ops.write((sc), (0x7828), ((sc)->ops.read((sc), ( 0x7828)) & ~(0x02000000))); |
471 | /* Set offsets 6-1. */ |
472 | for (i = 6; i >= 1; i--) { |
473 | AR_SETBITS(sc, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS(i))(sc)->ops.write((sc), (0x7834), ((sc)->ops.read((sc), ( 0x7834)) | ((1 << (19 + (i)))))); |
474 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
475 | DELAY(1)(*delay_func)(1); |
476 | if (AR_READ(sc, AR9285_AN_RF2G9)(sc)->ops.read((sc), (0x7840)) & AR9285_AN_RXTXBB1_SPARE90x00000001) { |
477 | AR_SETBITS(sc, AR9285_AN_RF2G6,(sc)->ops.write((sc), (0x7834), ((sc)->ops.read((sc), ( 0x7834)) | ((1 << (19 + (i)))))) |
478 | AR9285_AN_RF2G6_OFFS(i))(sc)->ops.write((sc), (0x7834), ((sc)->ops.read((sc), ( 0x7834)) | ((1 << (19 + (i)))))); |
479 | } else { |
480 | AR_CLRBITS(sc, AR9285_AN_RF2G6,(sc)->ops.write((sc), (0x7834), ((sc)->ops.read((sc), ( 0x7834)) & ~((1 << (19 + (i)))))) |
481 | AR9285_AN_RF2G6_OFFS(i))(sc)->ops.write((sc), (0x7834), ((sc)->ops.read((sc), ( 0x7834)) & ~((1 << (19 + (i)))))); |
482 | } |
483 | } |
484 | /* Set offset 0. */ |
485 | AR_SETBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP)(sc)->ops.write((sc), (0x7828), ((sc)->ops.read((sc), ( 0x7828)) | (0x02000000))); |
486 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
487 | DELAY(1)(*delay_func)(1); |
488 | if (AR_READ(sc, AR9285_AN_RF2G9)(sc)->ops.read((sc), (0x7840)) & AR9285_AN_RXTXBB1_SPARE90x00000001) |
489 | AR_SETBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP)(sc)->ops.write((sc), (0x7828), ((sc)->ops.read((sc), ( 0x7828)) | (0x02000000))); |
490 | else |
491 | AR_CLRBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP)(sc)->ops.write((sc), (0x7828), ((sc)->ops.read((sc), ( 0x7828)) & ~(0x02000000))); |
492 | |
493 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
494 | |
495 | AR_SETBITS(sc, AR9285_AN_RF2G6, 1)(sc)->ops.write((sc), (0x7834), ((sc)->ops.read((sc), ( 0x7834)) | (1))); |
496 | AR_CLRBITS(sc, AR_PHY(2), 1 << 27)(sc)->ops.write((sc), ((0x9800 + (2) * 4)), ((sc)->ops. read((sc), ((0x9800 + (2) * 4))) & ~(1 << 27))); |
497 | |
498 | /* Restore registers. */ |
499 | for (i = 0; i < nitems(regs)(sizeof((regs)) / sizeof((regs)[0])); i++) |
500 | AR_WRITE(sc, regs[i], svg[i])(sc)->ops.write((sc), (regs[i]), (svg[i])); |
501 | |
502 | /* Restore compensation capacitor value. */ |
503 | reg = AR_READ(sc, AR9285_AN_RF2G6)(sc)->ops.read((sc), (0x7834)); |
504 | reg = RW(reg, AR9285_AN_RF2G6_CCOMP, ccomp_svg)(((reg) & ~0x00007800) | (((uint32_t)(ccomp_svg) << 11) & 0x00007800)); |
505 | AR_WRITE(sc, AR9285_AN_RF2G6, reg)(sc)->ops.write((sc), (0x7834), (reg)); |
506 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
507 | } |
508 | |
509 | void |
510 | ar9271_pa_calib(struct athn_softc *sc) |
511 | { |
512 | #if NATHN_USB1 > 0 |
513 | /* List of registers that need to be saved/restored. */ |
514 | static const uint16_t regs[] = { |
515 | AR9285_AN_TOP30x786c, |
516 | AR9285_AN_RXTXBB10x7854, |
517 | AR9285_AN_RF2G10x7820, |
518 | AR9285_AN_RF2G20x7824, |
519 | AR9285_AN_TOP20x7868, |
520 | AR9285_AN_RF2G80x783c, |
521 | AR9285_AN_RF2G70x7838 |
522 | }; |
523 | uint32_t svg[7], reg, rf2g3_svg; |
524 | int i; |
525 | |
526 | /* Save registers. */ |
527 | for (i = 0; i < nitems(regs)(sizeof((regs)) / sizeof((regs)[0])); i++) |
528 | svg[i] = AR_READ(sc, regs[i])(sc)->ops.read((sc), (regs[i])); |
529 | |
530 | AR_CLRBITS(sc, AR9285_AN_RF2G6, 1)(sc)->ops.write((sc), (0x7834), ((sc)->ops.read((sc), ( 0x7834)) & ~(1))); |
531 | AR_SETBITS(sc, AR_PHY(2), 1 << 27)(sc)->ops.write((sc), ((0x9800 + (2) * 4)), ((sc)->ops. read((sc), ((0x9800 + (2) * 4))) | (1 << 27))); |
532 | |
533 | AR_SETBITS(sc, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC)(sc)->ops.write((sc), (0x786c), ((sc)->ops.read((sc), ( 0x786c)) | (0x00800000))); |
534 | AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1)(sc)->ops.write((sc), (0x7854), ((sc)->ops.read((sc), ( 0x7854)) | (0x00000020))); |
535 | AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I)(sc)->ops.write((sc), (0x7854), ((sc)->ops.read((sc), ( 0x7854)) | (0x00000080))); |
536 | AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF)(sc)->ops.write((sc), (0x7854), ((sc)->ops.read((sc), ( 0x7854)) | (0x00000100))); |
537 | AR_CLRBITS(sc, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL)(sc)->ops.write((sc), (0x7824), ((sc)->ops.read((sc), ( 0x7824)) & ~(0x00001000))); |
538 | AR_CLRBITS(sc, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB)(sc)->ops.write((sc), (0x7838), ((sc)->ops.read((sc), ( 0x7838)) & ~(0x00000002))); |
539 | AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL)(sc)->ops.write((sc), (0x7820), ((sc)->ops.read((sc), ( 0x7820)) & ~(0x00000800))); |
540 | /* Power down PA drivers. */ |
541 | AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1)(sc)->ops.write((sc), (0x7820), ((sc)->ops.read((sc), ( 0x7820)) & ~(0x02000000))); |
542 | AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2)(sc)->ops.write((sc), (0x7820), ((sc)->ops.read((sc), ( 0x7820)) & ~(0x01000000))); |
543 | AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT)(sc)->ops.write((sc), (0x7820), ((sc)->ops.read((sc), ( 0x7820)) & ~(0x00800000))); |
544 | |
545 | reg = AR_READ(sc, AR9285_AN_RF2G8)(sc)->ops.read((sc), (0x783c)); |
546 | reg = RW(reg, AR9285_AN_RF2G8_PADRVGN2TAB0, 7)(((reg) & ~0x0001c000) | (((uint32_t)(7) << 14) & 0x0001c000)); |
547 | AR_WRITE(sc, AR9285_AN_RF2G8, reg)(sc)->ops.write((sc), (0x783c), (reg)); |
548 | |
549 | reg = AR_READ(sc, AR9285_AN_RF2G7)(sc)->ops.read((sc), (0x7838)); |
550 | reg = RW(reg, AR9285_AN_RF2G7_PADRVGN2TAB0, 0)(((reg) & ~0xe0000000) | (((uint32_t)(0) << 29) & 0xe0000000)); |
551 | AR_WRITE(sc, AR9285_AN_RF2G7, reg)(sc)->ops.write((sc), (0x7838), (reg)); |
552 | |
553 | /* Save compensation capacitor value. */ |
554 | reg = rf2g3_svg = AR_READ(sc, AR9285_AN_RF2G3)(sc)->ops.read((sc), (0x7828)); |
555 | /* Program compensation capacitor for dynamic PA. */ |
556 | reg = RW(reg, AR9271_AN_RF2G3_CCOMP, 0xfff)(((reg) & ~0x00000fff) | (((uint32_t)(0xfff) << 0) & 0x00000fff)); |
557 | AR_WRITE(sc, AR9285_AN_RF2G3, reg)(sc)->ops.write((sc), (0x7828), (reg)); |
558 | |
559 | AR_WRITE(sc, AR9285_AN_TOP2, AR9285_AN_TOP2_DEFAULT)(sc)->ops.write((sc), (0x7868), (0xca0358a0)); |
560 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
561 | DELAY(30)(*delay_func)(30); |
562 | |
563 | /* Clear offsets 6-0. */ |
564 | AR_CLRBITS(sc, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS_6_0)(sc)->ops.write((sc), (0x7834), ((sc)->ops.read((sc), ( 0x7834)) & ~(0x07f00000))); |
565 | /* Set offsets 6-1. */ |
566 | for (i = 6; i >= 1; i--) { |
567 | reg = AR_READ(sc, AR9285_AN_RF2G6)(sc)->ops.read((sc), (0x7834)); |
568 | reg |= AR9271_AN_RF2G6_OFFS(i)(1 << (20 + (i))); |
569 | AR_WRITE(sc, AR9285_AN_RF2G6, reg)(sc)->ops.write((sc), (0x7834), (reg)); |
570 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
571 | DELAY(1)(*delay_func)(1); |
572 | if (!(AR_READ(sc, AR9285_AN_RF2G9)(sc)->ops.read((sc), (0x7840)) & AR9285_AN_RXTXBB1_SPARE90x00000001)) |
573 | reg &= ~AR9271_AN_RF2G6_OFFS(i)(1 << (20 + (i))); |
574 | AR_WRITE(sc, AR9285_AN_RF2G6, reg)(sc)->ops.write((sc), (0x7834), (reg)); |
575 | } |
576 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
577 | |
578 | AR_SETBITS(sc, AR9285_AN_RF2G6, 1)(sc)->ops.write((sc), (0x7834), ((sc)->ops.read((sc), ( 0x7834)) | (1))); |
579 | AR_CLRBITS(sc, AR_PHY(2), 1 << 27)(sc)->ops.write((sc), ((0x9800 + (2) * 4)), ((sc)->ops. read((sc), ((0x9800 + (2) * 4))) & ~(1 << 27))); |
580 | |
581 | /* Restore registers. */ |
582 | for (i = 0; i < nitems(regs)(sizeof((regs)) / sizeof((regs)[0])); i++) |
583 | AR_WRITE(sc, regs[i], svg[i])(sc)->ops.write((sc), (regs[i]), (svg[i])); |
584 | |
585 | /* Restore compensation capacitor value. */ |
586 | AR_WRITE(sc, AR9285_AN_RF2G3, rf2g3_svg)(sc)->ops.write((sc), (0x7828), (rf2g3_svg)); |
587 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
588 | #endif /* NATHN_USB */ |
589 | } |
590 | |
591 | /* |
592 | * Carrier Leakage Calibration. |
593 | */ |
594 | int |
595 | ar9285_cl_cal(struct athn_softc *sc, struct ieee80211_channel *c, |
596 | struct ieee80211_channel *extc) |
597 | { |
598 | int ntries; |
599 | |
600 | AR_SETBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE)(sc)->ops.write((sc), (0xa358), ((sc)->ops.read((sc), ( 0xa358)) | (0x00000002))); |
601 | if (0 && extc == NULL((void *)0)) { /* XXX IS_CHAN_HT20!! */ |
602 | AR_SETBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE)(sc)->ops.write((sc), (0xa358), ((sc)->ops.read((sc), ( 0xa358)) | (0x00000001))); |
603 | AR_SETBITS(sc, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN)(sc)->ops.write((sc), (0x9804), ((sc)->ops.read((sc), ( 0x9804)) | (0x00000004))); |
604 | AR_CLRBITS(sc, AR_PHY_AGC_CONTROL,(sc)->ops.write((sc), (0x9860), ((sc)->ops.read((sc), ( 0x9860)) & ~(0x00010000))) |
605 | AR_PHY_AGC_CONTROL_FLTR_CAL)(sc)->ops.write((sc), (0x9860), ((sc)->ops.read((sc), ( 0x9860)) & ~(0x00010000))); |
606 | AR_CLRBITS(sc, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE)(sc)->ops.write((sc), (0xa258), ((sc)->ops.read((sc), ( 0xa258)) & ~(0x00400000))); |
607 | AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL)(sc)->ops.write((sc), (0x9860), ((sc)->ops.read((sc), ( 0x9860)) | (0x00000001))); |
608 | for (ntries = 0; ntries < 10000; ntries++) { |
609 | if (!(AR_READ(sc, AR_PHY_AGC_CONTROL)(sc)->ops.read((sc), (0x9860)) & |
610 | AR_PHY_AGC_CONTROL_CAL0x00000001)) |
611 | break; |
612 | DELAY(10)(*delay_func)(10); |
613 | } |
614 | if (ntries == 10000) |
615 | return (ETIMEDOUT60); |
616 | AR_CLRBITS(sc, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN)(sc)->ops.write((sc), (0x9804), ((sc)->ops.read((sc), ( 0x9804)) & ~(0x00000004))); |
617 | AR_CLRBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE)(sc)->ops.write((sc), (0xa358), ((sc)->ops.read((sc), ( 0xa358)) & ~(0x00000001))); |
618 | AR_CLRBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE)(sc)->ops.write((sc), (0xa358), ((sc)->ops.read((sc), ( 0xa358)) & ~(0x00000002))); |
619 | } |
620 | AR_CLRBITS(sc, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC)(sc)->ops.write((sc), (0x982c), ((sc)->ops.read((sc), ( 0x982c)) & ~(0x00008000))); |
621 | AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL)(sc)->ops.write((sc), (0x9860), ((sc)->ops.read((sc), ( 0x9860)) | (0x00010000))); |
622 | AR_SETBITS(sc, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE)(sc)->ops.write((sc), (0xa258), ((sc)->ops.read((sc), ( 0xa258)) | (0x00400000))); |
623 | AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL)(sc)->ops.write((sc), (0x9860), ((sc)->ops.read((sc), ( 0x9860)) | (0x00000001))); |
624 | for (ntries = 0; ntries < 10000; ntries++) { |
625 | if (!(AR_READ(sc, AR_PHY_AGC_CONTROL)(sc)->ops.read((sc), (0x9860)) & |
626 | AR_PHY_AGC_CONTROL_CAL0x00000001)) |
627 | break; |
628 | DELAY(10)(*delay_func)(10); |
629 | } |
630 | if (ntries == 10000) |
631 | return (ETIMEDOUT60); |
632 | AR_SETBITS(sc, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC)(sc)->ops.write((sc), (0x982c), ((sc)->ops.read((sc), ( 0x982c)) | (0x00008000))); |
633 | AR_CLRBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE)(sc)->ops.write((sc), (0xa358), ((sc)->ops.read((sc), ( 0xa358)) & ~(0x00000002))); |
634 | AR_CLRBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL)(sc)->ops.write((sc), (0x9860), ((sc)->ops.read((sc), ( 0x9860)) & ~(0x00010000))); |
635 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
636 | return (0); |
637 | } |
638 | |
639 | void |
640 | ar9271_load_ani(struct athn_softc *sc) |
641 | { |
642 | #if NATHN_USB1 > 0 |
643 | /* Write ANI registers. */ |
644 | AR_WRITE(sc, AR_PHY_DESIRED_SZ, 0x6d4000e2)(sc)->ops.write((sc), (0x9850), (0x6d4000e2)); |
645 | AR_WRITE(sc, AR_PHY_AGC_CTL1, 0x3139605e)(sc)->ops.write((sc), (0x985c), (0x3139605e)); |
646 | AR_WRITE(sc, AR_PHY_FIND_SIG, 0x7ec84d2e)(sc)->ops.write((sc), (0x9858), (0x7ec84d2e)); |
647 | AR_WRITE(sc, AR_PHY_SFCORR_LOW, 0x06903881)(sc)->ops.write((sc), (0x986c), (0x06903881)); |
648 | AR_WRITE(sc, AR_PHY_SFCORR, 0x5ac640d0)(sc)->ops.write((sc), (0x9868), (0x5ac640d0)); |
649 | AR_WRITE(sc, AR_PHY_CCK_DETECT, 0x803e68c8)(sc)->ops.write((sc), (0xa208), (0x803e68c8)); |
650 | AR_WRITE(sc, AR_PHY_TIMING5, 0xd00a8007)(sc)->ops.write((sc), (0x9924), (0xd00a8007)); |
651 | AR_WRITE(sc, AR_PHY_SFCORR_EXT, 0x05eea6d4)(sc)->ops.write((sc), (0x99c0), (0x05eea6d4)); |
652 | AR_WRITE_BARRIER(sc)(sc)->ops.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)((sc)->mac_ver == 0x140)) |
669 | return (0); |
670 | |
671 | mask = 0; |
672 | nclcs = 0; |
673 | reg = AR_READ(sc, AR_PHY_TX_PWRCTRL7)(sc)->ops.read((sc), (0xa274)); |
674 | maxgain = MS(reg, AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX)(((uint32_t)(reg) & 0x0007e000) >> 13); |
675 | for (i = 0; i <= maxgain; i++) { |
676 | reg = AR_READ(sc, AR_PHY_TX_GAIN_TBL(i))(sc)->ops.read((sc), ((0xa300 + (i) * 4))); |
677 | clcgain = MS(reg, AR_PHY_TX_GAIN_CLC)(((uint32_t)(reg) & 0x0000001e) >> 1); |
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))(sc)->ops.read((sc), ((0xa35c + (i) * 4))); |
687 | if (MS(reg, AR_PHY_CLC_I0)(((uint32_t)(reg) & 0x07ff0000) >> 16) == 0) |
688 | thresh++; |
689 | if (MS(reg, AR_PHY_CLC_Q0)(((uint32_t)(reg) & 0x0000ffd0) >> 5) == 0) |
690 | thresh++; |
691 | } |
692 | if (thresh <= AR9285_CL_CAL_REDO_THRESH1) |
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)(sc)->ops.read((sc), (0x7830)); |
698 | if ((AR_READ(sc, AR_AN_SYNTH9)(sc)->ops.read((sc), (0x7868)) & 0x7) == 0x1) /* XE rev. */ |
699 | reg = RW(reg, AR9285_AN_RF2G5_IC50TX, 0x5)(((reg) & ~0x00000700) | (((uint32_t)(0x5) << 8) & 0x00000700)); |
700 | else |
701 | reg = RW(reg, AR9285_AN_RF2G5_IC50TX, 0x4)(((reg) & ~0x00000700) | (((uint32_t)(0x4) << 8) & 0x00000700)); |
702 | AR_WRITE(sc, AR9285_AN_RF2G5, reg)(sc)->ops.write((sc), (0x7830), (reg)); |
703 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
704 | error = ar9285_cl_cal(sc, c, extc); |
705 | AR_WRITE(sc, AR9285_AN_RF2G5, rf2g5_svg)(sc)->ops.write((sc), (0x7830), (rf2g5_svg)); |
706 | AR_WRITE_BARRIER(sc)(sc)->ops.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_PIERS3; |
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_ICEPTS5, 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_MASK4]; |
746 | uint8_t pdadcs[AR_NUM_PDADC_VALUES128]; |
747 | uint8_t xpdgains[AR9285_NUM_PD_GAINS2]; |
748 | uint8_t overlap; |
749 | uint32_t reg; |
750 | int i, nxpdgains; |
751 | |
752 | if (sc->eep_rev < AR_EEP_MINOR_VER_22) { |
753 | overlap = MS(AR_READ(sc, AR_PHY_TPCRG5),(((uint32_t)((sc)->ops.read((sc), (0xa26c))) & 0x0000000f ) >> 0) |
754 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP)(((uint32_t)((sc)->ops.read((sc), (0xa26c))) & 0x0000000f ) >> 0); |
755 | } else |
756 | overlap = eep->modalHeader.pdGainOverlap; |
757 | |
758 | nxpdgains = 0; |
759 | memset(xpdgains, 0, sizeof(xpdgains))__builtin_memset((xpdgains), (0), (sizeof(xpdgains))); |
760 | for (i = AR9285_PD_GAINS_IN_MASK4 - 1; i >= 0; i--) { |
761 | if (nxpdgains >= AR9285_NUM_PD_GAINS2) |
762 | break; |
763 | if (eep->modalHeader.xpdGain & (1 << i)) |
764 | xpdgains[nxpdgains++] = i; |
765 | } |
766 | reg = AR_READ(sc, AR_PHY_TPCRG1)(sc)->ops.read((sc), (0xa258)); |
767 | reg = RW(reg, AR_PHY_TPCRG1_NUM_PD_GAIN, nxpdgains - 1)(((reg) & ~0x0000c000) | (((uint32_t)(nxpdgains - 1) << 14) & 0x0000c000)); |
768 | reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_1, xpdgains[0])(((reg) & ~0x00030000) | (((uint32_t)(xpdgains[0]) << 16) & 0x00030000)); |
769 | reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_2, xpdgains[1])(((reg) & ~0x000c0000) | (((uint32_t)(xpdgains[1]) << 18) & 0x000c0000)); |
770 | AR_WRITE(sc, AR_PHY_TPCRG1, reg)(sc)->ops.write((sc), (0xa258), (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)(((uint32_t)(overlap) << 0) & 0x0000000f); |
777 | reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1, boundaries[0])(((uint32_t)(boundaries[0]) << 4) & 0x000003f0); |
778 | reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2, boundaries[1])(((uint32_t)(boundaries[1]) << 10) & 0x0000fc00); |
779 | reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3, boundaries[2])(((uint32_t)(boundaries[2]) << 16) & 0x003f0000); |
780 | reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4, boundaries[3])(((uint32_t)(boundaries[3]) << 22) & 0x0fc00000); |
781 | AR_WRITE(sc, AR_PHY_TPCRG5, reg)(sc)->ops.write((sc), (0xa26c), (reg)); |
782 | |
783 | /* Write PDADC values. */ |
784 | for (i = 0; i < AR_NUM_PDADC_VALUES128; i += 4) { |
785 | AR_WRITE(sc, AR_PHY_PDADC_TBL_BASE + i,(sc)->ops.write((sc), (0xa280 + i), (pdadcs[i + 0] << 0 | pdadcs[i + 1] << 8 | pdadcs[i + 2] << 16 | pdadcs [i + 3] << 24)) |
786 | pdadcs[i + 0] << 0 |(sc)->ops.write((sc), (0xa280 + i), (pdadcs[i + 0] << 0 | pdadcs[i + 1] << 8 | pdadcs[i + 2] << 16 | pdadcs [i + 3] << 24)) |
787 | pdadcs[i + 1] << 8 |(sc)->ops.write((sc), (0xa280 + i), (pdadcs[i + 0] << 0 | pdadcs[i + 1] << 8 | pdadcs[i + 2] << 16 | pdadcs [i + 3] << 24)) |
788 | pdadcs[i + 2] << 16 |(sc)->ops.write((sc), (0xa280 + i), (pdadcs[i + 0] << 0 | pdadcs[i + 1] << 8 | pdadcs[i + 2] << 16 | pdadcs [i + 3] << 24)) |
789 | pdadcs[i + 3] << 24)(sc)->ops.write((sc), (0xa280 + i), (pdadcs[i + 0] << 0 | pdadcs[i + 1] << 8 | pdadcs[i + 2] << 16 | pdadcs [i + 3] << 24)); |
790 | } |
791 | AR_WRITE_BARRIER(sc)(sc)->ops.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 | uint8_t tpow_cck_ext[4], tpow_ofdm_ext[4]; |
802 | uint8_t tpow_ht20[8], tpow_ht40[8]; |
803 | uint8_t ht40inc; |
804 | int16_t max_ant_gain, power[ATHN_POWER_COUNT68]; |
805 | int i; |
806 | |
807 | ar9285_set_power_calib(sc, c); |
808 | |
809 | /* Compute transmit power reduction due to antenna gain. */ |
810 | max_ant_gain = modal->antennaGain; |
Value stored to 'max_ant_gain' is never read | |
811 | /* XXX */ |
812 | |
813 | /* Get CCK target powers. */ |
814 | ar5008_get_lg_tpow(sc, c, AR_CTL_11B1, eep->calTargetPowerCck, |
815 | AR9285_NUM_2G_CCK_TARGET_POWERS3, tpow_cck); |
816 | |
817 | /* Get OFDM target powers. */ |
818 | ar5008_get_lg_tpow(sc, c, AR_CTL_11G2, eep->calTargetPower2G, |
819 | AR9285_NUM_2G_20_TARGET_POWERS3, tpow_ofdm); |
820 | |
821 | /* Get HT-20 target powers. */ |
822 | ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT205, eep->calTargetPower2GHT20, |
823 | AR9285_NUM_2G_20_TARGET_POWERS3, tpow_ht20); |
824 | |
825 | if (extc != NULL((void *)0)) { |
826 | /* Get HT-40 target powers. */ |
827 | ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT407, |
828 | eep->calTargetPower2GHT40, AR9285_NUM_2G_40_TARGET_POWERS3, |
829 | tpow_ht40); |
830 | |
831 | /* Get secondary channel CCK target powers. */ |
832 | ar5008_get_lg_tpow(sc, extc, AR_CTL_11B1, |
833 | eep->calTargetPowerCck, AR9285_NUM_2G_CCK_TARGET_POWERS3, |
834 | tpow_cck_ext); |
835 | |
836 | /* Get secondary channel OFDM target powers. */ |
837 | ar5008_get_lg_tpow(sc, extc, AR_CTL_11G2, |
838 | eep->calTargetPower2G, AR9285_NUM_2G_20_TARGET_POWERS3, |
839 | tpow_ofdm_ext); |
840 | } |
841 | |
842 | memset(power, 0, sizeof(power))__builtin_memset((power), (0), (sizeof(power))); |
843 | /* Shuffle target powers across transmit rates. */ |
844 | power[ATHN_POWER_OFDM60 ] = |
845 | power[ATHN_POWER_OFDM91 ] = |
846 | power[ATHN_POWER_OFDM122 ] = |
847 | power[ATHN_POWER_OFDM183 ] = |
848 | power[ATHN_POWER_OFDM244 ] = tpow_ofdm[0]; |
849 | power[ATHN_POWER_OFDM365 ] = tpow_ofdm[1]; |
850 | power[ATHN_POWER_OFDM486 ] = tpow_ofdm[2]; |
851 | power[ATHN_POWER_OFDM547 ] = tpow_ofdm[3]; |
852 | power[ATHN_POWER_XR15 ] = tpow_ofdm[0]; |
853 | power[ATHN_POWER_CCK1_LP8 ] = tpow_cck[0]; |
854 | power[ATHN_POWER_CCK2_LP9 ] = |
855 | power[ATHN_POWER_CCK2_SP10 ] = tpow_cck[1]; |
856 | power[ATHN_POWER_CCK55_LP11] = |
857 | power[ATHN_POWER_CCK55_SP12] = tpow_cck[2]; |
858 | power[ATHN_POWER_CCK11_LP13] = |
859 | power[ATHN_POWER_CCK11_SP14] = tpow_cck[3]; |
860 | for (i = 0; i < nitems(tpow_ht20)(sizeof((tpow_ht20)) / sizeof((tpow_ht20)[0])); i++) |
861 | power[ATHN_POWER_HT20(i)(16 + (i))] = tpow_ht20[i]; |
862 | if (extc != NULL((void *)0)) { |
863 | /* Correct PAR difference between HT40 and HT20/Legacy. */ |
864 | if (sc->eep_rev >= AR_EEP_MINOR_VER_22) |
865 | ht40inc = modal->ht40PowerIncForPdadc; |
866 | else |
867 | ht40inc = AR_HT40_POWER_INC_FOR_PDADC2; |
868 | for (i = 0; i < nitems(tpow_ht40)(sizeof((tpow_ht40)) / sizeof((tpow_ht40)[0])); i++) |
869 | power[ATHN_POWER_HT40(i)(40 + (i))] = tpow_ht40[i] + ht40inc; |
870 | power[ATHN_POWER_OFDM_DUP65] = tpow_ht40[0]; |
871 | power[ATHN_POWER_CCK_DUP64 ] = tpow_ht40[0]; |
872 | power[ATHN_POWER_OFDM_EXT67] = tpow_ofdm_ext[0]; |
873 | power[ATHN_POWER_CCK_EXT66 ] = tpow_cck_ext[0]; |
874 | } |
875 | |
876 | for (i = 0; i < ATHN_POWER_COUNT68; i++) { |
877 | power[i] -= AR_PWR_TABLE_OFFSET_DB(-5) * 2; /* In half dB. */ |
878 | if (power[i] > AR_MAX_RATE_POWER63) |
879 | power[i] = AR_MAX_RATE_POWER63; |
880 | } |
881 | |
882 | /* Commit transmit power values to hardware. */ |
883 | ar5008_write_txpower(sc, power); |
884 | } |