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 NBPFILTER > 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
65int	ar9285_attach(struct athn_softc *);
66void	ar9285_setup(struct athn_softc *);
67void	ar9285_swap_rom(struct athn_softc *);
68const	struct ar_spur_chan *ar9285_get_spur_chans(struct athn_softc *, int);
69void	ar9285_init_from_rom(struct athn_softc *, struct ieee80211_channel *,
70	    struct ieee80211_channel *);
71void	ar9285_pa_calib(struct athn_softc *);
72void	ar9271_pa_calib(struct athn_softc *);
73int	ar9285_cl_cal(struct athn_softc *, struct ieee80211_channel *,
74	    struct ieee80211_channel *);
75void	ar9271_load_ani(struct athn_softc *);
76int	ar9285_init_calib(struct athn_softc *, struct ieee80211_channel *,
77	    struct ieee80211_channel *);
78void	ar9285_get_pdadcs(struct athn_softc *, struct ieee80211_channel *,
79	    int, uint8_t, uint8_t *, uint8_t *);
80void	ar9285_set_power_calib(struct athn_softc *,
81	    struct ieee80211_channel *);
82void	ar9285_set_txpower(struct athn_softc *, struct ieee80211_channel *,
83	    struct ieee80211_channel *);
84
85/* Extern functions. */
86uint8_t	athn_chan2fbin(struct ieee80211_channel *);
87void	athn_get_pier_ival(uint8_t, const uint8_t *, int, int *, int *);
88int	ar5008_attach(struct athn_softc *);
89void	ar5008_write_txpower(struct athn_softc *, int16_t power[]);
90void	ar5008_get_pdadcs(struct athn_softc *, uint8_t, struct athn_pier *,
91	    struct athn_pier *, int, int, uint8_t, uint8_t *, uint8_t *);
92void	ar5008_get_lg_tpow(struct athn_softc *, struct ieee80211_channel *,
93	    uint8_t, const struct ar_cal_target_power_leg *, int, uint8_t[]);
94void	ar5008_get_ht_tpow(struct athn_softc *, struct ieee80211_channel *,
95	    uint8_t, const struct ar_cal_target_power_ht *, int, uint8_t[]);
96int	ar9280_set_synth(struct athn_softc *, struct ieee80211_channel *,
97	    struct ieee80211_channel *);
98void	ar9280_spur_mitigate(struct athn_softc *, struct ieee80211_channel *,
99	    struct ieee80211_channel *);
100
101
102int
103ar9285_attach(struct athn_softc *sc)
104{
105	sc->eep_base = AR9285_EEP_START_LOC;
106	sc->eep_size = sizeof(struct ar9285_eeprom);
107	sc->ngpiopins = (sc->flags & ATHN_FLAG_USB) ? 16 : 12;
108	sc->led_pin = (sc->flags & ATHN_FLAG_USB) ? 15 : 1;
109	sc->workaround = AR9285_WA_DEFAULT;
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_USB > 0
118	if (AR_SREV_9271(sc)) {
119		sc->cca_min_2g = AR9271_PHY_CCA_MIN_GOOD_VAL_2GHZ;
120		sc->cca_max_2g = AR9271_PHY_CCA_MAX_GOOD_VAL_2GHZ;
121	} else
122#endif
123	{
124		sc->cca_min_2g = AR9285_PHY_CCA_MIN_GOOD_VAL_2GHZ;
125		sc->cca_max_2g = AR9285_PHY_CCA_MAX_GOOD_VAL_2GHZ;
126	}
127#if NATHN_USB > 0
128	if (AR_SREV_9271(sc))
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
138void
139ar9285_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_USB > 0
148	if (AR_SREV_9271(sc)) {
149		if (type == AR_EEP_TXGAIN_HIGH_POWER)
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) & 0x7) == 0x1) {	/* XE rev. */
156		if (type == AR_EEP_TXGAIN_HIGH_POWER)
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_POWER)
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
168void
169ar9285_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);
176	eep->modalHeader.antCtrlChain =
177	    swap32(eep->modalHeader.antCtrlChain);
178
179	for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
180		eep->modalHeader.spurChans[i].spurChan =
181		    swap16(eep->modalHeader.spurChans[i].spurChan);
182	}
183}
184
185const struct ar_spur_chan *
186ar9285_get_spur_chans(struct athn_softc *sc, int is2ghz)
187{
188	const struct ar9285_eeprom *eep = sc->eep;
189
190	KASSERT(is2ghz);
191	return (eep->modalHeader.spurChans);
192}
193
194void
195ar9285_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);
205	AR_WRITE(sc, AR_PHY_SWITCH_CHAIN_0, modal->antCtrlChain);
206
207	reg = AR_READ(sc, AR_PHY_TIMING_CTRL4_0);
208	reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, modal->iqCalI);
209	reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, modal->iqCalQ);
210	AR_WRITE(sc, AR_PHY_TIMING_CTRL4_0, reg);
211
212	if (sc->eep_rev >= AR_EEP_MINOR_VER_3) {
213		reg = AR_READ(sc, AR_PHY_GAIN_2GHZ);
214		reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
215		    modal->bswMargin);
216		reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_DB,
217		    modal->bswAtten);
218		reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
219		    modal->xatten2Margin);
220		reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_DB,
221		    modal->xatten2Db);
222		AR_WRITE(sc, AR_PHY_GAIN_2GHZ, reg);
223
224		/* Duplicate values of chain 0 for chain 1. */
225		reg = AR_READ(sc, AR_PHY_GAIN_2GHZ + offset);
226		reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
227		    modal->bswMargin);
228		reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_DB,
229		    modal->bswAtten);
230		reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
231		    modal->xatten2Margin);
232		reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_DB,
233		    modal->xatten2Db);
234		AR_WRITE(sc, AR_PHY_GAIN_2GHZ + offset, reg);
235	}
236	if (sc->eep_rev >= AR_EEP_MINOR_VER_3)
237		txRxAtten = modal->txRxAtten;
238	else	/* Workaround for ROM versions < 14.3. */
239		txRxAtten = 23;
240	reg = AR_READ(sc, AR_PHY_RXGAIN);
241	reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAtten);
242	reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_MARGIN, modal->rxTxMargin);
243	AR_WRITE(sc, AR_PHY_RXGAIN, reg);
244
245	/* Duplicate values of chain 0 for chain 1. */
246	reg = AR_READ(sc, AR_PHY_RXGAIN + offset);
247	reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAtten);
248	reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_MARGIN, modal->rxTxMargin);
249	AR_WRITE(sc, AR_PHY_RXGAIN + offset, reg);
250
251	if (modal->version >= 3) {
252		/* Setup antenna diversity from ROM. */
253		reg = AR_READ(sc, AR_PHY_MULTICHAIN_GAIN_CTL);
254		reg = RW(reg, AR9285_PHY_ANT_DIV_CTL_ALL, 0);
255		reg = RW(reg, AR9285_PHY_ANT_DIV_CTL,
256		    (modal->ob_234  >> 12) & 0x1);
257		reg = RW(reg, AR9285_PHY_ANT_DIV_ALT_LNACONF,
258		    (modal->db1_234 >> 12) & 0x3);
259		reg = RW(reg, AR9285_PHY_ANT_DIV_MAIN_LNACONF,
260		    (modal->db1_234 >> 14) & 0x3);
261		reg = RW(reg, AR9285_PHY_ANT_DIV_ALT_GAINTB,
262		    (modal->ob_234  >> 13) & 0x1);
263		reg = RW(reg, AR9285_PHY_ANT_DIV_MAIN_GAINTB,
264		    (modal->ob_234  >> 14) & 0x1);
265		AR_WRITE(sc, AR_PHY_MULTICHAIN_GAIN_CTL, reg);
266		reg = AR_READ(sc, AR_PHY_MULTICHAIN_GAIN_CTL);	/* Flush. */
267
268		reg = AR_READ(sc, AR_PHY_CCK_DETECT);
269		if (modal->ob_234 & (1 << 15))
270			reg |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
271		else
272			reg &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
273		AR_WRITE(sc, AR_PHY_CCK_DETECT, reg);
274		reg = AR_READ(sc, AR_PHY_CCK_DETECT);		/* 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_USB > 0
323	if (AR_SREV_9271(sc)) {
324		reg = AR_READ(sc, AR9285_AN_RF2G3);
325		reg = RW(reg, AR9271_AN_RF2G3_OB_CCK, ob [0]);
326		reg = RW(reg, AR9271_AN_RF2G3_OB_PSK, ob [1]);
327		reg = RW(reg, AR9271_AN_RF2G3_OB_QAM, ob [2]);
328		reg = RW(reg, AR9271_AN_RF2G3_DB1,    db1[0]);
329		AR_WRITE(sc, AR9285_AN_RF2G3, reg);
330		AR_WRITE_BARRIER(sc);
331		DELAY(100);
332		reg = AR_READ(sc, AR9285_AN_RF2G4);
333		reg = RW(reg, AR9271_AN_RF2G4_DB2,    db2[0]);
334		AR_WRITE(sc, AR9285_AN_RF2G4, reg);
335		AR_WRITE_BARRIER(sc);
336		DELAY(100);
337	} else
338#endif	/* ATHN_USB */
339	{
340		reg = AR_READ(sc, AR9285_AN_RF2G3);
341		reg = RW(reg, AR9285_AN_RF2G3_OB_0,  ob [0]);
342		reg = RW(reg, AR9285_AN_RF2G3_OB_1,  ob [1]);
343		reg = RW(reg, AR9285_AN_RF2G3_OB_2,  ob [2]);
344		reg = RW(reg, AR9285_AN_RF2G3_OB_3,  ob [3]);
345		reg = RW(reg, AR9285_AN_RF2G3_OB_4,  ob [4]);
346		reg = RW(reg, AR9285_AN_RF2G3_DB1_0, db1[0]);
347		reg = RW(reg, AR9285_AN_RF2G3_DB1_1, db1[1]);
348		reg = RW(reg, AR9285_AN_RF2G3_DB1_2, db1[2]);
349		AR_WRITE(sc, AR9285_AN_RF2G3, reg);
350		AR_WRITE_BARRIER(sc);
351		DELAY(100);
352		reg = AR_READ(sc, AR9285_AN_RF2G4);
353		reg = RW(reg, AR9285_AN_RF2G4_DB1_3, db1[3]);
354		reg = RW(reg, AR9285_AN_RF2G4_DB1_4, db1[4]);
355		reg = RW(reg, AR9285_AN_RF2G4_DB2_0, db2[0]);
356		reg = RW(reg, AR9285_AN_RF2G4_DB2_1, db2[1]);
357		reg = RW(reg, AR9285_AN_RF2G4_DB2_2, db2[2]);
358		reg = RW(reg, AR9285_AN_RF2G4_DB2_3, db2[3]);
359		reg = RW(reg, AR9285_AN_RF2G4_DB2_4, db2[4]);
360		AR_WRITE(sc, AR9285_AN_RF2G4, reg);
361		AR_WRITE_BARRIER(sc);
362		DELAY(100);
363	}
364
365	reg = AR_READ(sc, AR_PHY_SETTLING);
366	reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->switchSettling);
367	AR_WRITE(sc, AR_PHY_SETTLING, reg);
368
369	reg = AR_READ(sc, AR_PHY_DESIRED_SZ);
370	reg = RW(reg, AR_PHY_DESIRED_SZ_ADC, modal->adcDesiredSize);
371	AR_WRITE(sc, AR_PHY_DESIRED_SZ, reg);
372
373	reg =  SM(AR_PHY_RF_CTL4_TX_END_XPAA_OFF, modal->txEndToXpaOff);
374	reg |= SM(AR_PHY_RF_CTL4_TX_END_XPAB_OFF, modal->txEndToXpaOff);
375	reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAA_ON, modal->txFrameToXpaOn);
376	reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAB_ON, modal->txFrameToXpaOn);
377	AR_WRITE(sc, AR_PHY_RF_CTL4, reg);
378
379	reg = AR_READ(sc, AR_PHY_RF_CTL3);
380	reg = RW(reg, AR_PHY_TX_END_TO_A2_RX_ON, modal->txEndToRxOn);
381	AR_WRITE(sc, AR_PHY_RF_CTL3, reg);
382
383	reg = AR_READ(sc, AR_PHY_CCA(0));
384	reg = RW(reg, AR9280_PHY_CCA_THRESH62, modal->thresh62);
385	AR_WRITE(sc, AR_PHY_CCA(0), reg);
386
387	reg = AR_READ(sc, AR_PHY_EXT_CCA0);
388	reg = RW(reg, AR_PHY_EXT_CCA0_THRESH62, modal->thresh62);
389	AR_WRITE(sc, AR_PHY_EXT_CCA0, reg);
390
391	if (sc->eep_rev >= AR_EEP_MINOR_VER_2) {
392		reg = AR_READ(sc, AR_PHY_RF_CTL2);
393		reg = RW(reg, AR_PHY_TX_END_PA_ON,
394		    modal->txFrameToPaOn);
395		reg = RW(reg, AR_PHY_TX_END_DATA_START,
396		    modal->txFrameToDataStart);
397		AR_WRITE(sc, AR_PHY_RF_CTL2, reg);
398	}
399	if (sc->eep_rev >= AR_EEP_MINOR_VER_3 && extc != NULL) {
400		reg = AR_READ(sc, AR_PHY_SETTLING);
401		reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->swSettleHt40);
402		AR_WRITE(sc, AR_PHY_SETTLING, reg);
403	}
404	AR_WRITE_BARRIER(sc);
405}
406
407void
408ar9285_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_TOP3,
413		AR9285_AN_RXTXBB1,
414		AR9285_AN_RF2G1,
415		AR9285_AN_RF2G2,
416		AR9285_AN_TOP2,
417		AR9285_AN_RF2G8,
418		AR9285_AN_RF2G7
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) &&
425	    ((struct ar9285_base_eep_header *)sc->eep)->txGainType ==
426	     AR_EEP_TXGAIN_HIGH_POWER)	/* XXX AR9287? */
427		return;
428
429	/* Save registers. */
430	for (i = 0; i < nitems(regs); i++)
431		svg[i] = AR_READ(sc, regs[i]);
432
433	AR_CLRBITS(sc, AR9285_AN_RF2G6, 1);
434	AR_SETBITS(sc, AR_PHY(2), 1 << 27);
435
436	AR_SETBITS(sc, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC);
437	AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1);
438	AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I);
439	AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF);
440	AR_CLRBITS(sc, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL);
441	AR_CLRBITS(sc, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB);
442	AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL);
443	/* Power down PA drivers. */
444	AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1);
445	AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2);
446	AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT);
447
448	reg = AR_READ(sc, AR9285_AN_RF2G8);
449	reg = RW(reg, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
450	AR_WRITE(sc, AR9285_AN_RF2G8, reg);
451
452	reg = AR_READ(sc, AR9285_AN_RF2G7);
453	reg = RW(reg, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
454	AR_WRITE(sc, AR9285_AN_RF2G7, reg);
455
456	reg = AR_READ(sc, AR9285_AN_RF2G6);
457	/* Save compensation capacitor value. */
458	ccomp_svg = MS(reg, AR9285_AN_RF2G6_CCOMP);
459	/* Program compensation capacitor for dynamic PA. */
460	reg = RW(reg, AR9285_AN_RF2G6_CCOMP, 0xf);
461	AR_WRITE(sc, AR9285_AN_RF2G6, reg);
462
463	AR_WRITE(sc, AR9285_AN_TOP2, AR9285_AN_TOP2_DEFAULT);
464	AR_WRITE_BARRIER(sc);
465	DELAY(30);
466
467	/* Clear offsets 6-1. */
468	AR_CLRBITS(sc, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS_6_1);
469	/* Clear offset 0. */
470	AR_CLRBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP);
471	/* Set offsets 6-1. */
472	for (i = 6; i >= 1; i--) {
473		AR_SETBITS(sc, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS(i));
474		AR_WRITE_BARRIER(sc);
475		DELAY(1);
476		if (AR_READ(sc, AR9285_AN_RF2G9) & AR9285_AN_RXTXBB1_SPARE9) {
477			AR_SETBITS(sc, AR9285_AN_RF2G6,
478			    AR9285_AN_RF2G6_OFFS(i));
479		} else {
480			AR_CLRBITS(sc, AR9285_AN_RF2G6,
481			    AR9285_AN_RF2G6_OFFS(i));
482		}
483	}
484	/* Set offset 0. */
485	AR_SETBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP);
486	AR_WRITE_BARRIER(sc);
487	DELAY(1);
488	if (AR_READ(sc, AR9285_AN_RF2G9) & AR9285_AN_RXTXBB1_SPARE9)
489		AR_SETBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP);
490	else
491		AR_CLRBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP);
492
493	AR_WRITE_BARRIER(sc);
494
495	AR_SETBITS(sc, AR9285_AN_RF2G6, 1);
496	AR_CLRBITS(sc, AR_PHY(2), 1 << 27);
497
498	/* Restore registers. */
499	for (i = 0; i < nitems(regs); i++)
500		AR_WRITE(sc, regs[i], svg[i]);
501
502	/* Restore compensation capacitor value. */
503	reg = AR_READ(sc, AR9285_AN_RF2G6);
504	reg = RW(reg, AR9285_AN_RF2G6_CCOMP, ccomp_svg);
505	AR_WRITE(sc, AR9285_AN_RF2G6, reg);
506	AR_WRITE_BARRIER(sc);
507}
508
509void
510ar9271_pa_calib(struct athn_softc *sc)
511{
512#if NATHN_USB > 0
513	/* List of registers that need to be saved/restored. */
514	static const uint16_t regs[] = {
515		AR9285_AN_TOP3,
516		AR9285_AN_RXTXBB1,
517		AR9285_AN_RF2G1,
518		AR9285_AN_RF2G2,
519		AR9285_AN_TOP2,
520		AR9285_AN_RF2G8,
521		AR9285_AN_RF2G7
522	};
523	uint32_t svg[7], reg, rf2g3_svg;
524	int i;
525
526	/* Save registers. */
527	for (i = 0; i < nitems(regs); i++)
528		svg[i] = AR_READ(sc, regs[i]);
529
530	AR_CLRBITS(sc, AR9285_AN_RF2G6, 1);
531	AR_SETBITS(sc, AR_PHY(2), 1 << 27);
532
533	AR_SETBITS(sc, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC);
534	AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1);
535	AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I);
536	AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF);
537	AR_CLRBITS(sc, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL);
538	AR_CLRBITS(sc, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB);
539	AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL);
540	/* Power down PA drivers. */
541	AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1);
542	AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2);
543	AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT);
544
545	reg = AR_READ(sc, AR9285_AN_RF2G8);
546	reg = RW(reg, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
547	AR_WRITE(sc, AR9285_AN_RF2G8, reg);
548
549	reg = AR_READ(sc, AR9285_AN_RF2G7);
550	reg = RW(reg, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
551	AR_WRITE(sc, AR9285_AN_RF2G7, reg);
552
553	/* Save compensation capacitor value. */
554	reg = rf2g3_svg = AR_READ(sc, AR9285_AN_RF2G3);
555	/* Program compensation capacitor for dynamic PA. */
556	reg = RW(reg, AR9271_AN_RF2G3_CCOMP, 0xfff);
557	AR_WRITE(sc, AR9285_AN_RF2G3, reg);
558
559	AR_WRITE(sc, AR9285_AN_TOP2, AR9285_AN_TOP2_DEFAULT);
560	AR_WRITE_BARRIER(sc);
561	DELAY(30);
562
563	/* Clear offsets 6-0. */
564	AR_CLRBITS(sc, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS_6_0);
565	/* Set offsets 6-1. */
566	for (i = 6; i >= 1; i--) {
567		reg = AR_READ(sc, AR9285_AN_RF2G6);
568		reg |= AR9271_AN_RF2G6_OFFS(i);
569		AR_WRITE(sc, AR9285_AN_RF2G6, reg);
570		AR_WRITE_BARRIER(sc);
571		DELAY(1);
572		if (!(AR_READ(sc, AR9285_AN_RF2G9) & AR9285_AN_RXTXBB1_SPARE9))
573			reg &= ~AR9271_AN_RF2G6_OFFS(i);
574		AR_WRITE(sc, AR9285_AN_RF2G6, reg);
575	}
576	AR_WRITE_BARRIER(sc);
577
578	AR_SETBITS(sc, AR9285_AN_RF2G6, 1);
579	AR_CLRBITS(sc, AR_PHY(2), 1 << 27);
580
581	/* Restore registers. */
582	for (i = 0; i < nitems(regs); i++)
583		AR_WRITE(sc, regs[i], svg[i]);
584
585	/* Restore compensation capacitor value. */
586	AR_WRITE(sc, AR9285_AN_RF2G3, rf2g3_svg);
587	AR_WRITE_BARRIER(sc);
588#endif	/* NATHN_USB */
589}
590
591/*
592 * Carrier Leakage Calibration.
593 */
594int
595ar9285_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);
601	if (0 && extc == NULL) {	/* XXX IS_CHAN_HT20!! */
602		AR_SETBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
603		AR_SETBITS(sc, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
604		AR_CLRBITS(sc, AR_PHY_AGC_CONTROL,
605		    AR_PHY_AGC_CONTROL_FLTR_CAL);
606		AR_CLRBITS(sc, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
607		AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
608		for (ntries = 0; ntries < 10000; ntries++) {
609			if (!(AR_READ(sc, AR_PHY_AGC_CONTROL) &
610			    AR_PHY_AGC_CONTROL_CAL))
611				break;
612			DELAY(10);
613		}
614		if (ntries == 10000)
615			return (ETIMEDOUT);
616		AR_CLRBITS(sc, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
617		AR_CLRBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
618		AR_CLRBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
619	}
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
639void
640ar9271_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
656int
657ar9285_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
710void
711ar9285_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
741void
742ar9285_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
794void
795ar9285_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_COUNT];
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;
811	/* XXX */
812
813	/* Get CCK target powers. */
814	ar5008_get_lg_tpow(sc, c, AR_CTL_11B, eep->calTargetPowerCck,
815	    AR9285_NUM_2G_CCK_TARGET_POWERS, tpow_cck);
816
817	/* Get OFDM target powers. */
818	ar5008_get_lg_tpow(sc, c, AR_CTL_11G, eep->calTargetPower2G,
819	    AR9285_NUM_2G_20_TARGET_POWERS, tpow_ofdm);
820
821	/* Get HT-20 target powers. */
822	ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT20, eep->calTargetPower2GHT20,
823	    AR9285_NUM_2G_20_TARGET_POWERS, tpow_ht20);
824
825	if (extc != NULL) {
826		/* Get HT-40 target powers. */
827		ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT40,
828		    eep->calTargetPower2GHT40, AR9285_NUM_2G_40_TARGET_POWERS,
829		    tpow_ht40);
830
831		/* Get secondary channel CCK target powers. */
832		ar5008_get_lg_tpow(sc, extc, AR_CTL_11B,
833		    eep->calTargetPowerCck, AR9285_NUM_2G_CCK_TARGET_POWERS,
834		    tpow_cck_ext);
835
836		/* Get secondary channel OFDM target powers. */
837		ar5008_get_lg_tpow(sc, extc, AR_CTL_11G,
838		    eep->calTargetPower2G, AR9285_NUM_2G_20_TARGET_POWERS,
839		    tpow_ofdm_ext);
840	}
841
842	memset(power, 0, sizeof(power));
843	/* Shuffle target powers across transmit rates. */
844	power[ATHN_POWER_OFDM6   ] =
845	power[ATHN_POWER_OFDM9   ] =
846	power[ATHN_POWER_OFDM12  ] =
847	power[ATHN_POWER_OFDM18  ] =
848	power[ATHN_POWER_OFDM24  ] = tpow_ofdm[0];
849	power[ATHN_POWER_OFDM36  ] = tpow_ofdm[1];
850	power[ATHN_POWER_OFDM48  ] = tpow_ofdm[2];
851	power[ATHN_POWER_OFDM54  ] = tpow_ofdm[3];
852	power[ATHN_POWER_XR      ] = tpow_ofdm[0];
853	power[ATHN_POWER_CCK1_LP ] = tpow_cck[0];
854	power[ATHN_POWER_CCK2_LP ] =
855	power[ATHN_POWER_CCK2_SP ] = tpow_cck[1];
856	power[ATHN_POWER_CCK55_LP] =
857	power[ATHN_POWER_CCK55_SP] = tpow_cck[2];
858	power[ATHN_POWER_CCK11_LP] =
859	power[ATHN_POWER_CCK11_SP] = tpow_cck[3];
860	for (i = 0; i < nitems(tpow_ht20); i++)
861		power[ATHN_POWER_HT20(i)] = tpow_ht20[i];
862	if (extc != NULL) {
863		/* Correct PAR difference between HT40 and HT20/Legacy. */
864		if (sc->eep_rev >= AR_EEP_MINOR_VER_2)
865			ht40inc = modal->ht40PowerIncForPdadc;
866		else
867			ht40inc = AR_HT40_POWER_INC_FOR_PDADC;
868		for (i = 0; i < nitems(tpow_ht40); i++)
869			power[ATHN_POWER_HT40(i)] = tpow_ht40[i] + ht40inc;
870		power[ATHN_POWER_OFDM_DUP] = tpow_ht40[0];
871		power[ATHN_POWER_CCK_DUP ] = tpow_ht40[0];
872		power[ATHN_POWER_OFDM_EXT] = tpow_ofdm_ext[0];
873		power[ATHN_POWER_CCK_EXT ] = tpow_cck_ext[0];
874	}
875
876	for (i = 0; i < ATHN_POWER_COUNT; i++) {
877		power[i] -= AR_PWR_TABLE_OFFSET_DB * 2;	/* In half dB. */
878		if (power[i] > AR_MAX_RATE_POWER)
879			power[i] = AR_MAX_RATE_POWER;
880	}
881
882	/* Commit transmit power values to hardware. */
883	ar5008_write_txpower(sc, power);
884}
885