1/*
2 * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting
3 * Copyright (c) 2008 Atheros Communications, Inc.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 *
17 * $FreeBSD: src/sys/dev/ath/ath_hal/ar5416/ar9285_attach.c,v 1.5 2010/06/01 15:33:10 rpaulo Exp $
18 */
19#include "opt_ah.h"
20
21#include "ah.h"
22#include "ah_internal.h"
23#include "ah_devid.h"
24
25#include "ah_eeprom_v4k.h"		/* XXX for tx/rx gain */
26
27#include "ar5416/ar9280.h"
28#include "ar5416/ar9285.h"
29#include "ar5416/ar5416reg.h"
30#include "ar5416/ar5416phy.h"
31
32#include "ar5416/ar9285.ini"
33#include "ar5416/ar9285v2.ini"
34#include "ar5416/ar9280v2.ini"		/* XXX ini for tx/rx gain */
35
36static const HAL_PERCAL_DATA ar9280_iq_cal = {		/* single sample */
37	.calName = "IQ", .calType = IQ_MISMATCH_CAL,
38	.calNumSamples	= MIN_CAL_SAMPLES,
39	.calCountMax	= PER_MAX_LOG_COUNT,
40	.calCollect	= ar5416IQCalCollect,
41	.calPostProc	= ar5416IQCalibration
42};
43static const HAL_PERCAL_DATA ar9280_adc_gain_cal = {	/* single sample */
44	.calName = "ADC Gain", .calType = ADC_GAIN_CAL,
45	.calNumSamples	= MIN_CAL_SAMPLES,
46	.calCountMax	= PER_MIN_LOG_COUNT,
47	.calCollect	= ar5416AdcGainCalCollect,
48	.calPostProc	= ar5416AdcGainCalibration
49};
50static const HAL_PERCAL_DATA ar9280_adc_dc_cal = {	/* single sample */
51	.calName = "ADC DC", .calType = ADC_DC_CAL,
52	.calNumSamples	= MIN_CAL_SAMPLES,
53	.calCountMax	= PER_MIN_LOG_COUNT,
54	.calCollect	= ar5416AdcDcCalCollect,
55	.calPostProc	= ar5416AdcDcCalibration
56};
57static const HAL_PERCAL_DATA ar9280_adc_init_dc_cal = {
58	.calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL,
59	.calNumSamples	= MIN_CAL_SAMPLES,
60	.calCountMax	= INIT_LOG_COUNT,
61	.calCollect	= ar5416AdcDcCalCollect,
62	.calPostProc	= ar5416AdcDcCalibration
63};
64
65static void ar9285ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore);
66static HAL_BOOL ar9285FillCapabilityInfo(struct ath_hal *ah);
67static void ar9285WriteIni(struct ath_hal *ah,
68	HAL_CHANNEL_INTERNAL *chan);
69
70static void
71ar9285AniSetup(struct ath_hal *ah)
72{
73	/* NB: disable ANI for reliable RIFS rx */
74	ar5212AniAttach(ah, AH_NULL, AH_NULL, AH_FALSE);
75}
76
77/*
78 * Attach for an AR9285 part.
79 */
80static struct ath_hal *
81ar9285Attach(uint16_t devid, HAL_SOFTC sc,
82	HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status)
83{
84	struct ath_hal_9285 *ahp9285;
85	struct ath_hal_5212 *ahp;
86	struct ath_hal *ah;
87	uint32_t val;
88	HAL_STATUS ecode;
89	HAL_BOOL rfStatus;
90
91	HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n",
92	    __func__, sc, (void*) st, (void*) sh);
93
94	/* NB: memory is returned zero'd */
95	ahp9285 = ath_hal_malloc(sizeof (struct ath_hal_9285));
96	if (ahp9285 == AH_NULL) {
97		HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
98		    "%s: cannot allocate memory for state block\n", __func__);
99		*status = HAL_ENOMEM;
100		return AH_NULL;
101	}
102	ahp = AH5212(ahp9285);
103	ah = &ahp->ah_priv.h;
104
105	ar5416InitState(AH5416(ah), devid, sc, st, sh, status);
106
107	/* XXX override with 9285 specific state */
108	/* override 5416 methods for our needs */
109	ah->ah_setAntennaSwitch		= ar9285SetAntennaSwitch;
110	ah->ah_configPCIE		= ar9285ConfigPCIE;
111	ah->ah_setTxPower		= ar9285SetTransmitPower;
112	ah->ah_setBoardValues		= ar9285SetBoardValues;
113
114	AH5416(ah)->ah_cal.iqCalData.calData = &ar9280_iq_cal;
115	AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9280_adc_gain_cal;
116	AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9280_adc_dc_cal;
117	AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9280_adc_init_dc_cal;
118	AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
119
120	AH5416(ah)->ah_spurMitigate	= ar9280SpurMitigate;
121	AH5416(ah)->ah_writeIni		= ar9285WriteIni;
122	AH5416(ah)->ah_rx_chainmask	= AR9285_DEFAULT_RXCHAINMASK;
123	AH5416(ah)->ah_tx_chainmask	= AR9285_DEFAULT_TXCHAINMASK;
124
125	ahp->ah_maxTxTrigLev		= MAX_TX_FIFO_THRESHOLD >> 1;
126
127	if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) {
128		/* reset chip */
129		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n",
130		    __func__);
131		ecode = HAL_EIO;
132		goto bad;
133	}
134
135	if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
136		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n",
137		    __func__);
138		ecode = HAL_EIO;
139		goto bad;
140	}
141	/* Read Revisions from Chips before taking out of reset */
142	val = OS_REG_READ(ah, AR_SREV);
143	HALDEBUG(ah, HAL_DEBUG_ATTACH,
144	    "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n",
145	    __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION),
146	    MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION));
147	/* NB: include chip type to differentiate from pre-Sowl versions */
148	AH_PRIVATE(ah)->ah_macVersion =
149	    (val & AR_XSREV_VERSION) >> AR_XSREV_TYPE_S;
150	AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION);
151	AH_PRIVATE(ah)->ah_ispcie = (val & AR_XSREV_TYPE_HOST_MODE) == 0;
152
153	/* setup common ini data; rf backends handle remainder */
154	if (AR_SREV_KITE_12_OR_LATER(ah)) {
155		HAL_INI_INIT(&ahp->ah_ini_modes, ar9285Modes_v2, 6);
156		HAL_INI_INIT(&ahp->ah_ini_common, ar9285Common_v2, 2);
157		HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes,
158		    ar9285PciePhy_clkreq_always_on_L1_v2, 2);
159	} else {
160		HAL_INI_INIT(&ahp->ah_ini_modes, ar9285Modes, 6);
161		HAL_INI_INIT(&ahp->ah_ini_common, ar9285Common, 2);
162		HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes,
163		    ar9285PciePhy_clkreq_always_on_L1, 2);
164	}
165	ar5416AttachPCIE(ah);
166
167	ecode = ath_hal_v4kEepromAttach(ah);
168	if (ecode != HAL_OK)
169		goto bad;
170
171	if (!ar5416ChipReset(ah, AH_NULL)) {	/* reset chip */
172		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n",
173		    __func__);
174		ecode = HAL_EIO;
175		goto bad;
176	}
177
178	AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID);
179
180	if (!ar5212ChipTest(ah)) {
181		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n",
182		    __func__);
183		ecode = HAL_ESELFTEST;
184		goto bad;
185	}
186
187	/*
188	 * Set correct Baseband to analog shift
189	 * setting to access analog chips.
190	 */
191	OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
192
193	/* Read Radio Chip Rev Extract */
194	AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah);
195	switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
196        case AR_RAD2133_SREV_MAJOR:	/* Sowl: 2G/3x3 */
197	case AR_RAD5133_SREV_MAJOR:	/* Sowl: 2+5G/3x3 */
198		break;
199	default:
200		if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) {
201			AH_PRIVATE(ah)->ah_analog5GhzRev =
202				AR_RAD5133_SREV_MAJOR;
203			break;
204		}
205#ifdef AH_DEBUG
206		HALDEBUG(ah, HAL_DEBUG_ANY,
207		    "%s: 5G Radio Chip Rev 0x%02X is not supported by "
208		    "this driver\n", __func__,
209		    AH_PRIVATE(ah)->ah_analog5GhzRev);
210		ecode = HAL_ENOTSUPP;
211		goto bad;
212#endif
213	}
214	rfStatus = ar9285RfAttach(ah, &ecode);
215	if (!rfStatus) {
216		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n",
217		    __func__, ecode);
218		goto bad;
219	}
220
221	HAL_INI_INIT(&ahp9285->ah_ini_rxgain, ar9280Modes_original_rxgain_v2,
222	    6);
223	/* setup txgain table */
224	switch (ath_hal_eepromGet(ah, AR_EEP_TXGAIN_TYPE, AH_NULL)) {
225	case AR5416_EEP_TXGAIN_HIGH_POWER:
226		HAL_INI_INIT(&ahp9285->ah_ini_txgain,
227		    ar9285Modes_high_power_tx_gain_v2, 6);
228		break;
229	case AR5416_EEP_TXGAIN_ORIG:
230		HAL_INI_INIT(&ahp9285->ah_ini_txgain,
231		    ar9285Modes_original_tx_gain_v2, 6);
232		break;
233	default:
234		HALASSERT(AH_FALSE);
235		goto bad;		/* XXX ? try to continue */
236	}
237
238	/*
239	 * Got everything we need now to setup the capabilities.
240	 */
241	if (!ar9285FillCapabilityInfo(ah)) {
242		ecode = HAL_EEREAD;
243		goto bad;
244	}
245
246	ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr);
247	if (ecode != HAL_OK) {
248		HALDEBUG(ah, HAL_DEBUG_ANY,
249		    "%s: error getting mac address from EEPROM\n", __func__);
250		goto bad;
251        }
252	/* XXX How about the serial number ? */
253	/* Read Reg Domain */
254	AH_PRIVATE(ah)->ah_currentRD =
255	    ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL);
256
257	/*
258	 * ah_miscMode is populated by ar5416FillCapabilityInfo()
259	 * starting from griffin. Set here to make sure that
260	 * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is
261	 * placed into hardware.
262	 */
263	if (ahp->ah_miscMode != 0)
264		OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
265
266	ar9285AniSetup(ah);			/* Anti Noise Immunity */
267	ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist);
268
269	HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);
270
271	return ah;
272bad:
273	if (ah != AH_NULL)
274		ah->ah_detach(ah);
275	if (status)
276		*status = ecode;
277	return AH_NULL;
278}
279
280static void
281ar9285ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore)
282{
283	if (AH_PRIVATE(ah)->ah_ispcie && !restore) {
284		ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_pcieserdes, 1, 0);
285		OS_DELAY(1000);
286		OS_REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
287		OS_REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT);
288	}
289}
290
291static void
292ar9285WriteIni(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
293{
294	u_int modesIndex;
295	int regWrites = 0;
296
297	/* Setup the indices for the next set of register array writes */
298	/* XXX Ignore 11n dynamic mode on the AR5416 for the moment */
299	if (IS_CHAN_HT40(chan))
300		modesIndex = 3;
301	else if (IS_CHAN_108G(chan))
302		modesIndex = 5;
303	else
304		modesIndex = 4;
305
306	/* Set correct Baseband to analog shift setting to access analog chips. */
307	OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
308	OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
309	regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes,
310	    modesIndex, regWrites);
311	if (AR_SREV_KITE_12_OR_LATER(ah)) {
312		regWrites = ath_hal_ini_write(ah, &AH9285(ah)->ah_ini_txgain,
313		    modesIndex, regWrites);
314	}
315	regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common,
316	    1, regWrites);
317
318      	OS_REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
319
320	if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
321		uint32_t val;
322		val = OS_REG_READ(ah, AR_PCU_MISC_MODE2) &
323			(~AR_PCU_MISC_MODE2_HWWAR1);
324		OS_REG_WRITE(ah, AR_PCU_MISC_MODE2, val);
325		OS_REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);
326	}
327
328}
329
330/*
331 * Fill all software cached or static hardware state information.
332 * Return failure if capabilities are to come from EEPROM and
333 * cannot be read.
334 */
335static HAL_BOOL
336ar9285FillCapabilityInfo(struct ath_hal *ah)
337{
338	HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
339
340	if (!ar5416FillCapabilityInfo(ah))
341		return AH_FALSE;
342	pCap->halNumGpioPins = 12;
343	pCap->halWowSupport = AH_TRUE;
344	pCap->halWowMatchPatternExact = AH_TRUE;
345#if 0
346	pCap->halWowMatchPatternDword = AH_TRUE;
347#endif
348	pCap->halCSTSupport = AH_TRUE;
349	pCap->halRifsRxSupport = AH_TRUE;
350	pCap->halRifsTxSupport = AH_TRUE;
351	pCap->halRtsAggrLimit = 64*1024;	/* 802.11n max */
352	pCap->halExtChanDfsSupport = AH_TRUE;
353#if 0
354	/* XXX bluetooth */
355	pCap->halBtCoexSupport = AH_TRUE;
356#endif
357	pCap->halAutoSleepSupport = AH_FALSE;	/* XXX? */
358#if 0
359	pCap->hal4kbSplitTransSupport = AH_FALSE;
360#endif
361	pCap->halRxStbcSupport = 1;
362	pCap->halTxStbcSupport = 1;
363
364	return AH_TRUE;
365}
366
367HAL_BOOL
368ar9285SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
369{
370#define ANTENNA0_CHAINMASK    0x1
371#define ANTENNA1_CHAINMASK    0x2
372	struct ath_hal_5416 *ahp = AH5416(ah);
373
374	/* Antenna selection is done by setting the tx/rx chainmasks approp. */
375	switch (settings) {
376	case HAL_ANT_FIXED_A:
377		/* Enable first antenna only */
378		ahp->ah_tx_chainmask = ANTENNA0_CHAINMASK;
379		ahp->ah_rx_chainmask = ANTENNA0_CHAINMASK;
380		break;
381	case HAL_ANT_FIXED_B:
382		/* Enable second antenna only, after checking capability */
383		if (AH_PRIVATE(ah)->ah_caps.halTxChainMask > ANTENNA1_CHAINMASK)
384			ahp->ah_tx_chainmask = ANTENNA1_CHAINMASK;
385		ahp->ah_rx_chainmask = ANTENNA1_CHAINMASK;
386		break;
387	case HAL_ANT_VARIABLE:
388		/* Restore original chainmask settings */
389		/* XXX */
390		ahp->ah_tx_chainmask = AR9285_DEFAULT_TXCHAINMASK;
391		ahp->ah_rx_chainmask = AR9285_DEFAULT_RXCHAINMASK;
392		break;
393	}
394	return AH_TRUE;
395#undef ANTENNA0_CHAINMASK
396#undef ANTENNA1_CHAINMASK
397}
398
399static const char*
400ar9285Probe(uint16_t vendorid, uint16_t devid)
401{
402	if (vendorid == ATHEROS_VENDOR_ID && devid == AR9285_DEVID_PCIE)
403		return "Atheros 9285";
404	return AH_NULL;
405}
406AH_CHIP(AR9285, ar9285Probe, ar9285Attach);
407