linux/drivers/gpio/gpio-plat-samsung.c
<<
>>
Prefs
   1/*
   2 * Copyright 2008 Openmoko, Inc.
   3 * Copyright 2008 Simtec Electronics
   4 *      Ben Dooks <ben@simtec.co.uk>
   5 *      http://armlinux.simtec.co.uk/
   6 *
   7 * Copyright (c) 2009 Samsung Electronics Co., Ltd.
   8 *              http://www.samsung.com/
   9 *
  10 * SAMSUNG - GPIOlib support
  11 *
  12 * This program is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License version 2 as
  14 * published by the Free Software Foundation.
  15 */
  16
  17#include <linux/kernel.h>
  18#include <linux/irq.h>
  19#include <linux/io.h>
  20#include <linux/gpio.h>
  21#include <plat/gpio-core.h>
  22#include <plat/gpio-cfg.h>
  23#include <plat/gpio-cfg-helpers.h>
  24
  25#ifndef DEBUG_GPIO
  26#define gpio_dbg(x...) do { } while (0)
  27#else
  28#define gpio_dbg(x...) printk(KERN_DEBUG x)
  29#endif
  30
  31/* The samsung_gpiolib_4bit routines are to control the gpio banks where
  32 * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
  33 * following example:
  34 *
  35 * base + 0x00: Control register, 4 bits per gpio
  36 *              gpio n: 4 bits starting at (4*n)
  37 *              0000 = input, 0001 = output, others mean special-function
  38 * base + 0x04: Data register, 1 bit per gpio
  39 *              bit n: data bit n
  40 *
  41 * Note, since the data register is one bit per gpio and is at base + 0x4
  42 * we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of
  43 * the output.
  44*/
  45
  46static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
  47                                      unsigned int offset)
  48{
  49        struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
  50        void __iomem *base = ourchip->base;
  51        unsigned long con;
  52
  53        con = __raw_readl(base + GPIOCON_OFF);
  54        con &= ~(0xf << con_4bit_shift(offset));
  55        __raw_writel(con, base + GPIOCON_OFF);
  56
  57        gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
  58
  59        return 0;
  60}
  61
  62static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
  63                                       unsigned int offset, int value)
  64{
  65        struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
  66        void __iomem *base = ourchip->base;
  67        unsigned long con;
  68        unsigned long dat;
  69
  70        con = __raw_readl(base + GPIOCON_OFF);
  71        con &= ~(0xf << con_4bit_shift(offset));
  72        con |= 0x1 << con_4bit_shift(offset);
  73
  74        dat = __raw_readl(base + GPIODAT_OFF);
  75
  76        if (value)
  77                dat |= 1 << offset;
  78        else
  79                dat &= ~(1 << offset);
  80
  81        __raw_writel(dat, base + GPIODAT_OFF);
  82        __raw_writel(con, base + GPIOCON_OFF);
  83        __raw_writel(dat, base + GPIODAT_OFF);
  84
  85        gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
  86
  87        return 0;
  88}
  89
  90/* The next set of routines are for the case where the GPIO configuration
  91 * registers are 4 bits per GPIO but there is more than one register (the
  92 * bank has more than 8 GPIOs.
  93 *
  94 * This case is the similar to the 4 bit case, but the registers are as
  95 * follows:
  96 *
  97 * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
  98 *              gpio n: 4 bits starting at (4*n)
  99 *              0000 = input, 0001 = output, others mean special-function
 100 * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
 101 *              gpio n: 4 bits starting at (4*n)
 102 *              0000 = input, 0001 = output, others mean special-function
 103 * base + 0x08: Data register, 1 bit per gpio
 104 *              bit n: data bit n
 105 *
 106 * To allow us to use the s3c_gpiolib_get and s3c_gpiolib_set routines we
 107 * store the 'base + 0x4' address so that these routines see the data
 108 * register at ourchip->base + 0x04.
 109 */
 110
 111static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
 112                                       unsigned int offset)
 113{
 114        struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
 115        void __iomem *base = ourchip->base;
 116        void __iomem *regcon = base;
 117        unsigned long con;
 118
 119        if (offset > 7)
 120                offset -= 8;
 121        else
 122                regcon -= 4;
 123
 124        con = __raw_readl(regcon);
 125        con &= ~(0xf << con_4bit_shift(offset));
 126        __raw_writel(con, regcon);
 127
 128        gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
 129
 130        return 0;
 131}
 132
 133static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
 134                                        unsigned int offset, int value)
 135{
 136        struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
 137        void __iomem *base = ourchip->base;
 138        void __iomem *regcon = base;
 139        unsigned long con;
 140        unsigned long dat;
 141        unsigned con_offset = offset;
 142
 143        if (con_offset > 7)
 144                con_offset -= 8;
 145        else
 146                regcon -= 4;
 147
 148        con = __raw_readl(regcon);
 149        con &= ~(0xf << con_4bit_shift(con_offset));
 150        con |= 0x1 << con_4bit_shift(con_offset);
 151
 152        dat = __raw_readl(base + GPIODAT_OFF);
 153
 154        if (value)
 155                dat |= 1 << offset;
 156        else
 157                dat &= ~(1 << offset);
 158
 159        __raw_writel(dat, base + GPIODAT_OFF);
 160        __raw_writel(con, regcon);
 161        __raw_writel(dat, base + GPIODAT_OFF);
 162
 163        gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
 164
 165        return 0;
 166}
 167
 168void __init samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
 169{
 170        chip->chip.direction_input = samsung_gpiolib_4bit_input;
 171        chip->chip.direction_output = samsung_gpiolib_4bit_output;
 172        chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
 173}
 174
 175void __init samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
 176{
 177        chip->chip.direction_input = samsung_gpiolib_4bit2_input;
 178        chip->chip.direction_output = samsung_gpiolib_4bit2_output;
 179        chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
 180}
 181
 182void __init samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
 183                                           int nr_chips)
 184{
 185        for (; nr_chips > 0; nr_chips--, chip++) {
 186                samsung_gpiolib_add_4bit(chip);
 187                s3c_gpiolib_add(chip);
 188        }
 189}
 190
 191void __init samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
 192                                            int nr_chips)
 193{
 194        for (; nr_chips > 0; nr_chips--, chip++) {
 195                samsung_gpiolib_add_4bit2(chip);
 196                s3c_gpiolib_add(chip);
 197        }
 198}
 199
 200void __init samsung_gpiolib_add_2bit_chips(struct s3c_gpio_chip *chip,
 201                                           int nr_chips)
 202{
 203        for (; nr_chips > 0; nr_chips--, chip++)
 204                s3c_gpiolib_add(chip);
 205}
 206