The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ath/ath_hal/ar5416/ar5416_gpio.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: ISC
    3  *
    4  * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
    5  * Copyright (c) 2002-2008 Atheros Communications, Inc.
    6  *
    7  * Permission to use, copy, modify, and/or distribute this software for any
    8  * purpose with or without fee is hereby granted, provided that the above
    9  * copyright notice and this permission notice appear in all copies.
   10  *
   11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   18  *
   19  * $FreeBSD$
   20  */
   21 #include "opt_ah.h"
   22 
   23 #include "ah.h"
   24 #include "ah_internal.h"
   25 #include "ah_devid.h"
   26 
   27 #include "ar5416/ar5416.h"
   28 #include "ar5416/ar5416reg.h"
   29 #include "ar5416/ar5416phy.h"
   30 
   31 #define AR_GPIO_BIT(_gpio)      (1 << _gpio)
   32 
   33 /*
   34  * Configure GPIO Output Mux control
   35  */
   36 static void
   37 cfgOutputMux(struct ath_hal *ah, uint32_t gpio, uint32_t type)
   38 {
   39         int addr;
   40         uint32_t gpio_shift, tmp;
   41 
   42         HALDEBUG(ah, HAL_DEBUG_GPIO, "%s: gpio=%d, type=%d\n",
   43             __func__, gpio, type);
   44 
   45         /* each MUX controls 6 GPIO pins */
   46         if (gpio > 11)
   47                 addr = AR_GPIO_OUTPUT_MUX3;
   48         else if (gpio > 5)
   49                 addr = AR_GPIO_OUTPUT_MUX2;
   50         else
   51                 addr = AR_GPIO_OUTPUT_MUX1;
   52 
   53         /*
   54          * 5 bits per GPIO pin. Bits 0..4 for 1st pin in that mux,
   55          * bits 5..9 for 2nd pin, etc.
   56          */
   57         gpio_shift = (gpio % 6) * 5;
   58 
   59         /*
   60          * From Owl to Merlin 1.0, the value read from MUX1 bit 4 to bit
   61          * 9 are wrong.  Here is hardware's coding:
   62          * PRDATA[4:0] <= gpio_output_mux[0];
   63          * PRDATA[9:4] <= gpio_output_mux[1];
   64          *      <==== Bit 4 is used by both gpio_output_mux[0] [1].
   65          * Currently the max value for gpio_output_mux[] is 6. So bit 4
   66          * will never be used.  So it should be fine that bit 4 won't be
   67          * able to recover.
   68          */
   69         if (AR_SREV_MERLIN_20_OR_LATER(ah) ||
   70             (addr != AR_GPIO_OUTPUT_MUX1)) {
   71                 OS_REG_RMW(ah, addr, (type << gpio_shift),
   72                     (0x1f << gpio_shift));
   73         } else {
   74                 tmp = OS_REG_READ(ah, addr);
   75                 tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0);
   76                 tmp &= ~(0x1f << gpio_shift);
   77                 tmp |= type << gpio_shift;
   78                 OS_REG_WRITE(ah, addr, tmp);
   79         }
   80 }
   81 
   82 /*
   83  * Configure GPIO Output lines
   84  */
   85 HAL_BOOL
   86 ar5416GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type)
   87 {
   88         uint32_t gpio_shift, reg;
   89 
   90 #define N(a)    (sizeof(a) / sizeof(a[0]))
   91 
   92         HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
   93 
   94         /*
   95          * This table maps the HAL GPIO pins to the actual hardware
   96          * values.
   97          */
   98         static const u_int32_t MuxSignalConversionTable[] = {
   99                 AR_GPIO_OUTPUT_MUX_AS_OUTPUT,
  100                 AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED,
  101                 AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED,
  102                 AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED,
  103                 AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED,
  104                 AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL,
  105                 AR_GPIO_OUTPUT_MUX_AS_TX_FRAME,
  106         };
  107 
  108         HALDEBUG(ah, HAL_DEBUG_GPIO,
  109             "%s: gpio=%d, type=%d\n", __func__, gpio, type);
  110 
  111         /*
  112          * Convert HAL signal type definitions to hardware-specific values.
  113          */
  114         if (type >= N(MuxSignalConversionTable)) {
  115                 ath_hal_printf(ah, "%s: mux %d is invalid!\n",
  116                     __func__,
  117                     type);
  118                 return AH_FALSE;
  119         }
  120         cfgOutputMux(ah, gpio, MuxSignalConversionTable[type]);
  121 
  122         /* 2 bits per output mode */
  123         gpio_shift = gpio << 1;
  124 
  125         /* Always drive, rather than tristate/drive low/drive high */
  126         reg = OS_REG_READ(ah, AR_GPIO_OE_OUT);
  127         reg &= ~(AR_GPIO_OE_OUT_DRV << gpio_shift);
  128         reg |= AR_GPIO_OE_OUT_DRV_ALL << gpio_shift;
  129         OS_REG_WRITE(ah, AR_GPIO_OE_OUT, reg);
  130 
  131         return AH_TRUE;
  132 #undef  N
  133 }
  134 
  135 /*
  136  * Configure GPIO Input lines
  137  */
  138 HAL_BOOL
  139 ar5416GpioCfgInput(struct ath_hal *ah, uint32_t gpio)
  140 {
  141         uint32_t gpio_shift, reg;
  142 
  143         HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
  144 
  145         HALDEBUG(ah, HAL_DEBUG_GPIO, "%s: gpio=%d\n", __func__, gpio);
  146 
  147         /* TODO: configure input mux for AR5416 */
  148         /* If configured as input, set output to tristate */
  149         gpio_shift = gpio << 1;
  150 
  151         reg = OS_REG_READ(ah, AR_GPIO_OE_OUT);
  152         reg &= ~(AR_GPIO_OE_OUT_DRV << gpio_shift);
  153         reg |= AR_GPIO_OE_OUT_DRV_ALL << gpio_shift;
  154         OS_REG_WRITE(ah, AR_GPIO_OE_OUT, reg);
  155 
  156         return AH_TRUE;
  157 }
  158 
  159 /*
  160  * Once configured for I/O - set output lines
  161  */
  162 HAL_BOOL
  163 ar5416GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val)
  164 {
  165         uint32_t reg;
  166 
  167         HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
  168         HALDEBUG(ah, HAL_DEBUG_GPIO,
  169            "%s: gpio=%d, val=%d\n", __func__, gpio, val);
  170 
  171         reg = OS_REG_READ(ah, AR_GPIO_IN_OUT);
  172         if (val & 1)
  173                 reg |= AR_GPIO_BIT(gpio);
  174         else 
  175                 reg &= ~AR_GPIO_BIT(gpio);
  176         OS_REG_WRITE(ah, AR_GPIO_IN_OUT, reg);  
  177         return AH_TRUE;
  178 }
  179 
  180 /*
  181  * Once configured for I/O - get input lines
  182  */
  183 uint32_t
  184 ar5416GpioGet(struct ath_hal *ah, uint32_t gpio)
  185 {
  186         uint32_t bits;
  187 
  188         if (gpio >= AH_PRIVATE(ah)->ah_caps.halNumGpioPins)
  189                 return 0xffffffff;
  190         /*
  191          * Read output value for all gpio's, shift it,
  192          * and verify whether the specific bit is set.
  193          */
  194         if (AR_SREV_KIWI_10_OR_LATER(ah))
  195                 bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR9287_GPIO_IN_VAL);
  196         if (AR_SREV_KITE_10_OR_LATER(ah))
  197                 bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR9285_GPIO_IN_VAL);
  198         else if (AR_SREV_MERLIN_10_OR_LATER(ah))
  199                 bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR928X_GPIO_IN_VAL);
  200         else
  201                 bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR_GPIO_IN_VAL);
  202         return ((bits & AR_GPIO_BIT(gpio)) != 0);
  203 }
  204 
  205 /*
  206  * Set the GPIO Interrupt Sync and Async interrupts are both set/cleared.
  207  * Async GPIO interrupts may not be raised when the chip is put to sleep.
  208  */
  209 void
  210 ar5416GpioSetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel)
  211 {
  212         uint32_t val, mask;
  213 
  214         HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins);
  215         HALDEBUG(ah, HAL_DEBUG_GPIO,
  216             "%s: gpio=%d, ilevel=%d\n", __func__, gpio, ilevel);
  217 
  218         if (ilevel == HAL_GPIO_INTR_DISABLE) {
  219                 val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE),
  220                          AR_INTR_ASYNC_ENABLE_GPIO) &~ AR_GPIO_BIT(gpio);
  221                 OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_ENABLE,
  222                     AR_INTR_ASYNC_ENABLE_GPIO, val);
  223 
  224                 mask = MS(OS_REG_READ(ah, AR_INTR_ASYNC_MASK),
  225                           AR_INTR_ASYNC_MASK_GPIO) &~ AR_GPIO_BIT(gpio);
  226                 OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_MASK,
  227                     AR_INTR_ASYNC_MASK_GPIO, mask);
  228 
  229                 /* Clear synchronous GPIO interrupt registers and pending interrupt flag */
  230                 val = MS(OS_REG_READ(ah, AR_INTR_SYNC_ENABLE),
  231                          AR_INTR_SYNC_ENABLE_GPIO) &~ AR_GPIO_BIT(gpio);
  232                 OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_ENABLE,
  233                     AR_INTR_SYNC_ENABLE_GPIO, val);
  234 
  235                 mask = MS(OS_REG_READ(ah, AR_INTR_SYNC_MASK),
  236                           AR_INTR_SYNC_MASK_GPIO) &~ AR_GPIO_BIT(gpio);
  237                 OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_MASK,
  238                     AR_INTR_SYNC_MASK_GPIO, mask);
  239 
  240                 val = MS(OS_REG_READ(ah, AR_INTR_SYNC_CAUSE),
  241                          AR_INTR_SYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio);
  242                 OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_CAUSE,
  243                     AR_INTR_SYNC_ENABLE_GPIO, val);
  244         } else {
  245                 val = MS(OS_REG_READ(ah, AR_GPIO_INTR_POL),
  246                          AR_GPIO_INTR_POL_VAL);
  247                 if (ilevel == HAL_GPIO_INTR_HIGH) {
  248                         /* 0 == interrupt on pin high */
  249                         val &= ~AR_GPIO_BIT(gpio);
  250                 } else if (ilevel == HAL_GPIO_INTR_LOW) {
  251                         /* 1 == interrupt on pin low */
  252                         val |= AR_GPIO_BIT(gpio);
  253                 }
  254                 OS_REG_RMW_FIELD(ah, AR_GPIO_INTR_POL,
  255                     AR_GPIO_INTR_POL_VAL, val);
  256 
  257                 /* Change the interrupt mask. */
  258                 val = MS(OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE),
  259                          AR_INTR_ASYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio);
  260                 OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_ENABLE,
  261                     AR_INTR_ASYNC_ENABLE_GPIO, val);
  262 
  263                 mask = MS(OS_REG_READ(ah, AR_INTR_ASYNC_MASK),
  264                           AR_INTR_ASYNC_MASK_GPIO) | AR_GPIO_BIT(gpio);
  265                 OS_REG_RMW_FIELD(ah, AR_INTR_ASYNC_MASK,
  266                     AR_INTR_ASYNC_MASK_GPIO, mask);
  267 
  268                 /* Set synchronous GPIO interrupt registers as well */
  269                 val = MS(OS_REG_READ(ah, AR_INTR_SYNC_ENABLE),
  270                          AR_INTR_SYNC_ENABLE_GPIO) | AR_GPIO_BIT(gpio);
  271                 OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_ENABLE,
  272                     AR_INTR_SYNC_ENABLE_GPIO, val);
  273 
  274                 mask = MS(OS_REG_READ(ah, AR_INTR_SYNC_MASK),
  275                           AR_INTR_SYNC_MASK_GPIO) | AR_GPIO_BIT(gpio);
  276                 OS_REG_RMW_FIELD(ah, AR_INTR_SYNC_MASK,
  277                     AR_INTR_SYNC_MASK_GPIO, mask);
  278         }
  279         AH5416(ah)->ah_gpioMask = mask;         /* for ar5416SetInterrupts */
  280 }

Cache object: 473614565c73017cef5faeb29813515d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.