Merge branch 'linux-next' of git://git.infradead.org/ubifs-2.6
[pandora-kernel.git] / arch / arm / mach-w90x900 / gpio.c
1 /*
2  * linux/arch/arm/mach-w90p910/gpio.c
3  *
4  * Generic w90p910 GPIO handling
5  *
6  *  Wan ZongShun <mcuos.com@gmail.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12
13 #include <linux/clk.h>
14 #include <linux/errno.h>
15 #include <linux/interrupt.h>
16 #include <linux/irq.h>
17 #include <linux/debugfs.h>
18 #include <linux/seq_file.h>
19 #include <linux/kernel.h>
20 #include <linux/list.h>
21 #include <linux/module.h>
22 #include <linux/io.h>
23 #include <linux/gpio.h>
24
25 #include <mach/hardware.h>
26
27 #define GPIO_BASE               (W90X900_VA_GPIO)
28 #define GPIO_DIR                (0x04)
29 #define GPIO_OUT                (0x08)
30 #define GPIO_IN                 (0x0C)
31 #define GROUPINERV              (0x10)
32 #define GPIO_GPIO(Nb)           (0x00000001 << (Nb))
33 #define to_w90p910_gpio_chip(c) container_of(c, struct w90p910_gpio_chip, chip)
34
35 #define W90P910_GPIO_CHIP(name, base_gpio, nr_gpio)                     \
36         {                                                               \
37                 .chip = {                                               \
38                         .label            = name,                       \
39                         .direction_input  = w90p910_dir_input,          \
40                         .direction_output = w90p910_dir_output,         \
41                         .get              = w90p910_gpio_get,           \
42                         .set              = w90p910_gpio_set,           \
43                         .base             = base_gpio,                  \
44                         .ngpio            = nr_gpio,                    \
45                 }                                                       \
46         }
47
48 struct w90p910_gpio_chip {
49         struct gpio_chip        chip;
50         void __iomem            *regbase;       /* Base of group register*/
51         spinlock_t              gpio_lock;
52 };
53
54 static int w90p910_gpio_get(struct gpio_chip *chip, unsigned offset)
55 {
56         struct w90p910_gpio_chip *w90p910_gpio = to_w90p910_gpio_chip(chip);
57         void __iomem *pio = w90p910_gpio->regbase + GPIO_IN;
58         unsigned int regval;
59
60         regval = __raw_readl(pio);
61         regval &= GPIO_GPIO(offset);
62
63         return (regval != 0);
64 }
65
66 static void w90p910_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
67 {
68         struct w90p910_gpio_chip *w90p910_gpio = to_w90p910_gpio_chip(chip);
69         void __iomem *pio = w90p910_gpio->regbase + GPIO_OUT;
70         unsigned int regval;
71         unsigned long flags;
72
73         spin_lock_irqsave(&w90p910_gpio->gpio_lock, flags);
74
75         regval = __raw_readl(pio);
76
77         if (val)
78                 regval |= GPIO_GPIO(offset);
79         else
80                 regval &= ~GPIO_GPIO(offset);
81
82         __raw_writel(regval, pio);
83
84         spin_unlock_irqrestore(&w90p910_gpio->gpio_lock, flags);
85 }
86
87 static int w90p910_dir_input(struct gpio_chip *chip, unsigned offset)
88 {
89         struct w90p910_gpio_chip *w90p910_gpio = to_w90p910_gpio_chip(chip);
90         void __iomem *pio = w90p910_gpio->regbase + GPIO_DIR;
91         unsigned int regval;
92         unsigned long flags;
93
94         spin_lock_irqsave(&w90p910_gpio->gpio_lock, flags);
95
96         regval = __raw_readl(pio);
97         regval &= ~GPIO_GPIO(offset);
98         __raw_writel(regval, pio);
99
100         spin_unlock_irqrestore(&w90p910_gpio->gpio_lock, flags);
101
102         return 0;
103 }
104
105 static int w90p910_dir_output(struct gpio_chip *chip, unsigned offset, int val)
106 {
107         struct w90p910_gpio_chip *w90p910_gpio = to_w90p910_gpio_chip(chip);
108         void __iomem *outreg = w90p910_gpio->regbase + GPIO_OUT;
109         void __iomem *pio = w90p910_gpio->regbase + GPIO_DIR;
110         unsigned int regval;
111         unsigned long flags;
112
113         spin_lock_irqsave(&w90p910_gpio->gpio_lock, flags);
114
115         regval = __raw_readl(pio);
116         regval |= GPIO_GPIO(offset);
117         __raw_writel(regval, pio);
118
119         regval = __raw_readl(outreg);
120
121         if (val)
122                 regval |= GPIO_GPIO(offset);
123         else
124                 regval &= ~GPIO_GPIO(offset);
125
126         __raw_writel(regval, outreg);
127
128         spin_unlock_irqrestore(&w90p910_gpio->gpio_lock, flags);
129
130         return 0;
131 }
132
133 static struct w90p910_gpio_chip w90p910_gpio[] = {
134         W90P910_GPIO_CHIP("GROUPC", 0, 16),
135         W90P910_GPIO_CHIP("GROUPD", 16, 10),
136         W90P910_GPIO_CHIP("GROUPE", 26, 14),
137         W90P910_GPIO_CHIP("GROUPF", 40, 10),
138         W90P910_GPIO_CHIP("GROUPG", 50, 17),
139         W90P910_GPIO_CHIP("GROUPH", 67, 8),
140         W90P910_GPIO_CHIP("GROUPI", 75, 17),
141 };
142
143 void __init w90p910_init_gpio(int nr_group)
144 {
145         unsigned        i;
146         struct w90p910_gpio_chip *gpio_chip;
147
148         for (i = 0; i < nr_group; i++) {
149                 gpio_chip = &w90p910_gpio[i];
150                 spin_lock_init(&gpio_chip->gpio_lock);
151                 gpio_chip->regbase = GPIO_BASE + i * GROUPINERV;
152                 gpiochip_add(&gpio_chip->chip);
153         }
154 }