Root/arch/arm/plat-samsung/gpio.c

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#include <linux/spinlock.h>
19
20#include <plat/gpio-core.h>
21
22#ifdef CONFIG_S3C_GPIO_TRACK
23struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
24
25static __init void s3c_gpiolib_track(struct s3c_gpio_chip *chip)
26{
27    unsigned int gpn;
28    int i;
29
30    gpn = chip->chip.base;
31    for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
32        BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
33        s3c_gpios[gpn] = chip;
34    }
35}
36#endif /* CONFIG_S3C_GPIO_TRACK */
37
38/* Default routines for controlling GPIO, based on the original S3C24XX
39 * GPIO functions which deal with the case where each gpio bank of the
40 * chip is as following:
41 *
42 * base + 0x00: Control register, 2 bits per gpio
43 * gpio n: 2 bits starting at (2*n)
44 * 00 = input, 01 = output, others mean special-function
45 * base + 0x04: Data register, 1 bit per gpio
46 * bit n: data bit n
47*/
48
49static int s3c_gpiolib_input(struct gpio_chip *chip, unsigned offset)
50{
51    struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
52    void __iomem *base = ourchip->base;
53    unsigned long flags;
54    unsigned long con;
55
56    s3c_gpio_lock(ourchip, flags);
57
58    con = __raw_readl(base + 0x00);
59    con &= ~(3 << (offset * 2));
60
61    __raw_writel(con, base + 0x00);
62
63    s3c_gpio_unlock(ourchip, flags);
64    return 0;
65}
66
67static int s3c_gpiolib_output(struct gpio_chip *chip,
68                  unsigned offset, int value)
69{
70    struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
71    void __iomem *base = ourchip->base;
72    unsigned long flags;
73    unsigned long dat;
74    unsigned long con;
75
76    s3c_gpio_lock(ourchip, flags);
77
78    dat = __raw_readl(base + 0x04);
79    dat &= ~(1 << offset);
80    if (value)
81        dat |= 1 << offset;
82    __raw_writel(dat, base + 0x04);
83
84    con = __raw_readl(base + 0x00);
85    con &= ~(3 << (offset * 2));
86    con |= 1 << (offset * 2);
87
88    __raw_writel(con, base + 0x00);
89    __raw_writel(dat, base + 0x04);
90
91    s3c_gpio_unlock(ourchip, flags);
92    return 0;
93}
94
95static void s3c_gpiolib_set(struct gpio_chip *chip,
96                unsigned offset, int value)
97{
98    struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
99    void __iomem *base = ourchip->base;
100    unsigned long flags;
101    unsigned long dat;
102
103    s3c_gpio_lock(ourchip, flags);
104
105    dat = __raw_readl(base + 0x04);
106    dat &= ~(1 << offset);
107    if (value)
108        dat |= 1 << offset;
109    __raw_writel(dat, base + 0x04);
110
111    s3c_gpio_unlock(ourchip, flags);
112}
113
114static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset)
115{
116    struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
117    unsigned long val;
118
119    val = __raw_readl(ourchip->base + 0x04);
120    val >>= offset;
121    val &= 1;
122
123    return val;
124}
125
126__init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
127{
128    struct gpio_chip *gc = &chip->chip;
129    int ret;
130
131    BUG_ON(!chip->base);
132    BUG_ON(!gc->label);
133    BUG_ON(!gc->ngpio);
134
135    spin_lock_init(&chip->lock);
136
137    if (!gc->direction_input)
138        gc->direction_input = s3c_gpiolib_input;
139    if (!gc->direction_output)
140        gc->direction_output = s3c_gpiolib_output;
141    if (!gc->set)
142        gc->set = s3c_gpiolib_set;
143    if (!gc->get)
144        gc->get = s3c_gpiolib_get;
145
146#ifdef CONFIG_PM
147    if (chip->pm != NULL) {
148        if (!chip->pm->save || !chip->pm->resume)
149            printk(KERN_ERR "gpio: %s has missing PM functions\n",
150                   gc->label);
151    } else
152        printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
153#endif
154
155    /* gpiochip_add() prints own failure message on error. */
156    ret = gpiochip_add(gc);
157    if (ret >= 0)
158        s3c_gpiolib_track(chip);
159}
160
161int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
162{
163    struct s3c_gpio_chip *s3c_chip = container_of(chip,
164            struct s3c_gpio_chip, chip);
165
166    return s3c_chip->irq_base + offset;
167}
168

Archive Download this file



interactive