Date: Tue, 24 Feb 2009 00:33:08 +0000 (UTC) From: Sam Leffler <sam@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r188976 - head/sys/dev/ath/ath_hal/ar5416 Message-ID: <200902240033.n1O0X8FE045560@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: sam Date: Tue Feb 24 00:33:08 2009 New Revision: 188976 URL: http://svn.freebsd.org/changeset/base/188976 Log: Fill in gpio support for 5416 and later parts: o add output mux support o gpio pin count is chip-dependent o 9280 and 9285 do input handling different o hookup gpio interrupts o no need to save/restore soft led state around reset Modified: head/sys/dev/ath/ath_hal/ar5416/ar5416.h head/sys/dev/ath/ath_hal/ar5416/ar5416_gpio.c head/sys/dev/ath/ath_hal/ar5416/ar5416_interrupts.c head/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c head/sys/dev/ath/ath_hal/ar5416/ar5416reg.h Modified: head/sys/dev/ath/ath_hal/ar5416/ar5416.h ============================================================================== --- head/sys/dev/ath/ath_hal/ar5416/ar5416.h Tue Feb 24 00:29:32 2009 (r188975) +++ head/sys/dev/ath/ath_hal/ar5416/ar5416.h Tue Feb 24 00:33:08 2009 (r188976) @@ -59,6 +59,7 @@ struct ath_hal_5416 { HAL_INI_ARRAY ah_ini_addac; u_int ah_globaltxtimeout; /* global tx timeout */ + u_int ah_gpioMask; int ah_hangs; /* h/w hangs state */ uint8_t ah_keytype[AR5416_KEYTABLE_SIZE]; /* Modified: head/sys/dev/ath/ath_hal/ar5416/ar5416_gpio.c ============================================================================== --- head/sys/dev/ath/ath_hal/ar5416/ar5416_gpio.c Tue Feb 24 00:29:32 2009 (r188975) +++ head/sys/dev/ath/ath_hal/ar5416/ar5416_gpio.c Tue Feb 24 00:33:08 2009 (r188976) @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting * Copyright (c) 2002-2008 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any @@ -21,36 +21,95 @@ #include "ah.h" #include "ah_internal.h" #include "ah_devid.h" -#ifdef AH_DEBUG -#include "ah_desc.h" /* NB: for HAL_PHYERR* */ -#endif #include "ar5416/ar5416.h" #include "ar5416/ar5416reg.h" #include "ar5416/ar5416phy.h" -#define AR_NUM_GPIO 6 /* 6 GPIO pins */ #define AR_GPIO_BIT(_gpio) (1 << _gpio) /* + * Configure GPIO Output Mux control + */ +static void +cfgOutputMux(struct ath_hal *ah, uint32_t gpio, uint32_t type) +{ + int addr; + uint32_t gpio_shift, reg; + + /* each MUX controls 6 GPIO pins */ + if (gpio > 11) + addr = AR_GPIO_OUTPUT_MUX3; + else if (gpio > 5) + addr = AR_GPIO_OUTPUT_MUX2; + else + addr = AR_GPIO_OUTPUT_MUX1; + + /* + * 5 bits per GPIO pin. Bits 0..4 for 1st pin in that mux, + * bits 5..9 for 2nd pin, etc. + */ + gpio_shift = (gpio % 6) * 5; + + /* + * From Owl to Merlin 1.0, the value read from MUX1 bit 4 to bit + * 9 are wrong. Here is hardware's coding: + * PRDATA[4:0] <= gpio_output_mux[0]; + * PRDATA[9:4] <= gpio_output_mux[1]; + * <==== Bit 4 is used by both gpio_output_mux[0] [1]. + * Currently the max value for gpio_output_mux[] is 6. So bit 4 + * will never be used. So it should be fine that bit 4 won't be + * able to recover. + */ + reg = OS_REG_READ(ah, addr); + if (addr == AR_GPIO_OUTPUT_MUX1 && !AR_SREV_MERLIN_20_OR_LATER(ah)) + reg = ((reg & 0x1F0) << 1) | (reg & ~0x1F0); + reg &= ~(0x1f << gpio_shift); + reg |= type << gpio_shift; + OS_REG_WRITE(ah, addr, reg); +} + +/* * Configure GPIO Output lines */ HAL_BOOL ar5416GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type) { - HALASSERT(gpio < AR_NUM_GPIO); - OS_REG_CLR_BIT(ah, AR_GPIO_INTR_OUT, AR_GPIO_BIT(gpio)); + uint32_t gpio_shift, reg; + + HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); + + /* NB: type maps directly to hardware */ + cfgOutputMux(ah, gpio, type); + gpio_shift = gpio << 1; /* 2 bits per output mode */ + + reg = OS_REG_READ(ah, AR_GPIO_OE_OUT); + reg &= ~(AR_GPIO_OE_OUT_DRV << gpio_shift); + reg |= AR_GPIO_OE_OUT_DRV_ALL << gpio_shift, + OS_REG_WRITE(ah, AR_GPIO_OE_OUT, reg); + return AH_TRUE; } - + /* * Configure GPIO Input lines */ HAL_BOOL ar5416GpioCfgInput(struct ath_hal *ah, uint32_t gpio) { - HALASSERT(gpio < AR_NUM_GPIO); - OS_REG_SET_BIT(ah, AR_GPIO_INTR_OUT, AR_GPIO_BIT(gpio)); + uint32_t gpio_shift, reg; + + HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); + + /* TODO: configure input mux for AR5416 */ + /* If configured as input, set output to tristate */ + gpio_shift = gpio << 1; + + reg = OS_REG_READ(ah, AR_GPIO_OE_OUT); + reg &= ~(AR_GPIO_OE_OUT_DRV << gpio_shift); + reg |= AR_GPIO_OE_OUT_DRV_ALL << gpio_shift, + OS_REG_WRITE(ah, AR_GPIO_OE_OUT, reg); + return AH_TRUE; } @@ -62,14 +121,14 @@ ar5416GpioSet(struct ath_hal *ah, uint32 { uint32_t reg; - HALASSERT(gpio < AR_NUM_GPIO); - reg = MS(OS_REG_READ(ah, AR_GPIO_INTR_OUT), AR_GPIO_OUT_VAL); + HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); + + reg = OS_REG_READ(ah, AR_GPIO_IN_OUT); if (val & 1) reg |= AR_GPIO_BIT(gpio); else reg &= ~AR_GPIO_BIT(gpio); - - OS_REG_RMW_FIELD(ah, AR_GPIO_INTR_OUT, AR_GPIO_OUT_VAL, reg); + OS_REG_WRITE(ah, AR_GPIO_IN_OUT, reg); return AH_TRUE; } @@ -79,34 +138,92 @@ ar5416GpioSet(struct ath_hal *ah, uint32 uint32_t ar5416GpioGet(struct ath_hal *ah, uint32_t gpio) { - if (gpio >= AR_NUM_GPIO) + uint32_t bits; + + if (gpio >= AH_PRIVATE(ah)->ah_caps.halNumGpioPins) return 0xffffffff; - return ((OS_REG_READ(ah, AR_GPIO_IN) & AR_GPIO_BIT(gpio)) >> gpio); + /* + * Read output value for all gpio's, shift it, + * and verify whether the specific bit is set. + */ + if (AR_SREV_MERLIN_10_OR_LATER(ah)) + bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR928X_GPIO_IN_VAL); + else + bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR_GPIO_IN_VAL); + return ((bits & AR_GPIO_BIT(gpio)) != 0); } /* - * Set the GPIO Interrupt + * Set the GPIO Interrupt Sync and Async interrupts are both set/cleared. + * Async GPIO interrupts may not be raised when the chip is put to sleep. */ void ar5416GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) { - uint32_t val; - - HALASSERT(gpio < AR_NUM_GPIO); - /* XXX bounds check gpio */ - val = MS(OS_REG_READ(ah, AR_GPIO_INTR_OUT), AR_GPIO_INTR_CTRL); - if (ilevel) /* 0 == interrupt on pin high */ - val &= ~AR_GPIO_BIT(gpio); - else /* 1 == interrupt on pin low */ - val |= AR_GPIO_BIT(gpio); - OS_REG_RMW_FIELD(ah, AR_GPIO_INTR_OUT, AR_GPIO_INTR_CTRL, val); - - /* Change the interrupt mask. */ - val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE), AR_INTR_GPIO); - val |= AR_GPIO_BIT(gpio); - OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_ENABLE, AR_INTR_GPIO, val); - - val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_MASK), AR_INTR_GPIO); - val |= AR_GPIO_BIT(gpio); - OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_MASK, AR_INTR_GPIO, val); + uint32_t val, mask; + + HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); + + if (ilevel == HAL_GPIO_INTR_DISABLE) { + val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE), + AR_INTR_ASYNC_ENABLE_GPIO) &~ AR_GPIO_BIT(gpio); + OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_ENABLE, + AR_INTR_ASYNC_ENABLE_GPIO, val); + + mask = MS(OS_REG_READ(ah, AR_INTR_ASYNC_MASK), + AR_INTR_ASYNC_MASK_GPIO) &~ AR_GPIO_BIT(gpio); + OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_MASK, + AR_INTR_ASYNC_MASK_GPIO, mask); + + /* Clear synchronous GPIO interrupt registers and pending interrupt flag */ + val = MS(OS_REG_READ(ah, AR_INTR_SYNC_ENABLE), + AR_INTR_SYNC_ENABLE_GPIO) &~ AR_GPIO_BIT(gpio); + OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_ENABLE, + AR_INTR_SYNC_ENABLE_GPIO, val); + + mask = MS(OS_REG_READ(ah, AR_INTR_SYNC_MASK), + AR_INTR_SYNC_MASK_GPIO) &~ AR_GPIO_BIT(gpio); + OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_MASK, + AR_INTR_SYNC_MASK_GPIO, mask); + + val = MS(OS_REG_READ(ah, AR_INTR_SYNC_CAUSE), + AR_INTR_SYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio); + OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_CAUSE, + AR_INTR_SYNC_ENABLE_GPIO, val); + } else { + val = MS(OS_REG_READ(ah, AR_GPIO_INTR_POL), + AR_GPIO_INTR_POL_VAL); + if (ilevel == HAL_GPIO_INTR_HIGH) { + /* 0 == interrupt on pin high */ + val &= ~AR_GPIO_BIT(gpio); + } else if (ilevel == HAL_GPIO_INTR_LOW) { + /* 1 == interrupt on pin low */ + val |= AR_GPIO_BIT(gpio); + } + OS_REG_RMW_FIELD(ah, AR_GPIO_INTR_POL, + AR_GPIO_INTR_POL_VAL, val); + + /* Change the interrupt mask. */ + val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE), + AR_INTR_ASYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio); + OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_ENABLE, + AR_INTR_ASYNC_ENABLE_GPIO, val); + + mask = MS(OS_REG_READ(ah, AR_INTR_ASYNC_MASK), + AR_INTR_ASYNC_MASK_GPIO) | AR_GPIO_BIT(gpio); + OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_MASK, + AR_INTR_ASYNC_MASK_GPIO, mask); + + /* Set synchronous GPIO interrupt registers as well */ + val = MS(OS_REG_READ(ah, AR_INTR_SYNC_ENABLE), + AR_INTR_SYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio); + OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_ENABLE, + AR_INTR_SYNC_ENABLE_GPIO, val); + + mask = MS(OS_REG_READ(ah, AR_INTR_SYNC_MASK), + AR_INTR_SYNC_MASK_GPIO) | AR_GPIO_BIT(gpio); + OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_MASK, + AR_INTR_SYNC_MASK_GPIO, mask); + } + AH5416(ah)->ah_gpioMask = mask; /* for ar5416SetInterrupts */ } Modified: head/sys/dev/ath/ath_hal/ar5416/ar5416_interrupts.c ============================================================================== --- head/sys/dev/ath/ath_hal/ar5416/ar5416_interrupts.c Tue Feb 24 00:29:32 2009 (r188975) +++ head/sys/dev/ath/ath_hal/ar5416/ar5416_interrupts.c Tue Feb 24 00:33:08 2009 (r188976) @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: ar5416_interrupts.c,v 1.6 2008/11/10 04:08:04 sam Exp $ + * $FreeBSD$ */ #include "opt_ah.h" @@ -167,7 +167,7 @@ ar5416SetInterrupts(struct ath_hal *ah, { struct ath_hal_5212 *ahp = AH5212(ah); uint32_t omask = ahp->ah_maskReg; - uint32_t mask,mask2; + uint32_t mask, mask2; HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: 0x%x => 0x%x\n", __func__, omask, ints); @@ -248,11 +248,19 @@ ar5416SetInterrupts(struct ath_hal *ah, HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__); OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE); - OS_REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, AR_INTR_MAC_IRQ); - OS_REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); - - OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT); - OS_REG_WRITE(ah, AR_INTR_SYNC_MASK, AR_INTR_SYNC_DEFAULT); + mask = AR_INTR_MAC_IRQ; + if (ints & HAL_INT_GPIO) + mask |= SM(AH5416(ah)->ah_gpioMask, + AR_INTR_ASYNC_MASK_GPIO); + OS_REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, mask); + OS_REG_WRITE(ah, AR_INTR_ASYNC_MASK, mask); + + mask = AR_INTR_SYNC_DEFAULT; + if (ints & HAL_INT_GPIO) + mask |= SM(AH5416(ah)->ah_gpioMask, + AR_INTR_SYNC_MASK_GPIO); + OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, mask); + OS_REG_WRITE(ah, AR_INTR_SYNC_MASK, mask); } return omask; Modified: head/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c ============================================================================== --- head/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c Tue Feb 24 00:29:32 2009 (r188975) +++ head/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c Tue Feb 24 00:33:08 2009 (r188976) @@ -117,7 +117,6 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMO #define FAIL(_code) do { ecode = _code; goto bad; } while (0) struct ath_hal_5212 *ahp = AH5212(ah); HAL_CHANNEL_INTERNAL *ichan; - uint32_t softLedCfg; uint32_t saveDefAntenna, saveLedState; uint32_t macStaId1; uint16_t rfXpdGain[2]; @@ -181,7 +180,6 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMO saveLedState = OS_REG_READ(ah, AR_MAC_LED) & (AR_MAC_LED_ASSOC | AR_MAC_LED_MODE | AR_MAC_LED_BLINK_THRESH_SEL | AR_MAC_LED_BLINK_SLOW); - softLedCfg = OS_REG_READ(ah, AR_GPIO_INTR_OUT); /* * Adjust gain parameters before reset if @@ -342,8 +340,6 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMO /* Restore previous led state */ OS_REG_WRITE(ah, AR_MAC_LED, OS_REG_READ(ah, AR_MAC_LED) | saveLedState); - /* Restore soft Led state to GPIO */ - OS_REG_WRITE(ah, AR_GPIO_INTR_OUT, softLedCfg); /* Restore previous antenna */ OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); Modified: head/sys/dev/ath/ath_hal/ar5416/ar5416reg.h ============================================================================== --- head/sys/dev/ath/ath_hal/ar5416/ar5416reg.h Tue Feb 24 00:29:32 2009 (r188975) +++ head/sys/dev/ath/ath_hal/ar5416/ar5416reg.h Tue Feb 24 00:33:08 2009 (r188976) @@ -31,7 +31,6 @@ #define AR_GTTM 0x0068 /* global transmit timeout mode */ #define AR_CST 0x006C /* carrier sense timeout */ #define AR_MAC_LED 0x1f04 /* LED control */ -#define AR5416_PCIE_PM_CTRL 0x4014 #define AR_AHB_MODE 0x4024 /* AHB mode for dma */ #define AR_INTR_SYNC_CAUSE_CLR 0x4028 /* clear interrupt */ #define AR_INTR_SYNC_CAUSE 0x4028 /* check pending interrupts */ @@ -42,8 +41,15 @@ #define AR_INTR_ASYNC_ENABLE 0x403c /* enable interrupts */ #define AR5416_PCIE_SERDES 0x4040 #define AR5416_PCIE_SERDES2 0x4044 -#define AR_GPIO_IN 0x4048 /* GPIO input register */ -#define AR_GPIO_INTR_OUT 0x404c /* GPIO output register */ +#define AR_GPIO_IN_OUT 0x4048 /* GPIO input/output register */ +#define AR_GPIO_OE_OUT 0x404c /* GPIO output enable register */ +#define AR_GPIO_INTR_POL 0x4050 /* GPIO interrupt polarity */ +#define AR_GPIO_INPUT_EN_VAL 0x4054 /* GPIO input enable and value */ +#define AR_GPIO_INPUT_MUX1 0x4058 +#define AR_GPIO_INPUT_MUX2 0x405c +#define AR_GPIO_OUTPUT_MUX1 0x4060 +#define AR_GPIO_OUTPUT_MUX2 0x4064 +#define AR_GPIO_OUTPUT_MUX3 0x4068 #define AR_EEPROM_STATUS_DATA 0x407c #define AR_OBS 0x4080 #define AR_RTC_RC 0x7000 /* reset control */ @@ -258,6 +264,21 @@ AR_INTR_SYNC_RADM_CPL_TIMEOUT | AR_INTR_SYNC_LOCAL_TIMEOUT | \ AR_INTR_SYNC_MAC_SLEEP_ACCESS) +#define AR_INTR_SYNC_MASK_GPIO 0xFFFC0000 +#define AR_INTR_SYNC_MASK_GPIO_S 18 + +#define AR_INTR_SYNC_ENABLE_GPIO 0xFFFC0000 +#define AR_INTR_SYNC_ENABLE_GPIO_S 18 + +#define AR_INTR_ASYNC_MASK_GPIO 0xFFFC0000 /* async int mask */ +#define AR_INTR_ASYNC_MASK_GPIO_S 18 + +#define AR_INTR_ASYNC_CAUSE_GPIO 0xFFFC0000 /* GPIO interrupts */ +#define AR_INTR_ASYNC_USED (AR_INTR_MAC_IRQ | AR_INTR_ASYNC_CAUSE_GPIO) + +#define AR_INTR_ASYNC_ENABLE_GPIO 0xFFFC0000 /* enable interrupts */ +#define AR_INTR_ASYNC_ENABLE_GPIO_S 18 + /* RTC registers */ #define AR_RTC_RC_M 0x00000003 #define AR_RTC_RC_MAC_WARM 0x00000001 @@ -418,6 +439,22 @@ #define AR_GPIO_INTR_CTRL 0x3FF00000 #define AR_GPIO_INTR_CTRL_S 20 +#define AR_GPIO_IN_VAL 0x0FFFC000 /* pre-9280 */ +#define AR_GPIO_IN_VAL_S 14 +#define AR928X_GPIO_IN_VAL 0x000FFC00 +#define AR928X_GPIO_IN_VAL_S 10 +#define AR9285_GPIO_IN_VAL 0x00FFF000 +#define AR9285_GPIO_IN_VAL_S 12 + +#define AR_GPIO_OE_OUT_DRV 0x3 /* 2 bit mask shifted by 2*bitpos */ +#define AR_GPIO_OE_OUT_DRV_NO 0x0 /* tristate */ +#define AR_GPIO_OE_OUT_DRV_LOW 0x1 /* drive if low */ +#define AR_GPIO_OE_OUT_DRV_HI 0x2 /* drive if high */ +#define AR_GPIO_OE_OUT_DRV_ALL 0x3 /* drive always */ + +#define AR_GPIO_INTR_POL_VAL 0x1FFF +#define AR_GPIO_INTR_POL_VAL_S 0 + #define AR_2040_JOINED_RX_CLEAR 0x00000001 /* use ctl + ext rx_clear for cca */ #define AR_PCU_TXBUF_CTRL_SIZE_MASK 0x7FF
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200902240033.n1O0X8FE045560>