Update ath_hal from FreeBSD.
[dragonfly.git] / sys / dev / netif / ath / hal / ath_hal / ar5416 / ar9160_attach.c
1 /*
2  * Copyright (c) 2008 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: head/sys/dev/ath/ath_hal/ar5416/ar9160_attach.c 203882 2010-02-14 16:26:32Z rpaulo $
18  * $DragonFly$
19  */
20 #include "opt_ah.h"
21
22 #include "ah.h"
23 #include "ah_internal.h"
24 #include "ah_devid.h"
25
26 #include "ar5416/ar5416.h"
27 #include "ar5416/ar5416reg.h"
28 #include "ar5416/ar5416phy.h"
29
30 #include "ar5416/ar9160.ini"
31
32 static const HAL_PERCAL_DATA ar9160_iq_cal = {          /* multi sample */
33         .calName = "IQ", .calType = IQ_MISMATCH_CAL,
34         .calNumSamples  = MAX_CAL_SAMPLES,
35         .calCountMax    = PER_MIN_LOG_COUNT,
36         .calCollect     = ar5416IQCalCollect,
37         .calPostProc    = ar5416IQCalibration
38 };
39 static const HAL_PERCAL_DATA ar9160_adc_gain_cal = {    /* multi sample */
40         .calName = "ADC Gain", .calType = ADC_GAIN_CAL,
41         .calNumSamples  = MAX_CAL_SAMPLES,
42         .calCountMax    = PER_MIN_LOG_COUNT,
43         .calCollect     = ar5416AdcGainCalCollect,
44         .calPostProc    = ar5416AdcGainCalibration
45 };
46 static const HAL_PERCAL_DATA ar9160_adc_dc_cal = {      /* multi sample */
47         .calName = "ADC DC", .calType = ADC_DC_CAL,
48         .calNumSamples  = MAX_CAL_SAMPLES,
49         .calCountMax    = PER_MIN_LOG_COUNT,
50         .calCollect     = ar5416AdcDcCalCollect,
51         .calPostProc    = ar5416AdcDcCalibration
52 };
53 static const HAL_PERCAL_DATA ar9160_adc_init_dc_cal = {
54         .calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL,
55         .calNumSamples  = MIN_CAL_SAMPLES,
56         .calCountMax    = INIT_LOG_COUNT,
57         .calCollect     = ar5416AdcDcCalCollect,
58         .calPostProc    = ar5416AdcDcCalibration
59 };
60
61 static HAL_BOOL ar9160FillCapabilityInfo(struct ath_hal *ah);
62
63 static void
64 ar9160AniSetup(struct ath_hal *ah)
65 {
66         static const struct ar5212AniParams aniparams = {
67                 .maxNoiseImmunityLevel  = 4,    /* levels 0..4 */
68                 .totalSizeDesired       = { -55, -55, -55, -55, -62 },
69                 .coarseHigh             = { -14, -14, -14, -14, -12 },
70                 .coarseLow              = { -64, -64, -64, -64, -70 },
71                 .firpwr                 = { -78, -78, -78, -78, -80 },
72                 .maxSpurImmunityLevel   = 2,
73                 .cycPwrThr1             = { 2, 4, 6 },
74                 .maxFirstepLevel        = 2,    /* levels 0..2 */
75                 .firstep                = { 0, 4, 8 },
76                 .ofdmTrigHigh           = 500,
77                 .ofdmTrigLow            = 200,
78                 .cckTrigHigh            = 200,
79                 .cckTrigLow             = 100,
80                 .rssiThrHigh            = 40,
81                 .rssiThrLow             = 7,
82                 .period                 = 100,
83         };
84         /* NB: ANI is not enabled yet */
85         ar5212AniAttach(ah, &aniparams, &aniparams, AH_FALSE);
86 }
87
88 /*
89  * Attach for an AR9160 part.
90  */
91 static struct ath_hal *
92 ar9160Attach(uint16_t devid, HAL_SOFTC sc,
93         HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status)
94 {
95         struct ath_hal_5416 *ahp5416;
96         struct ath_hal_5212 *ahp;
97         struct ath_hal *ah;
98         uint32_t val;
99         HAL_STATUS ecode;
100         HAL_BOOL rfStatus;
101
102         HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n",
103             __func__, sc, (void*) st, (void*) sh);
104
105         /* NB: memory is returned zero'd */
106         ahp5416 = ath_hal_malloc(sizeof (struct ath_hal_5416));
107         if (ahp5416 == AH_NULL) {
108                 HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
109                     "%s: cannot allocate memory for state block\n", __func__);
110                 *status = HAL_ENOMEM;
111                 return AH_NULL;
112         }
113         ar5416InitState(ahp5416, devid, sc, st, sh, status);
114         ahp = &ahp5416->ah_5212;
115         ah = &ahp->ah_priv.h;
116
117         /* XXX override with 9160 specific state */
118         /* override 5416 methods for our needs */
119
120         AH5416(ah)->ah_cal.iqCalData.calData = &ar9160_iq_cal;
121         AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9160_adc_gain_cal;
122         AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9160_adc_dc_cal;
123         AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9160_adc_init_dc_cal;
124         AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
125
126         if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) {
127                 /* reset chip */
128                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n",
129                     __func__);
130                 ecode = HAL_EIO;
131                 goto bad;
132         }
133
134         if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
135                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n",
136                     __func__);
137                 ecode = HAL_EIO;
138                 goto bad;
139         }
140         /* Read Revisions from Chips before taking out of reset */
141         val = OS_REG_READ(ah, AR_SREV);
142         HALDEBUG(ah, HAL_DEBUG_ATTACH,
143             "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n",
144             __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION),
145             MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION));
146         /* NB: include chip type to differentiate from pre-Sowl versions */
147         AH_PRIVATE(ah)->ah_macVersion =
148             (val & AR_XSREV_VERSION) >> AR_XSREV_TYPE_S;
149         AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION);
150         AH_PRIVATE(ah)->ah_ispcie = (val & AR_XSREV_TYPE_HOST_MODE) == 0;
151
152         /* setup common ini data; rf backends handle remainder */
153         HAL_INI_INIT(&ahp->ah_ini_modes, ar9160Modes, 6);
154         HAL_INI_INIT(&ahp->ah_ini_common, ar9160Common, 2);
155
156         HAL_INI_INIT(&AH5416(ah)->ah_ini_bb_rfgain, ar9160BB_RfGain, 3);
157         HAL_INI_INIT(&AH5416(ah)->ah_ini_bank0, ar9160Bank0, 2);
158         HAL_INI_INIT(&AH5416(ah)->ah_ini_bank1, ar9160Bank1, 2);
159         HAL_INI_INIT(&AH5416(ah)->ah_ini_bank2, ar9160Bank2, 2);
160         HAL_INI_INIT(&AH5416(ah)->ah_ini_bank3, ar9160Bank3, 3);
161         HAL_INI_INIT(&AH5416(ah)->ah_ini_bank6, ar9160Bank6, 3);
162         HAL_INI_INIT(&AH5416(ah)->ah_ini_bank7, ar9160Bank7, 2);
163         if (AR_SREV_SOWL_11(ah))
164                 HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar9160Addac_1_1, 2);
165         else
166                 HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar9160Addac, 2);
167
168         ecode = ath_hal_v14EepromAttach(ah);
169         if (ecode != HAL_OK)
170                 goto bad;
171
172         HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, ar9160PciePhy, 2);
173         ar5416AttachPCIE(ah);
174
175         if (!ar5416ChipReset(ah, AH_NULL)) {    /* reset chip */
176                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
177                 ecode = HAL_EIO;
178                 goto bad;
179         }
180
181         AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID);
182
183         if (!ar5212ChipTest(ah)) {
184                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n",
185                     __func__);
186                 ecode = HAL_ESELFTEST;
187                 goto bad;
188         }
189
190         /*
191          * Set correct Baseband to analog shift
192          * setting to access analog chips.
193          */
194         OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
195
196         /* Read Radio Chip Rev Extract */
197         AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah);
198         switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
199         case AR_RAD2133_SREV_MAJOR:     /* Sowl: 2G/3x3 */
200         case AR_RAD5133_SREV_MAJOR:     /* Sowl: 2+5G/3x3 */
201                 break;
202         default:
203                 if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) {
204                         AH_PRIVATE(ah)->ah_analog5GhzRev =
205                                 AR_RAD5133_SREV_MAJOR;
206                         break;
207                 }
208 #ifdef AH_DEBUG
209                 HALDEBUG(ah, HAL_DEBUG_ANY,
210                     "%s: 5G Radio Chip Rev 0x%02X is not supported by "
211                     "this driver\n", __func__,
212                     AH_PRIVATE(ah)->ah_analog5GhzRev);
213                 ecode = HAL_ENOTSUPP;
214                 goto bad;
215 #endif
216         }
217         rfStatus = ar2133RfAttach(ah, &ecode);
218         if (!rfStatus) {
219                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n",
220                     __func__, ecode);
221                 goto bad;
222         }
223
224         /*
225          * Got everything we need now to setup the capabilities.
226          */
227         if (!ar9160FillCapabilityInfo(ah)) {
228                 ecode = HAL_EEREAD;
229                 goto bad;
230         }
231
232         ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr);
233         if (ecode != HAL_OK) {
234                 HALDEBUG(ah, HAL_DEBUG_ANY,
235                     "%s: error getting mac address from EEPROM\n", __func__);
236                 goto bad;
237         }
238         /* XXX How about the serial number ? */
239         /* Read Reg Domain */
240         AH_PRIVATE(ah)->ah_currentRD =
241             ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL);
242
243         /*
244          * ah_miscMode is populated by ar5416FillCapabilityInfo()
245          * starting from griffin. Set here to make sure that
246          * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is
247          * placed into hardware.
248          */
249         if (ahp->ah_miscMode != 0)
250                 OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
251
252         ar9160AniSetup(ah);                     /* Anti Noise Immunity */
253         ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist);
254
255         HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);
256
257         return ah;
258 bad:
259         if (ahp)
260                 ar5416Detach((struct ath_hal *) ahp);
261         if (status)
262                 *status = ecode;
263         return AH_NULL;
264 }
265
266 /*
267  * Fill all software cached or static hardware state information.
268  * Return failure if capabilities are to come from EEPROM and
269  * cannot be read.
270  */
271 static HAL_BOOL
272 ar9160FillCapabilityInfo(struct ath_hal *ah)
273 {
274         HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
275
276         if (!ar5416FillCapabilityInfo(ah))
277                 return AH_FALSE;
278         pCap->halCSTSupport = AH_TRUE;
279         pCap->halRifsRxSupport = AH_TRUE;
280         pCap->halRifsTxSupport = AH_TRUE;
281         pCap->halRtsAggrLimit = 64*1024;        /* 802.11n max */
282         pCap->halExtChanDfsSupport = AH_TRUE;
283         pCap->halAutoSleepSupport = AH_FALSE;   /* XXX? */
284         return AH_TRUE;
285 }
286
287 static const char*
288 ar9160Probe(uint16_t vendorid, uint16_t devid)
289 {
290         if (vendorid == ATHEROS_VENDOR_ID && devid == AR9160_DEVID_PCI)
291                 return "Atheros 9160";
292         return AH_NULL;
293 }
294 AH_CHIP(AR9160, ar9160Probe, ar9160Attach);