linux/arch/arm/plat-s3c/gpio.c
<<
>>
Prefs
   1/* linux/arch/arm/plat-s3c/gpio.c
   2 *
   3 * Copyright 2008 Simtec Electronics
   4 *      Ben Dooks <ben@simtec.co.uk>
   5 *      http://armlinux.simtec.co.uk/
   6 *
   7 * S3C series GPIO core
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License version 2 as
  11 * published by the Free Software Foundation.
  12*/
  13
  14#include <linux/kernel.h>
  15#include <linux/init.h>
  16#include <linux/io.h>
  17#include <linux/gpio.h>
  18
  19#include <mach/gpio-core.h>
  20
  21#ifdef CONFIG_S3C_GPIO_TRACK
  22struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
  23
  24static __init void s3c_gpiolib_track(struct s3c_gpio_chip *chip)
  25{
  26        unsigned int gpn;
  27        int i;
  28
  29        gpn = chip->chip.base;
  30        for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
  31                BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
  32                s3c_gpios[gpn] = chip;
  33        }
  34}
  35#endif /* CONFIG_S3C_GPIO_TRACK */
  36
  37/* Default routines for controlling GPIO, based on the original S3C24XX
  38 * GPIO functions which deal with the case where each gpio bank of the
  39 * chip is as following:
  40 *
  41 * base + 0x00: Control register, 2 bits per gpio
  42 *              gpio n: 2 bits starting at (2*n)
  43 *              00 = input, 01 = output, others mean special-function
  44 * base + 0x04: Data register, 1 bit per gpio
  45 *              bit n: data bit n
  46*/
  47
  48static int s3c_gpiolib_input(struct gpio_chip *chip, unsigned offset)
  49{
  50        struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
  51        void __iomem *base = ourchip->base;
  52        unsigned long flags;
  53        unsigned long con;
  54
  55        local_irq_save(flags);
  56
  57        con = __raw_readl(base + 0x00);
  58        con &= ~(3 << (offset * 2));
  59
  60        __raw_writel(con, base + 0x00);
  61
  62        local_irq_restore(flags);
  63        return 0;
  64}
  65
  66static int s3c_gpiolib_output(struct gpio_chip *chip,
  67                              unsigned offset, int value)
  68{
  69        struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
  70        void __iomem *base = ourchip->base;
  71        unsigned long flags;
  72        unsigned long dat;
  73        unsigned long con;
  74
  75        local_irq_save(flags);
  76
  77        dat = __raw_readl(base + 0x04);
  78        dat &= ~(1 << offset);
  79        if (value)
  80                dat |= 1 << offset;
  81        __raw_writel(dat, base + 0x04);
  82
  83        con = __raw_readl(base + 0x00);
  84        con &= ~(3 << (offset * 2));
  85        con |= 1 << (offset * 2);
  86
  87        __raw_writel(con, base + 0x00);
  88        __raw_writel(dat, base + 0x04);
  89
  90        local_irq_restore(flags);
  91        return 0;
  92}
  93
  94static void s3c_gpiolib_set(struct gpio_chip *chip,
  95                            unsigned offset, int value)
  96{
  97        struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
  98        void __iomem *base = ourchip->base;
  99        unsigned long flags;
 100        unsigned long dat;
 101
 102        local_irq_save(flags);
 103
 104        dat = __raw_readl(base + 0x04);
 105        dat &= ~(1 << offset);
 106        if (value)
 107                dat |= 1 << offset;
 108        __raw_writel(dat, base + 0x04);
 109
 110        local_irq_restore(flags);
 111}
 112
 113static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset)
 114{
 115        struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
 116        unsigned long val;
 117
 118        val = __raw_readl(ourchip->base + 0x04);
 119        val >>= offset;
 120        val &= 1;
 121
 122        return val;
 123}
 124
 125__init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
 126{
 127        struct gpio_chip *gc = &chip->chip;
 128        int ret;
 129
 130        BUG_ON(!chip->base);
 131        BUG_ON(!gc->label);
 132        BUG_ON(!gc->ngpio);
 133
 134        if (!gc->direction_input)
 135                gc->direction_input = s3c_gpiolib_input;
 136        if (!gc->direction_output)
 137                gc->direction_output = s3c_gpiolib_output;
 138        if (!gc->set)
 139                gc->set = s3c_gpiolib_set;
 140        if (!gc->get)
 141                gc->get = s3c_gpiolib_get;
 142
 143#ifdef CONFIG_PM
 144        if (chip->pm != NULL) {
 145                if (!chip->pm->save || !chip->pm->resume)
 146                        printk(KERN_ERR "gpio: %s has missing PM functions\n",
 147                               gc->label);
 148        } else
 149                printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
 150#endif
 151
 152        /* gpiochip_add() prints own failure message on error. */
 153        ret = gpiochip_add(gc);
 154        if (ret >= 0)
 155                s3c_gpiolib_track(chip);
 156}
 157
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.