linux/arch/mips/include/asm/mach-pmcs-msp71xx/msp_gpio_macros.h
<<
>>
Prefs
   1/*
   2 *
   3 * Macros for external SMP-safe access to the PMC MSP71xx reference
   4 * board GPIO pins
   5 *
   6 * Copyright 2010 PMC-Sierra, Inc.
   7 *
   8 *  This program is free software; you can redistribute  it and/or modify it
   9 *  under  the terms of  the GNU General  Public License as published by the
  10 *  Free Software Foundation;  either version 2 of the  License, or (at your
  11 *  option) any later version.
  12 *
  13 *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
  14 *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
  15 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
  16 *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
  17 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  18 *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
  19 *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  20 *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
  21 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  22 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23 *
  24 *  You should have received a copy of the  GNU General Public License along
  25 *  with this program; if not, write  to the Free Software Foundation, Inc.,
  26 *  675 Mass Ave, Cambridge, MA 02139, USA.
  27 */
  28
  29#ifndef __MSP_GPIO_MACROS_H__
  30#define __MSP_GPIO_MACROS_H__
  31
  32#include <msp_regops.h>
  33#include <msp_regs.h>
  34
  35#ifdef CONFIG_PMC_MSP7120_GW
  36#define MSP_NUM_GPIOS           20
  37#else
  38#define MSP_NUM_GPIOS           28
  39#endif
  40
  41/* -- GPIO Enumerations -- */
  42enum msp_gpio_data {
  43        MSP_GPIO_LO = 0,
  44        MSP_GPIO_HI = 1,
  45        MSP_GPIO_NONE,          /* Special - Means pin is out of range */
  46        MSP_GPIO_TOGGLE,        /* Special - Sets pin to opposite */
  47};
  48
  49enum msp_gpio_mode {
  50        MSP_GPIO_INPUT          = 0x0,
  51        /* MSP_GPIO_ INTERRUPT  = 0x1,  Not supported yet */
  52        MSP_GPIO_UART_INPUT     = 0x2,  /* Only GPIO 4 or 5 */
  53        MSP_GPIO_OUTPUT         = 0x8,
  54        MSP_GPIO_UART_OUTPUT    = 0x9,  /* Only GPIO 2 or 3 */
  55        MSP_GPIO_PERIF_TIMERA   = 0x9,  /* Only GPIO 0 or 1 */
  56        MSP_GPIO_PERIF_TIMERB   = 0xa,  /* Only GPIO 0 or 1 */
  57        MSP_GPIO_UNKNOWN        = 0xb,  /* No such GPIO or mode */
  58};
  59
  60/* -- Static Tables -- */
  61
  62/* Maps pins to data register */
  63static volatile u32 * const MSP_GPIO_DATA_REGISTER[] = {
  64        /* GPIO 0 and 1 on the first register */
  65        GPIO_DATA1_REG, GPIO_DATA1_REG,
  66        /* GPIO 2, 3, 4, and 5 on the second register */
  67        GPIO_DATA2_REG, GPIO_DATA2_REG, GPIO_DATA2_REG, GPIO_DATA2_REG,
  68        /* GPIO 6, 7, 8, and 9 on the third register */
  69        GPIO_DATA3_REG, GPIO_DATA3_REG, GPIO_DATA3_REG, GPIO_DATA3_REG,
  70        /* GPIO 10, 11, 12, 13, 14, and 15 on the fourth register */
  71        GPIO_DATA4_REG, GPIO_DATA4_REG, GPIO_DATA4_REG, GPIO_DATA4_REG,
  72        GPIO_DATA4_REG, GPIO_DATA4_REG,
  73        /* GPIO 16 - 23 on the first strange EXTENDED register */
  74        EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG,
  75        EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG,
  76        EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG,
  77        /* GPIO 24 - 27 on the second strange EXTENDED register */
  78        EXTENDED_GPIO2_REG, EXTENDED_GPIO2_REG, EXTENDED_GPIO2_REG,
  79        EXTENDED_GPIO2_REG,
  80};
  81
  82/* Maps pins to mode register */
  83static volatile u32 * const MSP_GPIO_MODE_REGISTER[] = {
  84        /* GPIO 0 and 1 on the first register */
  85        GPIO_CFG1_REG, GPIO_CFG1_REG,
  86        /* GPIO 2, 3, 4, and 5 on the second register */
  87        GPIO_CFG2_REG, GPIO_CFG2_REG, GPIO_CFG2_REG, GPIO_CFG2_REG,
  88        /* GPIO 6, 7, 8, and 9 on the third register */
  89        GPIO_CFG3_REG, GPIO_CFG3_REG, GPIO_CFG3_REG, GPIO_CFG3_REG,
  90        /* GPIO 10, 11, 12, 13, 14, and 15 on the fourth register */
  91        GPIO_CFG4_REG, GPIO_CFG4_REG, GPIO_CFG4_REG, GPIO_CFG4_REG,
  92        GPIO_CFG4_REG, GPIO_CFG4_REG,
  93        /* GPIO 16 - 23 on the first strange EXTENDED register */
  94        EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG,
  95        EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG,
  96        EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG,
  97        /* GPIO 24 - 27 on the second strange EXTENDED register */
  98        EXTENDED_GPIO2_REG, EXTENDED_GPIO2_REG, EXTENDED_GPIO2_REG,
  99        EXTENDED_GPIO2_REG,
 100};
 101
 102/* Maps 'basic' pins to relative offset from 0 per register */
 103static int MSP_GPIO_OFFSET[] = {
 104        /* GPIO 0 and 1 on the first register */
 105        0, 0,
 106        /* GPIO 2, 3, 4, and 5 on the second register */
 107        2, 2, 2, 2,
 108        /* GPIO 6, 7, 8, and 9 on the third register */
 109        6, 6, 6, 6,
 110        /* GPIO 10, 11, 12, 13, 14, and 15 on the fourth register */
 111        10, 10, 10, 10, 10, 10,
 112};
 113
 114/* Maps MODE to allowed pin mask */
 115static unsigned int MSP_GPIO_MODE_ALLOWED[] = {
 116        0xffffffff,     /* Mode 0 - INPUT */
 117        0x00000,        /* Mode 1 - INTERRUPT */
 118        0x00030,        /* Mode 2 - UART_INPUT (GPIO 4, 5)*/
 119        0, 0, 0, 0, 0,  /* Modes 3, 4, 5, 6, and 7 are reserved */
 120        0xffffffff,     /* Mode 8 - OUTPUT */
 121        0x0000f,        /* Mode 9 - UART_OUTPUT/
 122                                PERF_TIMERA (GPIO 0, 1, 2, 3) */
 123        0x00003,        /* Mode a - PERF_TIMERB (GPIO 0, 1) */
 124        0x00000,        /* Mode b - Not really a mode! */
 125};
 126
 127/* -- Bit masks -- */
 128
 129/* This gives you the 'register relative offset gpio' number */
 130#define OFFSET_GPIO_NUMBER(gpio)        (gpio - MSP_GPIO_OFFSET[gpio])
 131
 132/* These take the 'register relative offset gpio' number */
 133#define BASIC_DATA_REG_MASK(ogpio)              (1 << ogpio)
 134#define BASIC_MODE_REG_VALUE(mode, ogpio)       \
 135        (mode << BASIC_MODE_REG_SHIFT(ogpio))
 136#define BASIC_MODE_REG_MASK(ogpio)              \
 137        BASIC_MODE_REG_VALUE(0xf, ogpio)
 138#define BASIC_MODE_REG_SHIFT(ogpio)             (ogpio * 4)
 139#define BASIC_MODE_REG_FROM_REG(data, ogpio)    \
 140        ((data & BASIC_MODE_REG_MASK(ogpio)) >> BASIC_MODE_REG_SHIFT(ogpio))
 141
 142/* These take the actual GPIO number (0 through 15) */
 143#define BASIC_DATA_MASK(gpio)   \
 144        BASIC_DATA_REG_MASK(OFFSET_GPIO_NUMBER(gpio))
 145#define BASIC_MODE_MASK(gpio)   \
 146        BASIC_MODE_REG_MASK(OFFSET_GPIO_NUMBER(gpio))
 147#define BASIC_MODE(mode, gpio)  \
 148        BASIC_MODE_REG_VALUE(mode, OFFSET_GPIO_NUMBER(gpio))
 149#define BASIC_MODE_SHIFT(gpio)  \
 150        BASIC_MODE_REG_SHIFT(OFFSET_GPIO_NUMBER(gpio))
 151#define BASIC_MODE_FROM_REG(data, gpio) \
 152        BASIC_MODE_REG_FROM_REG(data, OFFSET_GPIO_NUMBER(gpio))
 153
 154/*
 155 * Each extended GPIO register is 32 bits long and is responsible for up to
 156 * eight GPIOs. The least significant 16 bits contain the set and clear bit
 157 * pair for each of the GPIOs. The most significant 16 bits contain the
 158 * disable and enable bit pair for each of the GPIOs. For example, the
 159 * extended GPIO reg for GPIOs 16-23 is as follows:
 160 *
 161 *      31: GPIO23_DISABLE
 162 *      ...
 163 *      19: GPIO17_DISABLE
 164 *      18: GPIO17_ENABLE
 165 *      17: GPIO16_DISABLE
 166 *      16: GPIO16_ENABLE
 167 *      ...
 168 *      3:  GPIO17_SET
 169 *      2:  GPIO17_CLEAR
 170 *      1:  GPIO16_SET
 171 *      0:  GPIO16_CLEAR
 172 */
 173
 174/* This gives the 'register relative offset gpio' number */
 175#define EXTENDED_OFFSET_GPIO(gpio)      (gpio < 24 ? gpio - 16 : gpio - 24)
 176
 177/* These take the 'register relative offset gpio' number */
 178#define EXTENDED_REG_DISABLE(ogpio)     (0x2 << ((ogpio * 2) + 16))
 179#define EXTENDED_REG_ENABLE(ogpio)      (0x1 << ((ogpio * 2) + 16))
 180#define EXTENDED_REG_SET(ogpio)         (0x2 << (ogpio * 2))
 181#define EXTENDED_REG_CLR(ogpio)         (0x1 << (ogpio * 2))
 182
 183/* These take the actual GPIO number (16 through 27) */
 184#define EXTENDED_DISABLE(gpio)  \
 185        EXTENDED_REG_DISABLE(EXTENDED_OFFSET_GPIO(gpio))
 186#define EXTENDED_ENABLE(gpio)   \
 187        EXTENDED_REG_ENABLE(EXTENDED_OFFSET_GPIO(gpio))
 188#define EXTENDED_SET(gpio)      \
 189        EXTENDED_REG_SET(EXTENDED_OFFSET_GPIO(gpio))
 190#define EXTENDED_CLR(gpio)      \
 191        EXTENDED_REG_CLR(EXTENDED_OFFSET_GPIO(gpio))
 192
 193#define EXTENDED_FULL_MASK              (0xffffffff)
 194
 195/* -- API inline-functions -- */
 196
 197/*
 198 * Gets the current value of the specified pin
 199 */
 200static inline enum msp_gpio_data msp_gpio_pin_get(unsigned int gpio)
 201{
 202        u32 pinhi_mask = 0, pinhi_mask2 = 0;
 203
 204        if (gpio >= MSP_NUM_GPIOS)
 205                return MSP_GPIO_NONE;
 206
 207        if (gpio < 16) {
 208                pinhi_mask = BASIC_DATA_MASK(gpio);
 209        } else {
 210                /*
 211                 * Two cases are possible with the EXTENDED register:
 212                 *  - In output mode (ENABLED flag set), check the CLR bit
 213                 *  - In input mode (ENABLED flag not set), check the SET bit
 214                 */
 215                pinhi_mask = EXTENDED_ENABLE(gpio) | EXTENDED_CLR(gpio);
 216                pinhi_mask2 = EXTENDED_SET(gpio);
 217        }
 218        if (((*MSP_GPIO_DATA_REGISTER[gpio] & pinhi_mask) == pinhi_mask) ||
 219            (*MSP_GPIO_DATA_REGISTER[gpio] & pinhi_mask2))
 220                return MSP_GPIO_HI;
 221        else
 222                return MSP_GPIO_LO;
 223}
 224
 225/* Sets the specified pin to the specified value */
 226static inline void msp_gpio_pin_set(enum msp_gpio_data data, unsigned int gpio)
 227{
 228        if (gpio >= MSP_NUM_GPIOS)
 229                return;
 230
 231        if (gpio < 16) {
 232                if (data == MSP_GPIO_TOGGLE)
 233                        toggle_reg32(MSP_GPIO_DATA_REGISTER[gpio],
 234                                        BASIC_DATA_MASK(gpio));
 235                else if (data == MSP_GPIO_HI)
 236                        set_reg32(MSP_GPIO_DATA_REGISTER[gpio],
 237                                        BASIC_DATA_MASK(gpio));
 238                else
 239                        clear_reg32(MSP_GPIO_DATA_REGISTER[gpio],
 240                                        BASIC_DATA_MASK(gpio));
 241        } else {
 242                if (data == MSP_GPIO_TOGGLE) {
 243                        /* Special ugly case:
 244                         *   We have to read the CLR bit.
 245                         *   If set, we write the CLR bit.
 246                         *   If not, we write the SET bit.
 247                         */
 248                        u32 tmpdata;
 249
 250                        custom_read_reg32(MSP_GPIO_DATA_REGISTER[gpio],
 251                                                                tmpdata);
 252                        if (tmpdata & EXTENDED_CLR(gpio))
 253                                tmpdata = EXTENDED_CLR(gpio);
 254                        else
 255                                tmpdata = EXTENDED_SET(gpio);
 256                        custom_write_reg32(MSP_GPIO_DATA_REGISTER[gpio],
 257                                                                tmpdata);
 258                } else {
 259                        u32 newdata;
 260
 261                        if (data == MSP_GPIO_HI)
 262                                newdata = EXTENDED_SET(gpio);
 263                        else
 264                                newdata = EXTENDED_CLR(gpio);
 265                        set_value_reg32(MSP_GPIO_DATA_REGISTER[gpio],
 266                                                EXTENDED_FULL_MASK, newdata);
 267                }
 268        }
 269}
 270
 271/* Sets the specified pin to the specified value */
 272static inline void msp_gpio_pin_hi(unsigned int gpio)
 273{
 274        msp_gpio_pin_set(MSP_GPIO_HI, gpio);
 275}
 276
 277/* Sets the specified pin to the specified value */
 278static inline void msp_gpio_pin_lo(unsigned int gpio)
 279{
 280        msp_gpio_pin_set(MSP_GPIO_LO, gpio);
 281}
 282
 283/* Sets the specified pin to the opposite value */
 284static inline void msp_gpio_pin_toggle(unsigned int gpio)
 285{
 286        msp_gpio_pin_set(MSP_GPIO_TOGGLE, gpio);
 287}
 288
 289/* Gets the mode of the specified pin */
 290static inline enum msp_gpio_mode msp_gpio_pin_get_mode(unsigned int gpio)
 291{
 292        enum msp_gpio_mode retval = MSP_GPIO_UNKNOWN;
 293        uint32_t data;
 294
 295        if (gpio >= MSP_NUM_GPIOS)
 296                return retval;
 297
 298        data = *MSP_GPIO_MODE_REGISTER[gpio];
 299
 300        if (gpio < 16) {
 301                retval = BASIC_MODE_FROM_REG(data, gpio);
 302        } else {
 303                /* Extended pins can only be either INPUT or OUTPUT */
 304                if (data & EXTENDED_ENABLE(gpio))
 305                        retval = MSP_GPIO_OUTPUT;
 306                else
 307                        retval = MSP_GPIO_INPUT;
 308        }
 309
 310        return retval;
 311}
 312
 313/*
 314 * Sets the specified mode on the requested pin
 315 * Returns 0 on success, or -1 if that mode is not allowed on this pin
 316 */
 317static inline int msp_gpio_pin_mode(enum msp_gpio_mode mode, unsigned int gpio)
 318{
 319        u32 modemask, newmode;
 320
 321        if ((1 << gpio) & ~MSP_GPIO_MODE_ALLOWED[mode])
 322                return -1;
 323
 324        if (gpio >= MSP_NUM_GPIOS)
 325                return -1;
 326
 327        if (gpio < 16) {
 328                modemask = BASIC_MODE_MASK(gpio);
 329                newmode =  BASIC_MODE(mode, gpio);
 330        } else {
 331                modemask = EXTENDED_FULL_MASK;
 332                if (mode == MSP_GPIO_INPUT)
 333                        newmode = EXTENDED_DISABLE(gpio);
 334                else
 335                        newmode = EXTENDED_ENABLE(gpio);
 336        }
 337        /* Do the set atomically */
 338        set_value_reg32(MSP_GPIO_MODE_REGISTER[gpio], modemask, newmode);
 339
 340        return 0;
 341}
 342
 343#endif /* __MSP_GPIO_MACROS_H__ */
 344