1221163Sadrian/*
2221163Sadrian * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd
3221163Sadrian * Copyright (c) 2008 Sam Leffler, Errno Consulting
4221163Sadrian * Copyright (c) 2008 Atheros Communications, Inc.
5221163Sadrian *
6221163Sadrian * Permission to use, copy, modify, and/or distribute this software for any
7221163Sadrian * purpose with or without fee is hereby granted, provided that the above
8221163Sadrian * copyright notice and this permission notice appear in all copies.
9221163Sadrian *
10221163Sadrian * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11221163Sadrian * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12221163Sadrian * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13221163Sadrian * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14221163Sadrian * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15221163Sadrian * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16221163Sadrian * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17221163Sadrian *
18221163Sadrian * $FreeBSD: releng/11.0/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c 272292 2014-09-30 03:19:29Z adrian $
19221163Sadrian */
20221163Sadrian#include "opt_ah.h"
21221163Sadrian
22221163Sadrian#include "ah.h"
23221163Sadrian#include "ah_internal.h"
24221163Sadrian#include "ah_devid.h"
25221163Sadrian
26221163Sadrian#include "ar5416/ar5416.h"
27221163Sadrian#include "ar5416/ar5416reg.h"
28221163Sadrian#include "ar5416/ar5416phy.h"
29221163Sadrian
30221163Sadrian#include "ar9001/ar9130reg.h"
31221163Sadrian#include "ar9001/ar9130_phy.h"
32221163Sadrian#include "ar9001/ar9130_eeprom.h"
33221163Sadrian
34221163Sadrian#include "ar9001/ar9130.ini"
35221163Sadrian
36221163Sadrianstatic const HAL_PERCAL_DATA ar9130_iq_cal = {		/* multi sample */
37221163Sadrian	.calName = "IQ", .calType = IQ_MISMATCH_CAL,
38221163Sadrian	.calNumSamples	= MAX_CAL_SAMPLES,
39221163Sadrian	.calCountMax	= PER_MIN_LOG_COUNT,
40221163Sadrian	.calCollect	= ar5416IQCalCollect,
41221163Sadrian	.calPostProc	= ar5416IQCalibration
42221163Sadrian};
43221163Sadrianstatic const HAL_PERCAL_DATA ar9130_adc_gain_cal = {	/* multi sample */
44221163Sadrian	.calName = "ADC Gain", .calType = ADC_GAIN_CAL,
45221163Sadrian	.calNumSamples	= MAX_CAL_SAMPLES,
46221163Sadrian	.calCountMax	= PER_MIN_LOG_COUNT,
47221163Sadrian	.calCollect	= ar5416AdcGainCalCollect,
48221163Sadrian	.calPostProc	= ar5416AdcGainCalibration
49221163Sadrian};
50221163Sadrianstatic const HAL_PERCAL_DATA ar9130_adc_dc_cal = {	/* multi sample */
51221163Sadrian	.calName = "ADC DC", .calType = ADC_DC_CAL,
52221163Sadrian	.calNumSamples	= MAX_CAL_SAMPLES,
53221163Sadrian	.calCountMax	= PER_MIN_LOG_COUNT,
54221163Sadrian	.calCollect	= ar5416AdcDcCalCollect,
55221163Sadrian	.calPostProc	= ar5416AdcDcCalibration
56221163Sadrian};
57221163Sadrianstatic const HAL_PERCAL_DATA ar9130_adc_init_dc_cal = {
58221163Sadrian	.calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL,
59221163Sadrian	.calNumSamples	= MIN_CAL_SAMPLES,
60221163Sadrian	.calCountMax	= INIT_LOG_COUNT,
61221163Sadrian	.calCollect	= ar5416AdcDcCalCollect,
62221163Sadrian	.calPostProc	= ar5416AdcDcCalibration
63221163Sadrian};
64221163Sadrian
65221163Sadrianstatic HAL_BOOL ar9130FillCapabilityInfo(struct ath_hal *ah);
66221163Sadrian
67221163Sadrian/*
68221163Sadrian * Attach for an AR9130 part.
69221163Sadrian */
70221163Sadrianstatic struct ath_hal *
71221163Sadrianar9130Attach(uint16_t devid, HAL_SOFTC sc,
72272292Sadrian	HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,
73272292Sadrian	HAL_OPS_CONFIG *ah_config,
74272292Sadrian	HAL_STATUS *status)
75221163Sadrian{
76221163Sadrian	struct ath_hal_5416 *ahp5416;
77221163Sadrian	struct ath_hal_5212 *ahp;
78221163Sadrian	struct ath_hal *ah;
79221163Sadrian	uint32_t val;
80221163Sadrian	HAL_STATUS ecode;
81221163Sadrian	HAL_BOOL rfStatus;
82221163Sadrian
83225883Sadrian	HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n",
84221163Sadrian	    __func__, sc, (void*) st, (void*) sh);
85221163Sadrian
86221163Sadrian	/* NB: memory is returned zero'd */
87221163Sadrian	ahp5416 = ath_hal_malloc(sizeof (struct ath_hal_5416));
88221163Sadrian	if (ahp5416 == AH_NULL) {
89225883Sadrian		HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
90221163Sadrian		    "%s: cannot allocate memory for state block\n", __func__);
91221163Sadrian		*status = HAL_ENOMEM;
92221163Sadrian		return AH_NULL;
93221163Sadrian	}
94221163Sadrian	ar5416InitState(ahp5416, devid, sc, st, sh, status);
95221163Sadrian	ahp = &ahp5416->ah_5212;
96221163Sadrian	ah = &ahp->ah_priv.h;
97221163Sadrian
98221163Sadrian	/* XXX override with 9100 specific state */
99221163Sadrian	AH5416(ah)->ah_initPLL = ar9130InitPLL;
100221163Sadrian	/* XXX should force chainmasks to 0x7, as per ath9k calibration bugs */
101221163Sadrian
102221163Sadrian	/* override 5416 methods for our needs */
103221163Sadrian
104221163Sadrian	AH5416(ah)->ah_cal.iqCalData.calData = &ar9130_iq_cal;
105221163Sadrian	AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9130_adc_gain_cal;
106221163Sadrian	AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9130_adc_dc_cal;
107221163Sadrian	AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9130_adc_init_dc_cal;
108221163Sadrian	AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
109221163Sadrian
110221163Sadrian	/*
111221163Sadrian	 * This was hard-set because the initial ath9k port of this
112221163Sadrian	 * code kept their runtime conditional register #defines.
113221163Sadrian	 * AR_SREV and the RTC registers have shifted for Howl;
114221163Sadrian	 * they detected this and changed the values at runtime.
115221163Sadrian	 * The current port doesn't yet do this; it may do at a
116221163Sadrian	 * later stage, so this is set early so any routines which
117221163Sadrian	 * manipulate the registers have ah_macVersion set to base
118221163Sadrian	 * the above decision upon.
119221163Sadrian	 */
120221163Sadrian	AH_PRIVATE((ah))->ah_macVersion = AR_XSREV_VERSION_HOWL;
121221163Sadrian
122221163Sadrian	/*
123221163Sadrian	 * Use the "local" EEPROM data given to us by the higher layers.
124230147Sadrian	 * This is a private copy out of system flash.
125230147Sadrian	 * By this stage the SoC SPI flash may have disabled the memory-
126230147Sadrian	 * mapping and rely purely on port-based SPI IO.
127221163Sadrian	 */
128230147Sadrian	AH_PRIVATE((ah))->ah_eepromRead = ath_hal_EepromDataRead;
129221163Sadrian	AH_PRIVATE((ah))->ah_eepromWrite = NULL;
130221163Sadrian	ah->ah_eepromdata = eepromdata;
131221163Sadrian
132221163Sadrian	if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) {
133221163Sadrian		/* reset chip */
134221163Sadrian		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n",
135221163Sadrian		    __func__);
136221163Sadrian		ecode = HAL_EIO;
137221163Sadrian		goto bad;
138221163Sadrian	}
139221163Sadrian
140221163Sadrian	if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
141221163Sadrian		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n",
142221163Sadrian		    __func__);
143221163Sadrian		ecode = HAL_EIO;
144221163Sadrian		goto bad;
145221163Sadrian	}
146221163Sadrian	/* Read Revisions from Chips before taking out of reset */
147221163Sadrian	val = OS_REG_READ(ah, AR_SREV_CHIP_HOWL) & AR_SREV_CHIP_HOWL_ID;
148221163Sadrian
149221163Sadrian	/* XXX are these values even valid for the mac/radio revision? -adrian */
150221163Sadrian	HALDEBUG(ah, HAL_DEBUG_ATTACH,
151221163Sadrian	    "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n",
152221163Sadrian	    __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION),
153221163Sadrian	    MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION));
154221163Sadrian	AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION);
155221163Sadrian	AH_PRIVATE(ah)->ah_ispcie = 0;
156221163Sadrian
157221163Sadrian	/* setup common ini data; rf backends handle remainder */
158221163Sadrian	HAL_INI_INIT(&ahp->ah_ini_modes, ar5416Modes_9100, 6);
159221163Sadrian	HAL_INI_INIT(&ahp->ah_ini_common, ar5416Common_9100, 2);
160221163Sadrian
161221163Sadrian	HAL_INI_INIT(&AH5416(ah)->ah_ini_bb_rfgain, ar5416BB_RfGain_9100, 3);
162221163Sadrian	HAL_INI_INIT(&AH5416(ah)->ah_ini_bank0, ar5416Bank0_9100, 2);
163221163Sadrian	HAL_INI_INIT(&AH5416(ah)->ah_ini_bank1, ar5416Bank1_9100, 2);
164221163Sadrian	HAL_INI_INIT(&AH5416(ah)->ah_ini_bank2, ar5416Bank2_9100, 2);
165221163Sadrian	HAL_INI_INIT(&AH5416(ah)->ah_ini_bank3, ar5416Bank3_9100, 3);
166221163Sadrian	HAL_INI_INIT(&AH5416(ah)->ah_ini_bank6, ar5416Bank6TPC_9100, 3);
167221163Sadrian	HAL_INI_INIT(&AH5416(ah)->ah_ini_bank7, ar5416Bank7_9100, 2);
168221163Sadrian	HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar5416Addac_9100, 2);
169221163Sadrian
170221163Sadrian	ecode = ath_hal_v14EepromAttach(ah);
171221163Sadrian	if (ecode != HAL_OK)
172221163Sadrian		goto bad;
173221163Sadrian
174221163Sadrian	if (!ar5416ChipReset(ah, AH_NULL)) {	/* reset chip */
175221163Sadrian		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
176221163Sadrian		ecode = HAL_EIO;
177221163Sadrian		goto bad;
178221163Sadrian	}
179221163Sadrian
180221163Sadrian	AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID);
181221163Sadrian
182221163Sadrian	if (!ar5212ChipTest(ah)) {
183221163Sadrian		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n",
184221163Sadrian		    __func__);
185221163Sadrian		ecode = HAL_ESELFTEST;
186221163Sadrian		goto bad;
187221163Sadrian	}
188221163Sadrian
189221163Sadrian	/*
190221163Sadrian	 * Set correct Baseband to analog shift
191221163Sadrian	 * setting to access analog chips.
192221163Sadrian	 */
193221163Sadrian	OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
194221163Sadrian
195221163Sadrian	/* Read Radio Chip Rev Extract */
196221163Sadrian	AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah);
197221163Sadrian	switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
198221163Sadrian        case AR_RAD2133_SREV_MAJOR:	/* Sowl: 2G/3x3 */
199221163Sadrian	case AR_RAD5133_SREV_MAJOR:	/* Sowl: 2+5G/3x3 */
200221163Sadrian		break;
201221163Sadrian	default:
202221163Sadrian		if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) {
203221163Sadrian			AH_PRIVATE(ah)->ah_analog5GhzRev =
204221163Sadrian				AR_RAD5133_SREV_MAJOR;
205221163Sadrian			break;
206221163Sadrian		}
207221163Sadrian#ifdef AH_DEBUG
208221163Sadrian		HALDEBUG(ah, HAL_DEBUG_ANY,
209221163Sadrian		    "%s: 5G Radio Chip Rev 0x%02X is not supported by "
210221163Sadrian		    "this driver\n", __func__,
211221163Sadrian		    AH_PRIVATE(ah)->ah_analog5GhzRev);
212221163Sadrian		ecode = HAL_ENOTSUPP;
213221163Sadrian		goto bad;
214221163Sadrian#endif
215221163Sadrian	}
216221163Sadrian	rfStatus = ar2133RfAttach(ah, &ecode);
217221163Sadrian	if (!rfStatus) {
218221163Sadrian		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n",
219221163Sadrian		    __func__, ecode);
220221163Sadrian		goto bad;
221221163Sadrian	}
222221163Sadrian
223221163Sadrian	/*
224221163Sadrian	 * Got everything we need now to setup the capabilities.
225221163Sadrian	 */
226221163Sadrian	if (!ar9130FillCapabilityInfo(ah)) {
227221163Sadrian		ecode = HAL_EEREAD;
228221163Sadrian		goto bad;
229221163Sadrian	}
230221163Sadrian
231221163Sadrian	ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr);
232221163Sadrian	if (ecode != HAL_OK) {
233221163Sadrian		HALDEBUG(ah, HAL_DEBUG_ANY,
234221163Sadrian		    "%s: error getting mac address from EEPROM\n", __func__);
235221163Sadrian		goto bad;
236221163Sadrian        }
237221163Sadrian	/* XXX How about the serial number ? */
238221163Sadrian	/* Read Reg Domain */
239221163Sadrian	AH_PRIVATE(ah)->ah_currentRD =
240221163Sadrian	    ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL);
241221596Sadrian	AH_PRIVATE(ah)->ah_currentRDext =
242221596Sadrian	    ath_hal_eepromGet(ah, AR_EEP_REGDMN_1, AH_NULL);
243221163Sadrian
244221596Sadrian
245221163Sadrian	/*
246221163Sadrian	 * ah_miscMode is populated by ar5416FillCapabilityInfo()
247221163Sadrian	 * starting from griffin. Set here to make sure that
248221163Sadrian	 * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is
249221163Sadrian	 * placed into hardware.
250221163Sadrian	 */
251221163Sadrian	if (ahp->ah_miscMode != 0)
252221163Sadrian		OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
253221163Sadrian
254221163Sadrian	/* XXX no ANI for AR9130 */
255221163Sadrian	AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ;
256221163Sadrian	AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ;
257221163Sadrian	AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_5416_2GHZ;
258221163Sadrian	AH5416(ah)->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ;
259221163Sadrian	AH5416(ah)->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ;
260221163Sadrian	AH5416(ah)->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ;
261221163Sadrian
262221163Sadrian	ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist);
263221163Sadrian
264221163Sadrian	HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);
265221163Sadrian
266221163Sadrian	return ah;
267221163Sadrianbad:
268221163Sadrian	if (ahp)
269221163Sadrian		ar5416Detach((struct ath_hal *) ahp);
270221163Sadrian	if (status)
271221163Sadrian		*status = ecode;
272221163Sadrian	return AH_NULL;
273221163Sadrian}
274221163Sadrian
275221163Sadrian/*
276221163Sadrian * Fill all software cached or static hardware state information.
277221163Sadrian * Return failure if capabilities are to come from EEPROM and
278221163Sadrian * cannot be read.
279221163Sadrian */
280221163Sadrianstatic HAL_BOOL
281221163Sadrianar9130FillCapabilityInfo(struct ath_hal *ah)
282221163Sadrian{
283221163Sadrian	HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
284221163Sadrian
285221163Sadrian	HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: begin\n", __func__);
286221163Sadrian	if (!ar5416FillCapabilityInfo(ah))
287221163Sadrian		return AH_FALSE;
288221163Sadrian	HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: fill'ed; now setting\n", __func__);
289221163Sadrian	pCap->halCSTSupport = AH_TRUE;
290221163Sadrian	pCap->halRifsRxSupport = AH_TRUE;
291221163Sadrian	pCap->halRifsTxSupport = AH_TRUE;
292221163Sadrian	pCap->halRtsAggrLimit = 64*1024;	/* 802.11n max */
293221163Sadrian	pCap->halExtChanDfsSupport = AH_TRUE;
294222584Sadrian	pCap->halUseCombinedRadarRssi = AH_TRUE;
295221163Sadrian	pCap->halAutoSleepSupport = AH_FALSE;	/* XXX? */
296221603Sadrian	/*
297221603Sadrian	 * MBSSID aggregation is broken in Howl v1.1, v1.2, v1.3
298221603Sadrian	 * and works fine in v1.4.
299221603Sadrian	 * XXX todo, enable it for v1.4.
300221603Sadrian	 */
301221603Sadrian	pCap->halMbssidAggrSupport = AH_FALSE;
302221603Sadrian	pCap->hal4AddrAggrSupport = AH_TRUE;
303226488Sadrian	/* BB Read WAR */
304226488Sadrian	pCap->halHasBBReadWar = AH_TRUE;
305221603Sadrian
306242412Sadrian	/*
307242412Sadrian	 * Implement the PLL/config changes needed for half/quarter
308242412Sadrian	 * rates before re-enabling them here.
309242412Sadrian	 */
310242412Sadrian	pCap->halChanHalfRate = AH_FALSE;
311242412Sadrian	pCap->halChanQuarterRate = AH_FALSE;
312242412Sadrian
313221163Sadrian	return AH_TRUE;
314221163Sadrian}
315221163Sadrian
316221163Sadrianstatic const char*
317221163Sadrianar9130Probe(uint16_t vendorid, uint16_t devid)
318221163Sadrian{
319221163Sadrian        if (vendorid == ATHEROS_VENDOR_ID && devid == AR5416_AR9130_DEVID)
320221163Sadrian                return "Atheros 9130";
321221163Sadrian	return AH_NULL;
322221163Sadrian}
323221163SadrianAH_CHIP(AR9130, ar9130Probe, ar9130Attach);
324