xref: /freebsd/sys/dev/ath/ath_hal/ar5312/ar5312_misc.c (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
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