1*6e778a7eSPedro F. Giffuni /*-
2*6e778a7eSPedro F. Giffuni * SPDX-License-Identifier: ISC
3*6e778a7eSPedro F. Giffuni *
414779705SSam Leffler * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
514779705SSam Leffler * Copyright (c) 2002-2008 Atheros Communications, Inc.
614779705SSam Leffler *
714779705SSam Leffler * Permission to use, copy, modify, and/or distribute this software for any
814779705SSam Leffler * purpose with or without fee is hereby granted, provided that the above
914779705SSam Leffler * copyright notice and this permission notice appear in all copies.
1014779705SSam Leffler *
1114779705SSam Leffler * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1214779705SSam Leffler * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1314779705SSam Leffler * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1414779705SSam Leffler * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1514779705SSam Leffler * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1614779705SSam Leffler * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1714779705SSam Leffler * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1814779705SSam Leffler */
1914779705SSam Leffler #include "opt_ah.h"
2014779705SSam Leffler
2114779705SSam Leffler #ifdef AH_SUPPORT_AR5312
2214779705SSam Leffler
2314779705SSam Leffler #include "ah.h"
2414779705SSam Leffler #include "ah_internal.h"
2514779705SSam Leffler #include "ah_devid.h"
2614779705SSam Leffler
2714779705SSam Leffler #include "ar5312/ar5312.h"
2814779705SSam Leffler #include "ar5312/ar5312reg.h"
2914779705SSam Leffler #include "ar5312/ar5312phy.h"
3014779705SSam Leffler
3114779705SSam Leffler #define AR_NUM_GPIO 6 /* 6 GPIO pins */
3214779705SSam Leffler #define AR_GPIOD_MASK 0x0000002F /* GPIO data reg r/w mask */
3314779705SSam Leffler
3414779705SSam Leffler /*
3514779705SSam Leffler * Change the LED blinking pattern to correspond to the connectivity
3614779705SSam Leffler */
3714779705SSam Leffler void
ar5312SetLedState(struct ath_hal * ah,HAL_LED_STATE state)3814779705SSam Leffler ar5312SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
3914779705SSam Leffler {
4014779705SSam Leffler uint32_t val;
4114779705SSam Leffler uint32_t resOffset = (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh));
4214779705SSam Leffler if(IS_2316(ah)) return; /* not yet */
4314779705SSam Leffler val = SM(AR5312_PCICFG_LEDSEL0, AR5312_PCICFG_LEDSEL) |
4414779705SSam Leffler SM(AR5312_PCICFG_LEDMOD0, AR5312_PCICFG_LEDMODE) |
4514779705SSam Leffler 2;
4614779705SSam Leffler OS_REG_WRITE(ah, resOffset+AR5312_PCICFG,
4714779705SSam Leffler (OS_REG_READ(ah, AR5312_PCICFG) &~
4814779705SSam Leffler (AR5312_PCICFG_LEDSEL | AR5312_PCICFG_LEDMODE |
4914779705SSam Leffler AR5312_PCICFG_LEDSBR))
5014779705SSam Leffler | val);
5114779705SSam Leffler }
5214779705SSam Leffler
5314779705SSam Leffler /*
5414779705SSam Leffler * Detect if our wireless mac is present.
5514779705SSam Leffler */
5614779705SSam Leffler HAL_BOOL
ar5312DetectCardPresent(struct ath_hal * ah)5714779705SSam Leffler ar5312DetectCardPresent(struct ath_hal *ah)
5814779705SSam Leffler {
5914779705SSam Leffler uint16_t macVersion, macRev;
6014779705SSam Leffler uint32_t v;
6114779705SSam Leffler
6214779705SSam Leffler /*
6314779705SSam Leffler * Read the Silicon Revision register and compare that
6414779705SSam Leffler * to what we read at attach time. If the same, we say
6514779705SSam Leffler * a card/device is present.
6614779705SSam Leffler */
6714779705SSam Leffler #if (AH_SUPPORT_2316 || AH_SUPPORT_2317)
6814779705SSam Leffler if(IS_5315(ah))
6914779705SSam Leffler {
7014779705SSam Leffler v = (OS_REG_READ(ah,
7114779705SSam Leffler (AR5315_RSTIMER_BASE-((uint32_t) ah->ah_sh)) + AR5315_WREV))
7214779705SSam Leffler & AR_SREV_ID;
7314779705SSam Leffler macVersion = v >> AR_SREV_ID_S;
7414779705SSam Leffler macRev = v & AR_SREV_REVISION;
7514779705SSam Leffler return (AH_PRIVATE(ah)->ah_macVersion == macVersion &&
7614779705SSam Leffler AH_PRIVATE(ah)->ah_macRev == macRev);
7714779705SSam Leffler }
7814779705SSam Leffler else
7914779705SSam Leffler #endif
8014779705SSam Leffler {
8114779705SSam Leffler v = (OS_REG_READ(ah,
8214779705SSam Leffler (AR5312_RSTIMER_BASE-((uint32_t) ah->ah_sh)) + AR5312_WREV))
8314779705SSam Leffler & AR_SREV_ID;
8414779705SSam Leffler macVersion = v >> AR_SREV_ID_S;
8514779705SSam Leffler macRev = v & AR_SREV_REVISION;
8614779705SSam Leffler return (AH_PRIVATE(ah)->ah_macVersion == macVersion &&
8714779705SSam Leffler AH_PRIVATE(ah)->ah_macRev == macRev);
8814779705SSam Leffler }
8914779705SSam Leffler }
9014779705SSam Leffler
9114779705SSam Leffler /*
9214779705SSam Leffler * If 32KHz clock exists, use it to lower power consumption during sleep
9314779705SSam Leffler *
9414779705SSam Leffler * Note: If clock is set to 32 KHz, delays on accessing certain
9514779705SSam Leffler * baseband registers (27-31, 124-127) are required.
9614779705SSam Leffler */
9714779705SSam Leffler void
ar5312SetupClock(struct ath_hal * ah,HAL_OPMODE opmode)9814779705SSam Leffler ar5312SetupClock(struct ath_hal *ah, HAL_OPMODE opmode)
9914779705SSam Leffler {
10014779705SSam Leffler if (ar5212Use32KHzclock(ah, opmode)) {
10114779705SSam Leffler /*
10214779705SSam Leffler * Enable clocks to be turned OFF in BB during sleep
10314779705SSam Leffler * and also enable turning OFF 32MHz/40MHz Refclk
10414779705SSam Leffler * from A2.
10514779705SSam Leffler */
10614779705SSam Leffler OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f);
10714779705SSam Leffler OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x0d);
10814779705SSam Leffler OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0c);
10914779705SSam Leffler OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x03);
11014779705SSam Leffler OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0x05);
11114779705SSam Leffler OS_REG_WRITE(ah, AR_PHY_REFCLKPD,
11214779705SSam Leffler IS_RAD5112_ANY(ah) ? 0x14 : 0x18);
11314779705SSam Leffler
11414779705SSam Leffler OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 1);
11514779705SSam Leffler OS_REG_WRITE(ah, AR_TSF_PARM, 61); /* 32 KHz TSF incr */
11614779705SSam Leffler
11714779705SSam Leffler } else {
11814779705SSam Leffler OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32 MHz TSF incr */
11914779705SSam Leffler OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32,
12014779705SSam Leffler IS_RAD5112_ANY(ah) ? 39 : 31);
12114779705SSam Leffler
12214779705SSam Leffler OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f);
12314779705SSam Leffler OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f);
12414779705SSam Leffler
12514779705SSam Leffler if (IS_5312_2_X(ah)) {
12614779705SSam Leffler /* Set ADC/DAC select values */
12714779705SSam Leffler OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x04);
12814779705SSam Leffler } else {
12914779705SSam Leffler OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e);
13014779705SSam Leffler OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c);
13114779705SSam Leffler OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff);
13214779705SSam Leffler OS_REG_WRITE(ah, AR_PHY_REFCLKPD,
13314779705SSam Leffler IS_RAD5112_ANY(ah) ? 0x14 : 0x18);
13414779705SSam Leffler }
13514779705SSam Leffler }
13614779705SSam Leffler }
13714779705SSam Leffler
13814779705SSam Leffler /*
13914779705SSam Leffler * If 32KHz clock exists, turn it off and turn back on the 32Mhz
14014779705SSam Leffler */
14114779705SSam Leffler void
ar5312RestoreClock(struct ath_hal * ah,HAL_OPMODE opmode)14214779705SSam Leffler ar5312RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode)
14314779705SSam Leffler {
14414779705SSam Leffler if (ar5212Use32KHzclock(ah, opmode)) {
14514779705SSam Leffler /* # Set sleep clock rate back to 32 MHz. */
14614779705SSam Leffler OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32 MHz TSF incr */
14714779705SSam Leffler OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32,
14814779705SSam Leffler IS_RAD5112_ANY(ah) ? 39 : 31);
14914779705SSam Leffler
15014779705SSam Leffler /*
15114779705SSam Leffler * Restore BB registers to power-on defaults
15214779705SSam Leffler */
15314779705SSam Leffler OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f);
15414779705SSam Leffler OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f);
15514779705SSam Leffler if (IS_5312_2_X(ah)) {
15614779705SSam Leffler /* Set ADC/DAC select values */
15714779705SSam Leffler OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x04);
15814779705SSam Leffler } else {
15914779705SSam Leffler OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e);
16014779705SSam Leffler OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c);
16114779705SSam Leffler OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff);
16214779705SSam Leffler OS_REG_WRITE(ah, AR_PHY_REFCLKPD,
16314779705SSam Leffler IS_RAD5112_ANY(ah) ? 0x14 : 0x18);
16414779705SSam Leffler }
16514779705SSam Leffler }
16614779705SSam Leffler }
16714779705SSam Leffler
16814779705SSam Leffler #endif /* AH_SUPPORT_AR5312 */
169