linux/arch/arm/mach-pnx4008/gpio.c
<<
>>
Prefs
   1/*
   2 * arch/arm/mach-pnx4008/gpio.c
   3 *
   4 * PNX4008 GPIO driver
   5 *
   6 * Author: Dmitry Chigirev <source@mvista.com>
   7 *
   8 * Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips:
   9 * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
  10 *
  11 * 2005 (c) MontaVista Software, Inc. This file is licensed under
  12 * the terms of the GNU General Public License version 2. This program
  13 * is licensed "as is" without any warranty of any kind, whether express
  14 * or implied.
  15 */
  16
  17#include <linux/types.h>
  18#include <linux/kernel.h>
  19#include <linux/module.h>
  20#include <linux/io.h>
  21#include <mach/hardware.h>
  22#include <mach/platform.h>
  23#include <mach/gpio.h>
  24
  25/* register definitions */
  26#define PIO_VA_BASE     IO_ADDRESS(PNX4008_PIO_BASE)
  27
  28#define PIO_INP_STATE   (0x00U)
  29#define PIO_OUTP_SET    (0x04U)
  30#define PIO_OUTP_CLR    (0x08U)
  31#define PIO_OUTP_STATE  (0x0CU)
  32#define PIO_DRV_SET     (0x10U)
  33#define PIO_DRV_CLR     (0x14U)
  34#define PIO_DRV_STATE   (0x18U)
  35#define PIO_SDINP_STATE (0x1CU)
  36#define PIO_SDOUTP_SET  (0x20U)
  37#define PIO_SDOUTP_CLR  (0x24U)
  38#define PIO_MUX_SET     (0x28U)
  39#define PIO_MUX_CLR     (0x2CU)
  40#define PIO_MUX_STATE   (0x30U)
  41
  42static inline void gpio_lock(void)
  43{
  44        local_irq_disable();
  45}
  46
  47static inline void gpio_unlock(void)
  48{
  49        local_irq_enable();
  50}
  51
  52/* Inline functions */
  53static inline int gpio_read_bit(u32 reg, int gpio)
  54{
  55        u32 bit, val;
  56        int ret = -EFAULT;
  57
  58        if (gpio < 0)
  59                goto out;
  60
  61        bit = GPIO_BIT(gpio);
  62        if (bit) {
  63                val = __raw_readl(PIO_VA_BASE + reg);
  64                ret = (val & bit) ? 1 : 0;
  65        }
  66out:
  67        return ret;
  68}
  69
  70static inline int gpio_set_bit(u32 reg, int gpio)
  71{
  72        u32 bit, val;
  73        int ret = -EFAULT;
  74
  75        if (gpio < 0)
  76                goto out;
  77
  78        bit = GPIO_BIT(gpio);
  79        if (bit) {
  80                val = __raw_readl(PIO_VA_BASE + reg);
  81                val |= bit;
  82                __raw_writel(val, PIO_VA_BASE + reg);
  83                ret = 0;
  84        }
  85out:
  86        return ret;
  87}
  88
  89/* Very simple access control, bitmap for allocated/free */
  90static unsigned long access_map[4];
  91#define INP_INDEX       0
  92#define OUTP_INDEX      1
  93#define GPIO_INDEX      2
  94#define MUX_INDEX       3
  95
  96/*GPIO to Input Mapping */
  97static short gpio_to_inp_map[32] = {
  98        -1, -1, -1, -1, -1, -1, -1, -1,
  99        -1, -1, -1, -1, -1, -1, -1, -1,
 100        -1, -1, -1, -1, -1, -1, -1, -1,
 101        -1, 10, 11, 12, 13, 14, 24, -1
 102};
 103
 104/*GPIO to Mux Mapping */
 105static short gpio_to_mux_map[32] = {
 106        -1, -1, -1, -1, -1, -1, -1, -1,
 107        -1, -1, -1, -1, -1, -1, -1, -1,
 108        -1, -1, -1, -1, -1, -1, -1, -1,
 109        -1, -1, -1, 0, 1, 4, 5, -1
 110};
 111
 112/*Output to Mux Mapping */
 113static short outp_to_mux_map[32] = {
 114        -1, -1, -1, 6, -1, -1, -1, -1,
 115        -1, -1, -1, -1, -1, -1, -1, -1,
 116        -1, -1, -1, -1, -1, 2, -1, -1,
 117        -1, -1, -1, -1, -1, -1, -1, -1
 118};
 119
 120int pnx4008_gpio_register_pin(unsigned short pin)
 121{
 122        unsigned long bit = GPIO_BIT(pin);
 123        int ret = -EBUSY;       /* Already in use */
 124
 125        gpio_lock();
 126
 127        if (GPIO_ISBID(pin)) {
 128                if (access_map[GPIO_INDEX] & bit)
 129                        goto out;
 130                access_map[GPIO_INDEX] |= bit;
 131
 132        } else if (GPIO_ISRAM(pin)) {
 133                if (access_map[GPIO_INDEX] & bit)
 134                        goto out;
 135                access_map[GPIO_INDEX] |= bit;
 136
 137        } else if (GPIO_ISMUX(pin)) {
 138                if (access_map[MUX_INDEX] & bit)
 139                        goto out;
 140                access_map[MUX_INDEX] |= bit;
 141
 142        } else if (GPIO_ISOUT(pin)) {
 143                if (access_map[OUTP_INDEX] & bit)
 144                        goto out;
 145                access_map[OUTP_INDEX] |= bit;
 146
 147        } else if (GPIO_ISIN(pin)) {
 148                if (access_map[INP_INDEX] & bit)
 149                        goto out;
 150                access_map[INP_INDEX] |= bit;
 151        } else
 152                goto out;
 153        ret = 0;
 154
 155out:
 156        gpio_unlock();
 157        return ret;
 158}
 159
 160EXPORT_SYMBOL(pnx4008_gpio_register_pin);
 161
 162int pnx4008_gpio_unregister_pin(unsigned short pin)
 163{
 164        unsigned long bit = GPIO_BIT(pin);
 165        int ret = -EFAULT;      /* Not registered */
 166
 167        gpio_lock();
 168
 169        if (GPIO_ISBID(pin)) {
 170                if (~access_map[GPIO_INDEX] & bit)
 171                        goto out;
 172                access_map[GPIO_INDEX] &= ~bit;
 173        } else if (GPIO_ISRAM(pin)) {
 174                if (~access_map[GPIO_INDEX] & bit)
 175                        goto out;
 176                access_map[GPIO_INDEX] &= ~bit;
 177        } else if (GPIO_ISMUX(pin)) {
 178                if (~access_map[MUX_INDEX] & bit)
 179                        goto out;
 180                access_map[MUX_INDEX] &= ~bit;
 181        } else if (GPIO_ISOUT(pin)) {
 182                if (~access_map[OUTP_INDEX] & bit)
 183                        goto out;
 184                access_map[OUTP_INDEX] &= ~bit;
 185        } else if (GPIO_ISIN(pin)) {
 186                if (~access_map[INP_INDEX] & bit)
 187                        goto out;
 188                access_map[INP_INDEX] &= ~bit;
 189        } else
 190                goto out;
 191        ret = 0;
 192
 193out:
 194        gpio_unlock();
 195        return ret;
 196}
 197
 198EXPORT_SYMBOL(pnx4008_gpio_unregister_pin);
 199
 200unsigned long pnx4008_gpio_read_pin(unsigned short pin)
 201{
 202        unsigned long ret = -EFAULT;
 203        int gpio = GPIO_BIT_MASK(pin);
 204        gpio_lock();
 205        if (GPIO_ISOUT(pin)) {
 206                ret = gpio_read_bit(PIO_OUTP_STATE, gpio);
 207        } else if (GPIO_ISRAM(pin)) {
 208                if (gpio_read_bit(PIO_DRV_STATE, gpio) == 0) {
 209                        ret = gpio_read_bit(PIO_SDINP_STATE, gpio);
 210                }
 211        } else if (GPIO_ISBID(pin)) {
 212                ret = gpio_read_bit(PIO_DRV_STATE, gpio);
 213                if (ret > 0)
 214                        ret = gpio_read_bit(PIO_OUTP_STATE, gpio);
 215                else if (ret == 0)
 216                        ret =
 217                            gpio_read_bit(PIO_INP_STATE, gpio_to_inp_map[gpio]);
 218        } else if (GPIO_ISIN(pin)) {
 219                ret = gpio_read_bit(PIO_INP_STATE, gpio);
 220        }
 221        gpio_unlock();
 222        return ret;
 223}
 224
 225EXPORT_SYMBOL(pnx4008_gpio_read_pin);
 226
 227/* Write Value to output */
 228int pnx4008_gpio_write_pin(unsigned short pin, int output)
 229{
 230        int gpio = GPIO_BIT_MASK(pin);
 231        int ret = -EFAULT;
 232
 233        gpio_lock();
 234        if (GPIO_ISOUT(pin)) {
 235                printk( "writing '%x' to '%x'\n",
 236                                gpio, output ? PIO_OUTP_SET : PIO_OUTP_CLR );
 237                ret = gpio_set_bit(output ? PIO_OUTP_SET : PIO_OUTP_CLR, gpio);
 238        } else if (GPIO_ISRAM(pin)) {
 239                if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0)
 240                        ret = gpio_set_bit(output ? PIO_SDOUTP_SET :
 241                                           PIO_SDOUTP_CLR, gpio);
 242        } else if (GPIO_ISBID(pin)) {
 243                if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0)
 244                        ret = gpio_set_bit(output ? PIO_OUTP_SET :
 245                                           PIO_OUTP_CLR, gpio);
 246        }
 247        gpio_unlock();
 248        return ret;
 249}
 250
 251EXPORT_SYMBOL(pnx4008_gpio_write_pin);
 252
 253/* Value = 1 : Set GPIO pin as output */
 254/* Value = 0 : Set GPIO pin as input */
 255int pnx4008_gpio_set_pin_direction(unsigned short pin, int output)
 256{
 257        int gpio = GPIO_BIT_MASK(pin);
 258        int ret = -EFAULT;
 259
 260        gpio_lock();
 261        if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {
 262                ret = gpio_set_bit(output ? PIO_DRV_SET : PIO_DRV_CLR, gpio);
 263        }
 264        gpio_unlock();
 265        return ret;
 266}
 267
 268EXPORT_SYMBOL(pnx4008_gpio_set_pin_direction);
 269
 270/* Read GPIO pin direction: 0= pin used as input, 1= pin used as output*/
 271int pnx4008_gpio_read_pin_direction(unsigned short pin)
 272{
 273        int gpio = GPIO_BIT_MASK(pin);
 274        int ret = -EFAULT;
 275
 276        gpio_lock();
 277        if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {
 278                ret = gpio_read_bit(PIO_DRV_STATE, gpio);
 279        }
 280        gpio_unlock();
 281        return ret;
 282}
 283
 284EXPORT_SYMBOL(pnx4008_gpio_read_pin_direction);
 285
 286/* Value = 1 : Set pin to muxed function  */
 287/* Value = 0 : Set pin as GPIO */
 288int pnx4008_gpio_set_pin_mux(unsigned short pin, int output)
 289{
 290        int gpio = GPIO_BIT_MASK(pin);
 291        int ret = -EFAULT;
 292
 293        gpio_lock();
 294        if (GPIO_ISBID(pin)) {
 295                ret =
 296                    gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR,
 297                                 gpio_to_mux_map[gpio]);
 298        } else if (GPIO_ISOUT(pin)) {
 299                ret =
 300                    gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR,
 301                                 outp_to_mux_map[gpio]);
 302        } else if (GPIO_ISMUX(pin)) {
 303                ret = gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR, gpio);
 304        }
 305        gpio_unlock();
 306        return ret;
 307}
 308
 309EXPORT_SYMBOL(pnx4008_gpio_set_pin_mux);
 310
 311/* Read pin mux function: 0= pin used as GPIO, 1= pin used for muxed function*/
 312int pnx4008_gpio_read_pin_mux(unsigned short pin)
 313{
 314        int gpio = GPIO_BIT_MASK(pin);
 315        int ret = -EFAULT;
 316
 317        gpio_lock();
 318        if (GPIO_ISBID(pin)) {
 319                ret = gpio_read_bit(PIO_MUX_STATE, gpio_to_mux_map[gpio]);
 320        } else if (GPIO_ISOUT(pin)) {
 321                ret = gpio_read_bit(PIO_MUX_STATE, outp_to_mux_map[gpio]);
 322        } else if (GPIO_ISMUX(pin)) {
 323                ret = gpio_read_bit(PIO_MUX_STATE, gpio);
 324        }
 325        gpio_unlock();
 326        return ret;
 327}
 328
 329EXPORT_SYMBOL(pnx4008_gpio_read_pin_mux);
 330