1 /*
2  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
3  * Copyright (c) 2002-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  * $Id: ar5212_attach.c,v 1.5 2021/04/13 03:27:13 mrg 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 "ar5212/ar5212.h"
26 #include "ar5212/ar5212reg.h"
27 #include "ar5212/ar5212phy.h"
28 
29 #define AH_5212_COMMON
30 #include "ar5212/ar5212.ini"
31 
32 static void ar5212ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore);
33 static void ar5212DisablePCIE(struct ath_hal *ah);
34 
35 static const struct ath_hal_private ar5212hal = {{
36           .ah_magic                     = AR5212_MAGIC,
37           .ah_abi                                 = HAL_ABI_VERSION,
38           .ah_countryCode                         = CTRY_DEFAULT,
39 
40           .ah_getRateTable              = ar5212GetRateTable,
41           .ah_detach                              = ar5212Detach,
42 
43           /* Reset Functions */
44           .ah_reset                     = ar5212Reset,
45           .ah_phyDisable                          = ar5212PhyDisable,
46           .ah_disable                             = ar5212Disable,
47           .ah_configPCIE                          = ar5212ConfigPCIE,
48           .ah_disablePCIE                         = ar5212DisablePCIE,
49           .ah_setPCUConfig              = ar5212SetPCUConfig,
50           .ah_perCalibration            = ar5212PerCalibration,
51           .ah_perCalibrationN           = ar5212PerCalibrationN,
52           .ah_resetCalValid             = ar5212ResetCalValid,
53           .ah_setTxPowerLimit           = ar5212SetTxPowerLimit,
54           .ah_getChanNoise              = ath_hal_getChanNoise,
55 
56           /* Transmit functions */
57           .ah_updateTxTrigLevel                   = ar5212UpdateTxTrigLevel,
58           .ah_setupTxQueue              = ar5212SetupTxQueue,
59           .ah_setTxQueueProps             = ar5212SetTxQueueProps,
60           .ah_getTxQueueProps             = ar5212GetTxQueueProps,
61           .ah_releaseTxQueue            = ar5212ReleaseTxQueue,
62           .ah_resetTxQueue              = ar5212ResetTxQueue,
63           .ah_getTxDP                             = ar5212GetTxDP,
64           .ah_setTxDP                             = ar5212SetTxDP,
65           .ah_numTxPending              = ar5212NumTxPending,
66           .ah_startTxDma                          = ar5212StartTxDma,
67           .ah_stopTxDma                           = ar5212StopTxDma,
68           .ah_setupTxDesc                         = ar5212SetupTxDesc,
69           .ah_setupXTxDesc              = ar5212SetupXTxDesc,
70           .ah_fillTxDesc                          = ar5212FillTxDesc,
71           .ah_procTxDesc                          = ar5212ProcTxDesc,
72           .ah_getTxIntrQueue            = ar5212GetTxIntrQueue,
73           .ah_reqTxIntrDesc             = ar5212IntrReqTxDesc,
74 
75           /* RX Functions */
76           .ah_getRxDP                             = ar5212GetRxDP,
77           .ah_setRxDP                             = ar5212SetRxDP,
78           .ah_enableReceive             = ar5212EnableReceive,
79           .ah_stopDmaReceive            = ar5212StopDmaReceive,
80           .ah_startPcuReceive           = ar5212StartPcuReceive,
81           .ah_stopPcuReceive            = ar5212StopPcuReceive,
82           .ah_setMulticastFilter                  = ar5212SetMulticastFilter,
83           .ah_setMulticastFilterIndex   = ar5212SetMulticastFilterIndex,
84           .ah_clrMulticastFilterIndex   = ar5212ClrMulticastFilterIndex,
85           .ah_getRxFilter                         = ar5212GetRxFilter,
86           .ah_setRxFilter                         = ar5212SetRxFilter,
87           .ah_setupRxDesc                         = ar5212SetupRxDesc,
88           .ah_procRxDesc                          = ar5212ProcRxDesc,
89           .ah_rxMonitor                           = ar5212AniPoll,
90           .ah_procMibEvent              = ar5212ProcessMibIntr,
91 
92           /* Misc Functions */
93           .ah_getCapability             = ar5212GetCapability,
94           .ah_setCapability             = ar5212SetCapability,
95           .ah_getDiagState              = ar5212GetDiagState,
96           .ah_getMacAddress             = ar5212GetMacAddress,
97           .ah_setMacAddress             = ar5212SetMacAddress,
98           .ah_getBssIdMask              = ar5212GetBssIdMask,
99           .ah_setBssIdMask              = ar5212SetBssIdMask,
100           .ah_setRegulatoryDomain                 = ar5212SetRegulatoryDomain,
101           .ah_setLedState                         = ar5212SetLedState,
102           .ah_writeAssocid              = ar5212WriteAssocid,
103           .ah_gpioCfgInput              = ar5212GpioCfgInput,
104           .ah_gpioCfgOutput             = ar5212GpioCfgOutput,
105           .ah_gpioGet                             = ar5212GpioGet,
106           .ah_gpioSet                             = ar5212GpioSet,
107           .ah_gpioSetIntr                         = ar5212GpioSetIntr,
108           .ah_getTsf32                            = ar5212GetTsf32,
109           .ah_getTsf64                            = ar5212GetTsf64,
110           .ah_resetTsf                            = ar5212ResetTsf,
111           .ah_detectCardPresent                   = ar5212DetectCardPresent,
112           .ah_updateMibCounters                   = ar5212UpdateMibCounters,
113           .ah_getRfGain                           = ar5212GetRfgain,
114           .ah_getDefAntenna             = ar5212GetDefAntenna,
115           .ah_setDefAntenna             = ar5212SetDefAntenna,
116           .ah_getAntennaSwitch                    = ar5212GetAntennaSwitch,
117           .ah_setAntennaSwitch                    = ar5212SetAntennaSwitch,
118           .ah_setSifsTime                         = ar5212SetSifsTime,
119           .ah_getSifsTime                         = ar5212GetSifsTime,
120           .ah_setSlotTime                         = ar5212SetSlotTime,
121           .ah_getSlotTime                         = ar5212GetSlotTime,
122           .ah_setAckTimeout             = ar5212SetAckTimeout,
123           .ah_getAckTimeout             = ar5212GetAckTimeout,
124           .ah_setAckCTSRate             = ar5212SetAckCTSRate,
125           .ah_getAckCTSRate             = ar5212GetAckCTSRate,
126           .ah_setCTSTimeout             = ar5212SetCTSTimeout,
127           .ah_getCTSTimeout             = ar5212GetCTSTimeout,
128           .ah_setDecompMask               = ar5212SetDecompMask,
129           .ah_setCoverageClass            = ar5212SetCoverageClass,
130 
131           /* Key Cache Functions */
132           .ah_getKeyCacheSize           = ar5212GetKeyCacheSize,
133           .ah_resetKeyCacheEntry                  = ar5212ResetKeyCacheEntry,
134           .ah_isKeyCacheEntryValid      = ar5212IsKeyCacheEntryValid,
135           .ah_setKeyCacheEntry                    = ar5212SetKeyCacheEntry,
136           .ah_setKeyCacheEntryMac                 = ar5212SetKeyCacheEntryMac,
137 
138           /* Power Management Functions */
139           .ah_setPowerMode              = ar5212SetPowerMode,
140           .ah_getPowerMode              = ar5212GetPowerMode,
141 
142           /* Beacon Functions */
143           .ah_setBeaconTimers           = ar5212SetBeaconTimers,
144           .ah_beaconInit                          = ar5212BeaconInit,
145           .ah_setStationBeaconTimers    = ar5212SetStaBeaconTimers,
146           .ah_resetStationBeaconTimers  = ar5212ResetStaBeaconTimers,
147 
148           /* Interrupt Functions */
149           .ah_isInterruptPending                  = ar5212IsInterruptPending,
150           .ah_getPendingInterrupts      = ar5212GetPendingInterrupts,
151           .ah_getInterrupts             = ar5212GetInterrupts,
152           .ah_setInterrupts             = ar5212SetInterrupts },
153 
154           .ah_getChannelEdges           = ar5212GetChannelEdges,
155           .ah_getWirelessModes                    = ar5212GetWirelessModes,
156           .ah_eepromRead                          = ar5212EepromRead,
157 #ifdef AH_SUPPORT_WRITE_EEPROM
158           .ah_eepromWrite                         = ar5212EepromWrite,
159 #endif
160           .ah_gpioCfgOutput             = ar5212GpioCfgOutput,
161           .ah_gpioCfgInput              = ar5212GpioCfgInput,
162           .ah_gpioGet                             = ar5212GpioGet,
163           .ah_gpioSet                             = ar5212GpioSet,
164           .ah_gpioSetIntr                         = ar5212GpioSetIntr,
165           .ah_getChipPowerLimits                  = ar5212GetChipPowerLimits,
166 };
167 
168 uint32_t
ar5212GetRadioRev(struct ath_hal * ah)169 ar5212GetRadioRev(struct ath_hal *ah)
170 {
171           uint32_t val;
172           int i;
173 
174           /* Read Radio Chip Rev Extract */
175           OS_REG_WRITE(ah, AR_PHY(0x34), 0x00001c16);
176           for (i = 0; i < 8; i++)
177                     OS_REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
178           val = (OS_REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
179           val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
180           return ath_hal_reverseBits(val, 8);
181 }
182 
183 static void
ar5212AniSetup(struct ath_hal * ah)184 ar5212AniSetup(struct ath_hal *ah)
185 {
186           static const struct ar5212AniParams aniparams = {
187                     .maxNoiseImmunityLevel        = 4,      /* levels 0..4 */
188                     .totalSizeDesired   = { -55, -55, -55, -55, -62 },
189                     .coarseHigh                   = { -14, -14, -14, -14, -12 },
190                     .coarseLow                    = { -64, -64, -64, -64, -70 },
191                     .firpwr                       = { -78, -78, -78, -78, -80 },
192                     .maxSpurImmunityLevel         = 2,      /* NB: depends on chip rev */
193                     .cycPwrThr1                   = { 2, 4, 6, 8, 10, 12, 14, 16 },
194                     .maxFirstepLevel    = 2,      /* levels 0..2 */
195                     .firstep            = { 0, 4, 8 },
196                     .ofdmTrigHigh                 = 500,
197                     .ofdmTrigLow                  = 200,
198                     .cckTrigHigh                  = 200,
199                     .cckTrigLow                   = 100,
200                     .rssiThrHigh                  = 40,
201                     .rssiThrLow                   = 7,
202                     .period                       = 100,
203           };
204           if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_GRIFFIN) {
205                     struct ar5212AniParams tmp;
206                     OS_MEMCPY(&tmp, &aniparams, sizeof(struct ar5212AniParams));
207                     tmp.maxSpurImmunityLevel = 7; /* Venice and earlier */
208                     ar5212AniAttach(ah, &tmp, &tmp, AH_TRUE);
209           } else
210                     ar5212AniAttach(ah, &aniparams, &aniparams, AH_TRUE);
211 }
212 
213 /*
214  * Attach for an AR5212 part.
215  */
216 void
ar5212InitState(struct ath_hal_5212 * ahp,uint16_t devid,HAL_SOFTC sc,HAL_BUS_TAG st,HAL_BUS_HANDLE sh,HAL_STATUS * status)217 ar5212InitState(struct ath_hal_5212 *ahp, uint16_t devid, HAL_SOFTC sc,
218           HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status)
219 {
220 #define   N(a)      (sizeof(a)/sizeof(a[0]))
221           static const uint8_t defbssidmask[IEEE80211_ADDR_LEN] =
222                     { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
223           struct ath_hal *ah;
224 
225           ah = &ahp->ah_priv.h;
226           /* set initial values */
227           OS_MEMCPY(&ahp->ah_priv, &ar5212hal, sizeof(struct ath_hal_private));
228           ah->ah_sc = sc;
229           ah->ah_st = st;
230           ah->ah_sh = sh;
231 
232           ah->ah_devid = devid;                             /* NB: for alq */
233           AH_PRIVATE(ah)->ah_devid = devid;
234           AH_PRIVATE(ah)->ah_subvendorid = 0;     /* XXX */
235 
236           AH_PRIVATE(ah)->ah_powerLimit = MAX_RATE_POWER;
237           AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX;    /* no scaling */
238 
239           ahp->ah_antControl = HAL_ANT_VARIABLE;
240           ahp->ah_diversity = AH_TRUE;
241           ahp->ah_bIQCalibration = IQ_CAL_INACTIVE;
242           /*
243            * Enable MIC handling.
244            */
245           ahp->ah_staId1Defaults = AR_STA_ID1_CRPT_MIC_ENABLE;
246           ahp->ah_rssiThr = INIT_RSSI_THR;
247           ahp->ah_tpcEnabled = AH_FALSE;                    /* disabled by default */
248           ahp->ah_phyPowerOn = AH_FALSE;
249           ahp->ah_macTPC = SM(MAX_RATE_POWER, AR_TPC_ACK)
250                            | SM(MAX_RATE_POWER, AR_TPC_CTS)
251                            | SM(MAX_RATE_POWER, AR_TPC_CHIRP);
252           ahp->ah_beaconInterval = 100;           /* XXX [20..1000] */
253           ahp->ah_enable32kHzClock = DONT_USE_32KHZ;/* XXX */
254           ahp->ah_slottime = (u_int) -1;
255           ahp->ah_acktimeout = (u_int) -1;
256           ahp->ah_ctstimeout = (u_int) -1;
257           ahp->ah_sifstime = (u_int) -1;
258           ahp->ah_txTrigLev = INIT_TX_FIFO_THRESHOLD;
259           ahp->ah_maxTxTrigLev = MAX_TX_FIFO_THRESHOLD;
260 
261           OS_MEMCPY(&ahp->ah_bssidmask, defbssidmask, IEEE80211_ADDR_LEN);
262 #undef N
263 }
264 
265 /*
266  * Validate MAC version and revision.
267  */
268 static HAL_BOOL
ar5212IsMacSupported(uint8_t macVersion,uint8_t macRev)269 ar5212IsMacSupported(uint8_t macVersion, uint8_t macRev)
270 {
271 #define   N(a)      (sizeof(a)/sizeof(a[0]))
272           static const struct {
273                     uint8_t   version;
274                     uint8_t   revMin, revMax;
275           } macs[] = {
276               { AR_SREV_VERSION_VENICE,
277                 AR_SREV_D2PLUS,                   AR_SREV_REVISION_MAX },
278               { AR_SREV_VERSION_GRIFFIN,
279                 AR_SREV_D2PLUS,                   AR_SREV_REVISION_MAX },
280               { AR_SREV_5413,
281                 AR_SREV_REVISION_MIN,   AR_SREV_REVISION_MAX },
282               { AR_SREV_5424,
283                 AR_SREV_REVISION_MIN,   AR_SREV_REVISION_MAX },
284               { AR_SREV_2425,
285                 AR_SREV_REVISION_MIN,   AR_SREV_REVISION_MAX },
286               { AR_SREV_2417,
287                 AR_SREV_REVISION_MIN,   AR_SREV_REVISION_MAX },
288           };
289           int i;
290 
291           for (i = 0; i < N(macs); i++)
292                     if (macs[i].version == macVersion &&
293                         macs[i].revMin <= macRev && macRev <= macs[i].revMax)
294                               return AH_TRUE;
295           return AH_FALSE;
296 #undef N
297 }
298 
299 /*
300  * Attach for an AR5212 part.
301  */
302 static struct ath_hal *
ar5212Attach(uint16_t devid,HAL_SOFTC sc,HAL_BUS_TAG st,HAL_BUS_HANDLE sh,HAL_STATUS * status)303 ar5212Attach(uint16_t devid, HAL_SOFTC sc,
304           HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status)
305 {
306 #define   AH_EEPROM_PROTECT(ah) \
307           (AH_PRIVATE(ah)->ah_ispcie)? AR_EEPROM_PROTECT_PCIE : AR_EEPROM_PROTECT)
308           struct ath_hal_5212 *ahp;
309           struct ath_hal *ah;
310           struct ath_hal_rf *rf;
311           uint32_t val;
312           uint16_t eeval;
313           HAL_STATUS ecode;
314 
315           HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n",
316               __func__, sc, (void*) st, (void*) sh);
317 
318           /* NB: memory is returned zero'd */
319           ahp = ath_hal_malloc(sizeof (struct ath_hal_5212));
320           if (ahp == AH_NULL) {
321                     HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
322                         "%s: cannot allocate memory for state block\n", __func__);
323                     *status = HAL_ENOMEM;
324                     return AH_NULL;
325           }
326           ar5212InitState(ahp, devid, sc, st, sh, status);
327           ah = &ahp->ah_priv.h;
328 
329           if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
330                     HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n",
331                         __func__);
332                     ecode = HAL_EIO;
333                     goto bad;
334           }
335           /* Read Revisions from Chips before taking out of reset */
336           val = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID;
337           AH_PRIVATE(ah)->ah_macVersion = val >> AR_SREV_ID_S;
338           AH_PRIVATE(ah)->ah_macRev = val & AR_SREV_REVISION;
339           AH_PRIVATE(ah)->ah_ispcie = IS_5424(ah) || IS_2425(ah);
340 
341           if (!ar5212IsMacSupported(AH_PRIVATE(ah)->ah_macVersion, AH_PRIVATE(ah)->ah_macRev)) {
342                     HALDEBUG(ah, HAL_DEBUG_ANY,
343                         "%s: Mac Chip Rev 0x%02x.%x not supported\n" ,
344                         __func__, AH_PRIVATE(ah)->ah_macVersion,
345                         AH_PRIVATE(ah)->ah_macRev);
346                     ecode = HAL_ENOTSUPP;
347                     goto bad;
348           }
349 
350           /* setup common ini data; rf backends handle remainder */
351           HAL_INI_INIT(&ahp->ah_ini_modes, ar5212Modes, 6);
352           HAL_INI_INIT(&ahp->ah_ini_common, ar5212Common, 2);
353 
354           if (!ar5212ChipReset(ah, AH_NULL)) {    /* reset chip */
355                     HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
356                     ecode = HAL_EIO;
357                     goto bad;
358           }
359 
360           AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID);
361 
362           if (AH_PRIVATE(ah)->ah_ispcie) {
363                     /* XXX: build flag to disable this? */
364                     ath_hal_configPCIE(ah, AH_FALSE);
365           }
366 
367           if (!ar5212ChipTest(ah)) {
368                     HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n",
369                         __func__);
370                     ecode = HAL_ESELFTEST;
371                     goto bad;
372           }
373 
374           /* Enable PCI core retry fix in software for Hainan and up */
375           if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_VENICE)
376                     OS_REG_SET_BIT(ah, AR_PCICFG, AR_PCICFG_RETRYFIXEN);
377 
378           /*
379            * Set correct Baseband to analog shift
380            * setting to access analog chips.
381            */
382           OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
383 
384           /* Read Radio Chip Rev Extract */
385           AH_PRIVATE(ah)->ah_analog5GhzRev = ar5212GetRadioRev(ah);
386 
387           rf = ath_hal_rfprobe(ah, &ecode);
388           if (rf == AH_NULL)
389                     goto bad;
390 
391           /* NB: silently accept anything in release code per Atheros */
392           switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
393           case AR_RAD5111_SREV_MAJOR:
394           case AR_RAD5112_SREV_MAJOR:
395           case AR_RAD2112_SREV_MAJOR:
396           case AR_RAD2111_SREV_MAJOR:
397           case AR_RAD2413_SREV_MAJOR:
398           case AR_RAD5413_SREV_MAJOR:
399           case AR_RAD5424_SREV_MAJOR:
400                     break;
401           default:
402                     if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) {
403                               /*
404                                * When RF_Silent is used, the
405                                * analog chip is reset.  So when the system boots
406                                * up with the radio switch off we cannot determine
407                                * the RF chip rev.  To workaround this check the
408                                * mac+phy revs and if Hainan, set the radio rev
409                                * to Derby.
410                                */
411                               if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE &&
412                                   AH_PRIVATE(ah)->ah_macRev == AR_SREV_HAINAN &&
413                                   AH_PRIVATE(ah)->ah_phyRev == AR_PHYREV_HAINAN) {
414                                         AH_PRIVATE(ah)->ah_analog5GhzRev = AR_ANALOG5REV_HAINAN;
415                                         break;
416                               }
417                               if (IS_2413(ah)) {            /* Griffin */
418                                         AH_PRIVATE(ah)->ah_analog5GhzRev =
419                                             AR_RAD2413_SREV_MAJOR | 0x1;
420                                         break;
421                               }
422                               if (IS_5413(ah)) {            /* Eagle */
423                                         AH_PRIVATE(ah)->ah_analog5GhzRev =
424                                             AR_RAD5413_SREV_MAJOR | 0x2;
425                                         break;
426                               }
427                               if (IS_2425(ah) || IS_2417(ah)) {/* Swan or Nala */
428                                         AH_PRIVATE(ah)->ah_analog5GhzRev =
429                                             AR_RAD5424_SREV_MAJOR | 0x2;
430                                         break;
431                               }
432                     }
433 #ifdef AH_DEBUG
434                     HALDEBUG(ah, HAL_DEBUG_ANY,
435                         "%s: 5G Radio Chip Rev 0x%02X is not supported by "
436                         "this driver\n",
437                         __func__, AH_PRIVATE(ah)->ah_analog5GhzRev);
438                     ecode = HAL_ENOTSUPP;
439                     goto bad;
440 #endif
441           }
442           if (IS_RAD5112_REV1(ah)) {
443                     HALDEBUG(ah, HAL_DEBUG_ANY,
444                         "%s: 5112 Rev 1 is not supported by this "
445                         "driver (analog5GhzRev 0x%x)\n", __func__,
446                         AH_PRIVATE(ah)->ah_analog5GhzRev);
447                     ecode = HAL_ENOTSUPP;
448                     goto bad;
449           }
450 
451           val = OS_REG_READ(ah, AR_PCICFG);
452           val = MS(val, AR_PCICFG_EEPROM_SIZE);
453           if (val == 0) {
454                     if (!AH_PRIVATE(ah)->ah_ispcie) {
455                               HALDEBUG(ah, HAL_DEBUG_ANY,
456                                   "%s: unsupported EEPROM size %u (0x%x) found\n",
457                                   __func__, val, val);
458                               ecode = HAL_EESIZE;
459                               goto bad;
460                     }
461                     /* XXX AH_PRIVATE(ah)->ah_isPciExpress = AH_TRUE; */
462           } else if (val != AR_PCICFG_EEPROM_SIZE_16K) {
463                     if (AR_PCICFG_EEPROM_SIZE_FAILED == val) {
464                               HALDEBUG(ah, HAL_DEBUG_ANY,
465                                   "%s: unsupported EEPROM size %u (0x%x) found\n",
466                                   __func__, val, val);
467                               ecode = HAL_EESIZE;
468                               goto bad;
469                     }
470                     HALDEBUG(ah, HAL_DEBUG_ANY,
471                         "%s: EEPROM size = %d. Must be %d (16k).\n",
472                         __func__, val, AR_PCICFG_EEPROM_SIZE_16K);
473                     ecode = HAL_EESIZE;
474                     goto bad;
475           }
476           ecode = ath_hal_legacyEepromAttach(ah);
477           if (ecode != HAL_OK) {
478                     goto bad;
479           }
480           ahp->ah_isHb63 = IS_2425(ah) && ath_hal_eepromGetFlag(ah, AR_EEP_ISTALON);
481 
482           /*
483            * If Bmode and AR5212, verify 2.4 analog exists
484            */
485           if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE) &&
486               (AH_PRIVATE(ah)->ah_analog5GhzRev & 0xF0) == AR_RAD5111_SREV_MAJOR) {
487                     /*
488                      * Set correct Baseband to analog shift
489                      * setting to access analog chips.
490                      */
491                     OS_REG_WRITE(ah, AR_PHY(0), 0x00004007);
492                     OS_DELAY(2000);
493                     AH_PRIVATE(ah)->ah_analog2GhzRev = ar5212GetRadioRev(ah);
494 
495                     /* Set baseband for 5GHz chip */
496                     OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
497                     OS_DELAY(2000);
498                     if ((AH_PRIVATE(ah)->ah_analog2GhzRev & 0xF0) != AR_RAD2111_SREV_MAJOR) {
499                               HALDEBUG(ah, HAL_DEBUG_ANY,
500                                   "%s: 2G Radio Chip Rev 0x%02X is not "
501                                   "supported by this driver\n", __func__,
502                                   AH_PRIVATE(ah)->ah_analog2GhzRev);
503                               ecode = HAL_ENOTSUPP;
504                               goto bad;
505                     }
506           }
507 
508           ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval);
509           if (ecode != HAL_OK) {
510                     HALDEBUG(ah, HAL_DEBUG_ANY,
511                         "%s: cannot read regulatory domain from EEPROM\n",
512                         __func__);
513                     goto bad;
514         }
515           AH_PRIVATE(ah)->ah_currentRD = eeval;
516           /* XXX record serial number */
517 
518           /*
519            * Got everything we need now to setup the capabilities.
520            */
521           if (!ar5212FillCapabilityInfo(ah)) {
522                     HALDEBUG(ah, HAL_DEBUG_ANY,
523                         "%s: failed ar5212FillCapabilityInfo\n", __func__);
524                     ecode = HAL_EEREAD;
525                     goto bad;
526           }
527 
528           if (!rf->attach(ah, &ecode)) {
529                     HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n",
530                         __func__, ecode);
531                     goto bad;
532           }
533           /*
534            * Set noise floor adjust method; we arrange a
535            * direct call instead of thunking.
536            */
537           AH_PRIVATE(ah)->ah_getNfAdjust = ahp->ah_rfHal->getNfAdjust;
538 
539           /* Initialize gain ladder thermal calibration structure */
540           ar5212InitializeGainValues(ah);
541 
542           ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr);
543           if (ecode != HAL_OK) {
544                     HALDEBUG(ah, HAL_DEBUG_ANY,
545                         "%s: error getting mac address from EEPROM\n", __func__);
546                     goto bad;
547         }
548 
549           ar5212AniSetup(ah);
550           /* Setup of Radar/AR structures happens in ath_hal_initchannels*/
551           ar5212InitNfCalHistBuffer(ah);
552 
553           /* XXX EAR stuff goes here */
554 
555           HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);
556 
557           return ah;
558 
559 bad:
560           if (ahp)
561                     ar5212Detach((struct ath_hal *) ahp);
562           if (status)
563                     *status = ecode;
564           return AH_NULL;
565 #undef AH_EEPROM_PROTECT
566 }
567 
568 void
ar5212Detach(struct ath_hal * ah)569 ar5212Detach(struct ath_hal *ah)
570 {
571           HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__);
572 
573           HALASSERT(ah != AH_NULL);
574           HALASSERT(ah->ah_magic == AR5212_MAGIC);
575 
576           ar5212AniDetach(ah);
577           ar5212RfDetach(ah);
578           ar5212Disable(ah);
579           ar5212SetPowerMode(ah, HAL_PM_FULL_SLEEP, AH_TRUE);
580 
581           ath_hal_eepromDetach(ah);
582           ath_hal_free(ah);
583 }
584 
585 HAL_BOOL
ar5212ChipTest(struct ath_hal * ah)586 ar5212ChipTest(struct ath_hal *ah)
587 {
588           uint32_t regAddr[2] = { AR_STA_ID0, AR_PHY_BASE+(8 << 2) };
589           uint32_t regHold[2];
590           uint32_t patternData[4] =
591               { 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 };
592           int i, j;
593 
594           /* Test PHY & MAC registers */
595           for (i = 0; i < 2; i++) {
596                     uint32_t addr = regAddr[i];
597                     uint32_t wrData, rdData;
598 
599                     regHold[i] = OS_REG_READ(ah, addr);
600                     for (j = 0; j < 0x100; j++) {
601                               wrData = (j << 16) | j;
602                               OS_REG_WRITE(ah, addr, wrData);
603                               rdData = OS_REG_READ(ah, addr);
604                               if (rdData != wrData) {
605                                         HALDEBUG(ah, HAL_DEBUG_ANY,
606 "%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
607                                         __func__, addr, wrData, rdData);
608                                         return AH_FALSE;
609                               }
610                     }
611                     for (j = 0; j < 4; j++) {
612                               wrData = patternData[j];
613                               OS_REG_WRITE(ah, addr, wrData);
614                               rdData = OS_REG_READ(ah, addr);
615                               if (wrData != rdData) {
616                                         HALDEBUG(ah, HAL_DEBUG_ANY,
617 "%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
618                                                   __func__, addr, wrData, rdData);
619                                         return AH_FALSE;
620                               }
621                     }
622                     OS_REG_WRITE(ah, regAddr[i], regHold[i]);
623           }
624           OS_DELAY(100);
625           return AH_TRUE;
626 }
627 
628 /*
629  * Store the channel edges for the requested operational mode
630  */
631 HAL_BOOL
ar5212GetChannelEdges(struct ath_hal * ah,uint16_t flags,uint16_t * low,uint16_t * high)632 ar5212GetChannelEdges(struct ath_hal *ah,
633           uint16_t flags, uint16_t *low, uint16_t *high)
634 {
635           if (flags & CHANNEL_5GHZ) {
636                     *low = 4915;
637                     *high = 6100;
638                     return AH_TRUE;
639           }
640           if ((flags & CHANNEL_2GHZ) &&
641               (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE) ||
642                ath_hal_eepromGetFlag(ah, AR_EEP_GMODE))) {
643                     *low = 2312;
644                     *high = 2732;
645                     return AH_TRUE;
646           }
647           return AH_FALSE;
648 }
649 
650 /*
651  * Disable PLL when in L0s as well as receiver clock when in L1.
652  * This power saving option must be enabled through the Serdes.
653  *
654  * Programming the Serdes must go through the same 288 bit serial shift
655  * register as the other analog registers.  Hence the 9 writes.
656  *
657  * XXX Clean up the magic numbers.
658  */
659 static void
ar5212ConfigPCIE(struct ath_hal * ah,HAL_BOOL restore)660 ar5212ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore)
661 {
662           OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
663           OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
664 
665           /* RX shut off when elecidle is asserted */
666           OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
667           OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
668           OS_REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
669 
670           /* Shut off PLL and CLKREQ active in L1 */
671           OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
672           OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
673           OS_REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
674           OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
675 
676           /* Load the new settings */
677           OS_REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
678 }
679 
680 static void
ar5212DisablePCIE(struct ath_hal * ah)681 ar5212DisablePCIE(struct ath_hal *ah)
682 {
683           /* NB: fill in for 9100 */
684 }
685 
686 /*
687  * Fill all software cached or static hardware state information.
688  * Return failure if capabilities are to come from EEPROM and
689  * cannot be read.
690  */
691 HAL_BOOL
ar5212FillCapabilityInfo(struct ath_hal * ah)692 ar5212FillCapabilityInfo(struct ath_hal *ah)
693 {
694 #define   AR_KEYTABLE_SIZE    128
695 #define   IS_GRIFFIN_LITE(ah) \
696     (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_GRIFFIN && \
697      AH_PRIVATE(ah)->ah_macRev == AR_SREV_GRIFFIN_LITE)
698 #define   IS_COBRA(ah) \
699     (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_COBRA)
700 #define IS_2112(ah) \
701           ((AH_PRIVATE(ah)->ah_analog5GhzRev & 0xF0) == AR_RAD2112_SREV_MAJOR)
702 
703           struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
704           HAL_CAPABILITIES *pCap = &ahpriv->ah_caps;
705           uint16_t capField, val;
706 
707           /* Read the capability EEPROM location */
708           if (ath_hal_eepromGet(ah, AR_EEP_OPCAP, &capField) != HAL_OK) {
709                     HALDEBUG(ah, HAL_DEBUG_ANY,
710                         "%s: unable to read caps from eeprom\n", __func__);
711                     return AH_FALSE;
712           }
713           if (IS_2112(ah))
714                     ath_hal_eepromSet(ah, AR_EEP_AMODE, AH_FALSE);
715           if (capField == 0 && IS_GRIFFIN_LITE(ah)) {
716                     /*
717                      * For griffin-lite cards with unprogrammed capabilities.
718                      */
719                     ath_hal_eepromSet(ah, AR_EEP_COMPRESS, AH_FALSE);
720                     ath_hal_eepromSet(ah, AR_EEP_FASTFRAME, AH_FALSE);
721                     ath_hal_eepromSet(ah, AR_EEP_TURBO5DISABLE, AH_TRUE);
722                     ath_hal_eepromSet(ah, AR_EEP_TURBO2DISABLE, AH_TRUE);
723                     HALDEBUG(ah, HAL_DEBUG_ATTACH,
724                         "%s: override caps for griffin-lite, now 0x%x (+!turbo)\n",
725                         __func__, capField);
726           }
727 
728           /* Modify reg domain on newer cards that need to work with older sw */
729           if (ahpriv->ah_opmode != HAL_M_HOSTAP &&
730               ahpriv->ah_subvendorid == AR_SUBVENDOR_ID_NEW_A) {
731                     if (ahpriv->ah_currentRD == 0x64 ||
732                         ahpriv->ah_currentRD == 0x65)
733                               ahpriv->ah_currentRD += 5;
734                     else if (ahpriv->ah_currentRD == 0x41)
735                               ahpriv->ah_currentRD = 0x43;
736                     HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: regdomain mapped to 0x%x\n",
737                         __func__, ahpriv->ah_currentRD);
738           }
739 
740           if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2417 ||
741               AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2425) {
742                     HALDEBUG(ah, HAL_DEBUG_ATTACH,
743                         "%s: enable Bmode and disable turbo for Swan/Nala\n",
744                         __func__);
745                     ath_hal_eepromSet(ah, AR_EEP_BMODE, AH_TRUE);
746                     ath_hal_eepromSet(ah, AR_EEP_COMPRESS, AH_FALSE);
747                     ath_hal_eepromSet(ah, AR_EEP_FASTFRAME, AH_FALSE);
748                     ath_hal_eepromSet(ah, AR_EEP_TURBO5DISABLE, AH_TRUE);
749                     ath_hal_eepromSet(ah, AR_EEP_TURBO2DISABLE, AH_TRUE);
750           }
751 
752           /* Construct wireless mode from EEPROM */
753           pCap->halWirelessModes = 0;
754           if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) {
755                     pCap->halWirelessModes |= HAL_MODE_11A;
756                     if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE))
757                               pCap->halWirelessModes |= HAL_MODE_TURBO;
758           }
759           if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE))
760                     pCap->halWirelessModes |= HAL_MODE_11B;
761           if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) &&
762               ahpriv->ah_subvendorid != AR_SUBVENDOR_ID_NOG) {
763                     pCap->halWirelessModes |= HAL_MODE_11G;
764                     if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO2DISABLE))
765                               pCap->halWirelessModes |= HAL_MODE_108G;
766           }
767 
768           pCap->halLow2GhzChan = 2312;
769           /* XXX 2417 too? */
770           if (IS_RAD5112_ANY(ah) || IS_5413(ah) || IS_2425(ah) ||  IS_2417(ah))
771                     pCap->halHigh2GhzChan = 2500;
772           else
773                     pCap->halHigh2GhzChan = 2732;
774 
775           pCap->halLow5GhzChan = 4915;
776           pCap->halHigh5GhzChan = 6100;
777 
778           pCap->halCipherCkipSupport = AH_FALSE;
779           pCap->halCipherTkipSupport = AH_TRUE;
780           pCap->halCipherAesCcmSupport =
781                     (ath_hal_eepromGetFlag(ah, AR_EEP_AES) &&
782                      ((AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE) ||
783                       ((AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE) &&
784                        (AH_PRIVATE(ah)->ah_macRev >= AR_SREV_VERSION_OAHU))));
785 
786           pCap->halMicCkipSupport    = AH_FALSE;
787           pCap->halMicTkipSupport    = AH_TRUE;
788           pCap->halMicAesCcmSupport  = ath_hal_eepromGetFlag(ah, AR_EEP_AES);
789           /*
790            * Starting with Griffin TX+RX mic keys can be combined
791            * in one key cache slot.
792            */
793           if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_GRIFFIN)
794                     pCap->halTkipMicTxRxKeySupport = AH_TRUE;
795           else
796                     pCap->halTkipMicTxRxKeySupport = AH_FALSE;
797           pCap->halChanSpreadSupport = AH_TRUE;
798           pCap->halSleepAfterBeaconBroken = AH_TRUE;
799 
800           if (ahpriv->ah_macRev > 1 || IS_COBRA(ah)) {
801                     pCap->halCompressSupport   =
802                               ath_hal_eepromGetFlag(ah, AR_EEP_COMPRESS) &&
803                               (pCap->halWirelessModes & (HAL_MODE_11A|HAL_MODE_11G)) != 0;
804                     pCap->halBurstSupport = ath_hal_eepromGetFlag(ah, AR_EEP_BURST);
805                     pCap->halFastFramesSupport =
806                               ath_hal_eepromGetFlag(ah, AR_EEP_FASTFRAME) &&
807                               (pCap->halWirelessModes & (HAL_MODE_11A|HAL_MODE_11G)) != 0;
808                     pCap->halChapTuningSupport = AH_TRUE;
809                     pCap->halTurboPrimeSupport = AH_TRUE;
810           }
811           pCap->halTurboGSupport = pCap->halWirelessModes & HAL_MODE_108G;
812 
813           pCap->halPSPollBroken = AH_TRUE;        /* XXX fixed in later revs? */
814           pCap->halVEOLSupport = AH_TRUE;
815           pCap->halBssIdMaskSupport = AH_TRUE;
816           pCap->halMcastKeySrchSupport = AH_TRUE;
817           if ((ahpriv->ah_macVersion == AR_SREV_VERSION_VENICE &&
818                ahpriv->ah_macRev == 8) ||
819               ahpriv->ah_macVersion > AR_SREV_VERSION_VENICE)
820                     pCap->halTsfAddSupport = AH_TRUE;
821 
822           if (ath_hal_eepromGet(ah, AR_EEP_MAXQCU, &val) == HAL_OK)
823                     pCap->halTotalQueues = val;
824           else
825                     pCap->halTotalQueues = HAL_NUM_TX_QUEUES;
826 
827           if (ath_hal_eepromGet(ah, AR_EEP_KCENTRIES, &val) == HAL_OK)
828                     pCap->halKeyCacheSize = val;
829           else
830                     pCap->halKeyCacheSize = AR_KEYTABLE_SIZE;
831 
832           pCap->halChanHalfRate = AH_TRUE;
833           pCap->halChanQuarterRate = AH_TRUE;
834 
835           if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) &&
836               ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) {
837                     /* NB: enabled by default */
838                     ahpriv->ah_rfkillEnabled = AH_TRUE;
839                     pCap->halRfSilentSupport = AH_TRUE;
840           }
841 
842           /* NB: this is a guess, noone seems to know the answer */
843           ahpriv->ah_rxornIsFatal =
844               (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_VENICE);
845 
846           /* enable features that first appeared in Hainan */
847           if ((AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE &&
848                AH_PRIVATE(ah)->ah_macRev == AR_SREV_HAINAN) ||
849               AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE) {
850                     /* h/w phy counters */
851                     pCap->halHwPhyCounterSupport = AH_TRUE;
852                     /* bssid match disable */
853                     pCap->halBssidMatchSupport = AH_TRUE;
854           }
855 
856           pCap->halTstampPrecision = 15;
857           pCap->halIntrMask = HAL_INT_COMMON
858                               | HAL_INT_RX
859                               | HAL_INT_TX
860                               | HAL_INT_FATAL
861                               | HAL_INT_BNR
862                               | HAL_INT_BMISC
863                               ;
864 
865           if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_GRIFFIN)
866                     pCap->halIntrMask &= ~HAL_INT_TBTT;
867 
868           return AH_TRUE;
869 #undef IS_COBRA
870 #undef IS_GRIFFIN_LITE
871 #undef AR_KEYTABLE_SIZE
872 }
873 
874 static const char*
ar5212Probe(uint16_t vendorid,uint16_t devid)875 ar5212Probe(uint16_t vendorid, uint16_t devid)
876 {
877           if (vendorid == ATHEROS_VENDOR_ID ||
878               vendorid == ATHEROS_3COM_VENDOR_ID ||
879               vendorid == ATHEROS_3COM2_VENDOR_ID) {
880                     switch (devid) {
881                     case AR5212_FPGA:
882                               return "Atheros 5212 (FPGA)";
883                     case AR5212_DEVID:
884                     case AR5212_DEVID_IBM:
885                     case AR5212_DEFAULT:
886                               return "Atheros 5212";
887                     case AR5212_AR2413:
888                               return "Atheros 2413";
889                     case AR5212_AR2417:
890                               return "Atheros 2417";
891                     case AR5212_AR5413:
892                               return "Atheros 5413";
893                     case AR5212_AR5424:
894                               return "Atheros 5424/2424";
895                     }
896           }
897           return AH_NULL;
898 }
899 AH_CHIP(AR5212, ar5212Probe, ar5212Attach);
900