Path: blob/main/sys/dev/ath/ath_hal/ar5416/ar5416_gpio.c
39566 views
/*-1* SPDX-License-Identifier: ISC2*3* Copyright (c) 2002-2009 Sam Leffler, Errno Consulting4* Copyright (c) 2002-2008 Atheros Communications, Inc.5*6* Permission to use, copy, modify, and/or distribute this software for any7* purpose with or without fee is hereby granted, provided that the above8* copyright notice and this permission notice appear in all copies.9*10* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES11* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF12* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR13* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES14* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN15* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF16* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.17*/18#include "opt_ah.h"1920#include "ah.h"21#include "ah_internal.h"22#include "ah_devid.h"2324#include "ar5416/ar5416.h"25#include "ar5416/ar5416reg.h"26#include "ar5416/ar5416phy.h"2728#define AR_GPIO_BIT(_gpio) (1 << _gpio)2930/*31* Configure GPIO Output Mux control32*/33static void34cfgOutputMux(struct ath_hal *ah, uint32_t gpio, uint32_t type)35{36int addr;37uint32_t gpio_shift, tmp;3839HALDEBUG(ah, HAL_DEBUG_GPIO, "%s: gpio=%d, type=%d\n",40__func__, gpio, type);4142/* each MUX controls 6 GPIO pins */43if (gpio > 11)44addr = AR_GPIO_OUTPUT_MUX3;45else if (gpio > 5)46addr = AR_GPIO_OUTPUT_MUX2;47else48addr = AR_GPIO_OUTPUT_MUX1;4950/*51* 5 bits per GPIO pin. Bits 0..4 for 1st pin in that mux,52* bits 5..9 for 2nd pin, etc.53*/54gpio_shift = (gpio % 6) * 5;5556/*57* From Owl to Merlin 1.0, the value read from MUX1 bit 4 to bit58* 9 are wrong. Here is hardware's coding:59* PRDATA[4:0] <= gpio_output_mux[0];60* PRDATA[9:4] <= gpio_output_mux[1];61* <==== Bit 4 is used by both gpio_output_mux[0] [1].62* Currently the max value for gpio_output_mux[] is 6. So bit 463* will never be used. So it should be fine that bit 4 won't be64* able to recover.65*/66if (AR_SREV_MERLIN_20_OR_LATER(ah) ||67(addr != AR_GPIO_OUTPUT_MUX1)) {68OS_REG_RMW(ah, addr, (type << gpio_shift),69(0x1f << gpio_shift));70} else {71tmp = OS_REG_READ(ah, addr);72tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0);73tmp &= ~(0x1f << gpio_shift);74tmp |= type << gpio_shift;75OS_REG_WRITE(ah, addr, tmp);76}77}7879/*80* Configure GPIO Output lines81*/82HAL_BOOL83ar5416GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type)84{85uint32_t gpio_shift, reg;8687#define N(a) (sizeof(a) / sizeof(a[0]))8889HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);9091/*92* This table maps the HAL GPIO pins to the actual hardware93* values.94*/95static const u_int32_t MuxSignalConversionTable[] = {96AR_GPIO_OUTPUT_MUX_AS_OUTPUT,97AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED,98AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED,99AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED,100AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED,101AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL,102AR_GPIO_OUTPUT_MUX_AS_TX_FRAME,103};104105HALDEBUG(ah, HAL_DEBUG_GPIO,106"%s: gpio=%d, type=%d\n", __func__, gpio, type);107108/*109* Convert HAL signal type definitions to hardware-specific values.110*/111if (type >= N(MuxSignalConversionTable)) {112ath_hal_printf(ah, "%s: mux %d is invalid!\n",113__func__,114type);115return AH_FALSE;116}117cfgOutputMux(ah, gpio, MuxSignalConversionTable[type]);118119/* 2 bits per output mode */120gpio_shift = gpio << 1;121122/* Always drive, rather than tristate/drive low/drive high */123reg = OS_REG_READ(ah, AR_GPIO_OE_OUT);124reg &= ~(AR_GPIO_OE_OUT_DRV << gpio_shift);125reg |= AR_GPIO_OE_OUT_DRV_ALL << gpio_shift;126OS_REG_WRITE(ah, AR_GPIO_OE_OUT, reg);127128return AH_TRUE;129#undef N130}131132/*133* Configure GPIO Input lines134*/135HAL_BOOL136ar5416GpioCfgInput(struct ath_hal *ah, uint32_t gpio)137{138uint32_t gpio_shift, reg;139140HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);141142HALDEBUG(ah, HAL_DEBUG_GPIO, "%s: gpio=%d\n", __func__, gpio);143144/* TODO: configure input mux for AR5416 */145/* If configured as input, set output to tristate */146gpio_shift = gpio << 1;147148reg = OS_REG_READ(ah, AR_GPIO_OE_OUT);149reg &= ~(AR_GPIO_OE_OUT_DRV << gpio_shift);150reg |= AR_GPIO_OE_OUT_DRV_ALL << gpio_shift;151OS_REG_WRITE(ah, AR_GPIO_OE_OUT, reg);152153return AH_TRUE;154}155156/*157* Once configured for I/O - set output lines158*/159HAL_BOOL160ar5416GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val)161{162uint32_t reg;163164HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);165HALDEBUG(ah, HAL_DEBUG_GPIO,166"%s: gpio=%d, val=%d\n", __func__, gpio, val);167168reg = OS_REG_READ(ah, AR_GPIO_IN_OUT);169if (val & 1)170reg |= AR_GPIO_BIT(gpio);171else172reg &= ~AR_GPIO_BIT(gpio);173OS_REG_WRITE(ah, AR_GPIO_IN_OUT, reg);174return AH_TRUE;175}176177/*178* Once configured for I/O - get input lines179*/180uint32_t181ar5416GpioGet(struct ath_hal *ah, uint32_t gpio)182{183uint32_t bits;184185if (gpio >= AH_PRIVATE(ah)->ah_caps.halNumGpioPins)186return 0xffffffff;187/*188* Read output value for all gpio's, shift it,189* and verify whether the specific bit is set.190*/191if (AR_SREV_KIWI_10_OR_LATER(ah))192bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR9287_GPIO_IN_VAL);193if (AR_SREV_KITE_10_OR_LATER(ah))194bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR9285_GPIO_IN_VAL);195else if (AR_SREV_MERLIN_10_OR_LATER(ah))196bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR928X_GPIO_IN_VAL);197else198bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR_GPIO_IN_VAL);199return ((bits & AR_GPIO_BIT(gpio)) != 0);200}201202/*203* Set the GPIO Interrupt Sync and Async interrupts are both set/cleared.204* Async GPIO interrupts may not be raised when the chip is put to sleep.205*/206void207ar5416GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel)208{209uint32_t val, mask;210211HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);212HALDEBUG(ah, HAL_DEBUG_GPIO,213"%s: gpio=%d, ilevel=%d\n", __func__, gpio, ilevel);214215if (ilevel == HAL_GPIO_INTR_DISABLE) {216val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE),217AR_INTR_ASYNC_ENABLE_GPIO) &~ AR_GPIO_BIT(gpio);218OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_ENABLE,219AR_INTR_ASYNC_ENABLE_GPIO, val);220221mask = MS(OS_REG_READ(ah, AR_INTR_ASYNC_MASK),222AR_INTR_ASYNC_MASK_GPIO) &~ AR_GPIO_BIT(gpio);223OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_MASK,224AR_INTR_ASYNC_MASK_GPIO, mask);225226/* Clear synchronous GPIO interrupt registers and pending interrupt flag */227val = MS(OS_REG_READ(ah, AR_INTR_SYNC_ENABLE),228AR_INTR_SYNC_ENABLE_GPIO) &~ AR_GPIO_BIT(gpio);229OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_ENABLE,230AR_INTR_SYNC_ENABLE_GPIO, val);231232mask = MS(OS_REG_READ(ah, AR_INTR_SYNC_MASK),233AR_INTR_SYNC_MASK_GPIO) &~ AR_GPIO_BIT(gpio);234OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_MASK,235AR_INTR_SYNC_MASK_GPIO, mask);236237val = MS(OS_REG_READ(ah, AR_INTR_SYNC_CAUSE),238AR_INTR_SYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio);239OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_CAUSE,240AR_INTR_SYNC_ENABLE_GPIO, val);241} else {242val = MS(OS_REG_READ(ah, AR_GPIO_INTR_POL),243AR_GPIO_INTR_POL_VAL);244if (ilevel == HAL_GPIO_INTR_HIGH) {245/* 0 == interrupt on pin high */246val &= ~AR_GPIO_BIT(gpio);247} else if (ilevel == HAL_GPIO_INTR_LOW) {248/* 1 == interrupt on pin low */249val |= AR_GPIO_BIT(gpio);250}251OS_REG_RMW_FIELD(ah, AR_GPIO_INTR_POL,252AR_GPIO_INTR_POL_VAL, val);253254/* Change the interrupt mask. */255val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE),256AR_INTR_ASYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio);257OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_ENABLE,258AR_INTR_ASYNC_ENABLE_GPIO, val);259260mask = MS(OS_REG_READ(ah, AR_INTR_ASYNC_MASK),261AR_INTR_ASYNC_MASK_GPIO) | AR_GPIO_BIT(gpio);262OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_MASK,263AR_INTR_ASYNC_MASK_GPIO, mask);264265/* Set synchronous GPIO interrupt registers as well */266val = MS(OS_REG_READ(ah, AR_INTR_SYNC_ENABLE),267AR_INTR_SYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio);268OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_ENABLE,269AR_INTR_SYNC_ENABLE_GPIO, val);270271mask = MS(OS_REG_READ(ah, AR_INTR_SYNC_MASK),272AR_INTR_SYNC_MASK_GPIO) | AR_GPIO_BIT(gpio);273OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_MASK,274AR_INTR_SYNC_MASK_GPIO, mask);275}276AH5416(ah)->ah_gpioMask = mask; /* for ar5416SetInterrupts */277}278279280