Root/target/linux/s3c24xx/files-2.6.30/drivers/mfd/glamo/glamo-gpio.c

1/* Smedia Glamo 336x/337x gpio driver
2 *
3 * (C) 2009 Lars-Peter Clausen
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18 * MA 02111-1307 USA
19 */
20
21#include <linux/kernel.h>
22#include <linux/init.h>
23#include <linux/module.h>
24#include <linux/spinlock.h>
25#include <linux/io.h>
26#include <linux/platform_device.h>
27
28#include <linux/gpio.h>
29#include <linux/mfd/glamo.h>
30
31#include "glamo-core.h"
32#include "glamo-regs.h"
33
34#define GLAMO_NR_GPIO 21
35#define GLAMO_NR_GPIO_REGS DIV_ROUND_UP(GLAMO_NR_GPIO, 4)
36
37#define GLAMO_REG_GPIO(x) (((x) * 2) + GLAMO_REG_GPIO_GEN1)
38
39struct glamo_gpio {
40    struct glamo_core *glamo;
41    struct gpio_chip chip;
42    uint16_t saved_regs[GLAMO_NR_GPIO_REGS];
43};
44
45#define REG_OF_GPIO(gpio) (GLAMO_REG_GPIO(gpio >> 2))
46#define NUM_OF_GPIO(gpio) (gpio & 0x3)
47#define DIRECTION_BIT(gpio) (1 << (NUM_OF_GPIO(gpio) + 0))
48#define OUTPUT_BIT(gpio) (1 << (NUM_OF_GPIO(gpio) + 4))
49#define INPUT_BIT(gpio) (1 << (NUM_OF_GPIO(gpio) + 8))
50#define FUNC_BIT(gpio) (1 << (NUM_OF_GPIO(gpio) + 12))
51
52
53static inline struct glamo_core *chip_to_glamo(struct gpio_chip *chip)
54{
55    return container_of(chip, struct glamo_gpio, chip)->glamo;
56}
57
58static void glamo_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
59{
60    struct glamo_core *glamo = chip_to_glamo(chip);
61    unsigned int reg = REG_OF_GPIO(offset);
62    u_int16_t tmp;
63
64    spin_lock(&glamo->lock);
65    tmp = readw(glamo->base + reg);
66    if (value)
67        tmp |= OUTPUT_BIT(offset);
68    else
69        tmp &= ~OUTPUT_BIT(offset);
70    writew(tmp, glamo->base + reg);
71    spin_unlock(&glamo->lock);
72}
73
74static int glamo_gpio_get(struct gpio_chip *chip, unsigned offset)
75{
76    struct glamo_core *glamo = chip_to_glamo(chip);
77    return readw(glamo->base + REG_OF_GPIO(offset)) & INPUT_BIT(offset) ? 1 : 0;
78}
79
80static int glamo_gpio_request(struct gpio_chip *chip, unsigned offset)
81{
82    struct glamo_core *glamo = chip_to_glamo(chip);
83    unsigned int reg = REG_OF_GPIO(offset);
84    u_int16_t tmp;
85
86    spin_lock(&glamo->lock);
87    tmp = readw(glamo->base + reg);
88    if ((tmp & FUNC_BIT(offset)) == 0) {
89        tmp |= FUNC_BIT(offset);
90        writew(tmp, glamo->base + reg);
91    }
92    spin_unlock(&glamo->lock);
93
94    return 0;
95}
96
97static void glamo_gpio_free(struct gpio_chip *chip, unsigned offset)
98{
99    struct glamo_core *glamo = chip_to_glamo(chip);
100    unsigned int reg = REG_OF_GPIO(offset);
101    u_int16_t tmp;
102
103    spin_lock(&glamo->lock);
104    tmp = readw(glamo->base + reg);
105    if ((tmp & FUNC_BIT(offset)) == 1) {
106        tmp &= ~FUNC_BIT(offset);
107        writew(tmp, glamo->base + reg);
108    }
109    spin_unlock(&glamo->lock);
110}
111
112static int glamo_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
113                        int value)
114{
115    struct glamo_core *glamo = chip_to_glamo(chip);
116    unsigned int reg = REG_OF_GPIO(offset);
117    u_int16_t tmp;
118
119    spin_lock(&glamo->lock);
120    tmp = readw(glamo->base + reg);
121    tmp &= ~DIRECTION_BIT(offset);
122
123    if (value)
124        tmp |= OUTPUT_BIT(offset);
125    else
126        tmp &= ~OUTPUT_BIT(offset);
127
128    writew(tmp, glamo->base + reg);
129    spin_unlock(&glamo->lock);
130
131    return 0;
132}
133
134static int glamo_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
135{
136    struct glamo_core *glamo = chip_to_glamo(chip);
137    unsigned int reg = REG_OF_GPIO(offset);
138    u_int16_t tmp;
139
140    spin_lock(&glamo->lock);
141    tmp = readw(glamo->base + reg);
142    if ((tmp & DIRECTION_BIT(offset)) == 0) {
143        tmp |= DIRECTION_BIT(offset);
144        writew(tmp, glamo->base + reg);
145    }
146    spin_unlock(&glamo->lock);
147
148    return 0;
149}
150
151static const struct __devinit gpio_chip glamo_gpio_chip = {
152    .label = "glamo",
153    .request = glamo_gpio_request,
154    .free = glamo_gpio_free,
155    .direction_input = glamo_gpio_direction_input,
156    .get = glamo_gpio_get,
157    .direction_output = glamo_gpio_direction_output,
158    .set = glamo_gpio_set,
159    .base = -1,
160    .ngpio = GLAMO_NR_GPIO,
161    .can_sleep = 0,
162    .owner = THIS_MODULE,
163};
164
165static int __devinit glamo_gpio_probe(struct platform_device *pdev)
166{
167    struct glamo_platform_data *pdata = pdev->dev.parent->platform_data;
168    struct glamo_gpio *glamo_gpio;
169    int ret;
170
171    glamo_gpio = kzalloc(sizeof(struct glamo_gpio), GFP_KERNEL);
172    if (!glamo_gpio)
173        return -ENOMEM;
174
175    glamo_gpio->glamo = dev_get_drvdata(pdev->dev.parent);
176    glamo_gpio->chip = glamo_gpio_chip;
177    glamo_gpio->chip.dev = &pdev->dev;
178    if (pdata)
179        glamo_gpio->chip.base = pdata->gpio_base;
180
181    ret = gpiochip_add(&glamo_gpio->chip);
182
183    if (ret) {
184        dev_err(&pdev->dev, "Could not register gpio chip: %d\n", ret);
185        goto err;
186    }
187
188    platform_set_drvdata(pdev, glamo_gpio);
189    return 0;
190err:
191    kfree(glamo_gpio);
192    return ret;
193}
194
195static int __devexit glamo_gpio_remove(struct platform_device *pdev)
196{
197    struct glamo_gpio *glamo_gpio = platform_get_drvdata(pdev);
198    int ret;
199
200    ret = gpiochip_remove(&glamo_gpio->chip);
201    if (!ret)
202        goto done;
203
204    platform_set_drvdata(pdev, NULL);
205    kfree(glamo_gpio);
206
207done:
208    return ret;
209}
210
211#ifdef CONFIG_PM
212
213static int glamo_gpio_suspend(struct device *dev)
214{
215    struct glamo_gpio *glamo_gpio = dev_get_drvdata(dev);
216    struct glamo_core *glamo = glamo_gpio->glamo;
217    uint16_t *saved_regs = glamo_gpio->saved_regs;
218    int i;
219
220    spin_lock(&glamo->lock);
221    for (i = 0; i < GLAMO_NR_GPIO / 4; ++i)
222        saved_regs[i] = readw(glamo->base + GLAMO_REG_GPIO(i));
223    spin_unlock(&glamo->lock);
224
225    return 0;
226}
227
228static int glamo_gpio_resume(struct device *dev)
229{
230    struct glamo_gpio *glamo_gpio = dev_get_drvdata(dev);
231    struct glamo_core *glamo = glamo_gpio->glamo;
232    uint16_t *saved_regs = glamo_gpio->saved_regs;
233    int i;
234
235    spin_lock(&glamo->lock);
236    for (i = 0; i < GLAMO_NR_GPIO_REGS; ++i)
237        writew(saved_regs[i], glamo->base + GLAMO_REG_GPIO(i));
238    spin_unlock(&glamo->lock);
239    return 0;
240}
241
242static const struct dev_pm_ops glamo_pm_ops = {
243    .suspend = glamo_gpio_suspend,
244    .resume = glamo_gpio_resume,
245    .freeze = glamo_gpio_suspend,
246    .thaw = glamo_gpio_resume,
247};
248
249#define GLAMO_GPIO_PM_OPS (&glamo_pm_ops)
250
251#else
252#define GLAMO_GPIO_PM_OPS NULL
253#endif
254
255static struct platform_driver glamo_gpio_driver = {
256    .driver = {
257        .name = "glamo-gpio",
258        .owner = THIS_MODULE,
259        .pm = GLAMO_GPIO_PM_OPS,
260    },
261    .probe = glamo_gpio_probe,
262    .remove = __devexit_p(glamo_gpio_remove),
263};
264
265static int __devinit glamo_gpio_init(void)
266{
267    return platform_driver_register(&glamo_gpio_driver);
268}
269
270static void __exit glamo_gpio_exit(void)
271{
272    platform_driver_unregister(&glamo_gpio_driver);
273}
274
275module_init(glamo_gpio_init);
276module_exit(glamo_gpio_exit);
277
278MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
279MODULE_DESCRIPTION("GPIO interface for the Glamo multimedia device");
280MODULE_LICENSE("GPL");
281MODULE_ALIAS("platform:glamo-gpio");
282

Archive Download this file



interactive