]> git.karo-electronics.de Git - karo-tx-linux.git/blob - arch/arm/mach-vt8500/gpio.c
Merge tag 'iommu-updates-v3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/joro...
[karo-tx-linux.git] / arch / arm / mach-vt8500 / gpio.c
1 /* linux/arch/arm/mach-vt8500/gpio.c
2  *
3  * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
4  *
5  * This software is licensed under the terms of the GNU General Public
6  * License version 2, as published by the Free Software Foundation, and
7  * may be copied, distributed, and modified under those terms.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  */
15
16 #include <linux/gpio.h>
17 #include <linux/init.h>
18 #include <linux/irq.h>
19 #include <linux/io.h>
20
21 #include "devices.h"
22
23 #define to_vt8500(__chip) container_of(__chip, struct vt8500_gpio_chip, chip)
24
25 #define ENABLE_REGS     0x0
26 #define DIRECTION_REGS  0x20
27 #define OUTVALUE_REGS   0x40
28 #define INVALUE_REGS    0x60
29
30 #define EXT_REGOFF      0x1c
31
32 static void __iomem *regbase;
33
34 struct vt8500_gpio_chip {
35         struct gpio_chip        chip;
36         unsigned int            shift;
37         unsigned int            regoff;
38 };
39
40 static int gpio_to_irq_map[8];
41
42 static int vt8500_muxed_gpio_request(struct gpio_chip *chip,
43                                      unsigned offset)
44 {
45         struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
46         unsigned val = readl(regbase + ENABLE_REGS + vt8500_chip->regoff);
47
48         val |= (1 << vt8500_chip->shift << offset);
49         writel(val, regbase + ENABLE_REGS + vt8500_chip->regoff);
50
51         return 0;
52 }
53
54 static void vt8500_muxed_gpio_free(struct gpio_chip *chip,
55                                    unsigned offset)
56 {
57         struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
58         unsigned val = readl(regbase + ENABLE_REGS + vt8500_chip->regoff);
59
60         val &= ~(1 << vt8500_chip->shift << offset);
61         writel(val, regbase + ENABLE_REGS + vt8500_chip->regoff);
62 }
63
64 static int vt8500_muxed_gpio_direction_input(struct gpio_chip *chip,
65                                        unsigned offset)
66 {
67         struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
68         unsigned val = readl(regbase + DIRECTION_REGS + vt8500_chip->regoff);
69
70         val &= ~(1 << vt8500_chip->shift << offset);
71         writel(val, regbase + DIRECTION_REGS + vt8500_chip->regoff);
72
73         return 0;
74 }
75
76 static int vt8500_muxed_gpio_direction_output(struct gpio_chip *chip,
77                                         unsigned offset, int value)
78 {
79         struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
80         unsigned val = readl(regbase + DIRECTION_REGS + vt8500_chip->regoff);
81
82         val |= (1 << vt8500_chip->shift << offset);
83         writel(val, regbase + DIRECTION_REGS + vt8500_chip->regoff);
84
85         if (value) {
86                 val = readl(regbase + OUTVALUE_REGS + vt8500_chip->regoff);
87                 val |= (1 << vt8500_chip->shift << offset);
88                 writel(val, regbase + OUTVALUE_REGS + vt8500_chip->regoff);
89         }
90         return 0;
91 }
92
93 static int vt8500_muxed_gpio_get_value(struct gpio_chip *chip,
94                                        unsigned offset)
95 {
96         struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
97
98         return (readl(regbase + INVALUE_REGS + vt8500_chip->regoff)
99                 >> vt8500_chip->shift >> offset) & 1;
100 }
101
102 static void vt8500_muxed_gpio_set_value(struct gpio_chip *chip,
103                                         unsigned offset, int value)
104 {
105         struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
106         unsigned val = readl(regbase + INVALUE_REGS + vt8500_chip->regoff);
107
108         if (value)
109                 val |= (1 << vt8500_chip->shift << offset);
110         else
111                 val &= ~(1 << vt8500_chip->shift << offset);
112
113         writel(val, regbase + INVALUE_REGS + vt8500_chip->regoff);
114 }
115
116 #define VT8500_GPIO_BANK(__name, __shift, __off, __base, __num)         \
117 {                                                                       \
118         .chip = {                                                       \
119                 .label                  = __name,                       \
120                 .request                = vt8500_muxed_gpio_request,    \
121                 .free                   = vt8500_muxed_gpio_free,       \
122                 .direction_input  = vt8500_muxed_gpio_direction_input,  \
123                 .direction_output = vt8500_muxed_gpio_direction_output, \
124                 .get                    = vt8500_muxed_gpio_get_value,  \
125                 .set                    = vt8500_muxed_gpio_set_value,  \
126                 .can_sleep              = 0,                            \
127                 .base                   = __base,                       \
128                 .ngpio                  = __num,                        \
129         },                                                              \
130         .shift          = __shift,                                      \
131         .regoff         = __off,                                        \
132 }
133
134 static struct vt8500_gpio_chip vt8500_muxed_gpios[] = {
135         VT8500_GPIO_BANK("uart0",       0,      0x0,    8,      4),
136         VT8500_GPIO_BANK("uart1",       4,      0x0,    12,     4),
137         VT8500_GPIO_BANK("spi0",        8,      0x0,    16,     4),
138         VT8500_GPIO_BANK("spi1",        12,     0x0,    20,     4),
139         VT8500_GPIO_BANK("spi2",        16,     0x0,    24,     4),
140         VT8500_GPIO_BANK("pwmout",      24,     0x0,    28,     2),
141
142         VT8500_GPIO_BANK("sdmmc",       0,      0x4,    30,     11),
143         VT8500_GPIO_BANK("ms",          16,     0x4,    41,     7),
144         VT8500_GPIO_BANK("i2c0",        24,     0x4,    48,     2),
145         VT8500_GPIO_BANK("i2c1",        26,     0x4,    50,     2),
146
147         VT8500_GPIO_BANK("mii",         0,      0x8,    52,     20),
148         VT8500_GPIO_BANK("see",         20,     0x8,    72,     4),
149         VT8500_GPIO_BANK("ide",         24,     0x8,    76,     7),
150
151         VT8500_GPIO_BANK("ccir",        0,      0xc,    83,     19),
152
153         VT8500_GPIO_BANK("ts",          8,      0x10,   102,    11),
154
155         VT8500_GPIO_BANK("lcd",         0,      0x14,   113,    23),
156 };
157
158 static int vt8500_gpio_direction_input(struct gpio_chip *chip,
159                                        unsigned offset)
160 {
161         unsigned val = readl(regbase + DIRECTION_REGS + EXT_REGOFF);
162
163         val &= ~(1 << offset);
164         writel(val, regbase + DIRECTION_REGS + EXT_REGOFF);
165         return 0;
166 }
167
168 static int vt8500_gpio_direction_output(struct gpio_chip *chip,
169                                         unsigned offset, int value)
170 {
171         unsigned val = readl(regbase + DIRECTION_REGS + EXT_REGOFF);
172
173         val |= (1 << offset);
174         writel(val, regbase + DIRECTION_REGS + EXT_REGOFF);
175
176         if (value) {
177                 val = readl(regbase + OUTVALUE_REGS + EXT_REGOFF);
178                 val |= (1 << offset);
179                 writel(val, regbase + OUTVALUE_REGS + EXT_REGOFF);
180         }
181         return 0;
182 }
183
184 static int vt8500_gpio_get_value(struct gpio_chip *chip,
185                                        unsigned offset)
186 {
187         return (readl(regbase + INVALUE_REGS + EXT_REGOFF) >> offset) & 1;
188 }
189
190 static void vt8500_gpio_set_value(struct gpio_chip *chip,
191                                         unsigned offset, int value)
192 {
193         unsigned val = readl(regbase + OUTVALUE_REGS + EXT_REGOFF);
194
195         if (value)
196                 val |= (1 << offset);
197         else
198                 val &= ~(1 << offset);
199
200         writel(val, regbase + OUTVALUE_REGS + EXT_REGOFF);
201 }
202
203 static int vt8500_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
204 {
205         if (offset > 7)
206                 return -EINVAL;
207
208         return gpio_to_irq_map[offset];
209 }
210
211 static struct gpio_chip vt8500_external_gpios = {
212         .label                  = "extgpio",
213         .direction_input        = vt8500_gpio_direction_input,
214         .direction_output       = vt8500_gpio_direction_output,
215         .get                    = vt8500_gpio_get_value,
216         .set                    = vt8500_gpio_set_value,
217         .to_irq                 = vt8500_gpio_to_irq,
218         .can_sleep              = 0,
219         .base                   = 0,
220         .ngpio                  = 8,
221 };
222
223 void __init vt8500_gpio_init(void)
224 {
225         int i;
226
227         for (i = 0; i < 8; i++)
228                 gpio_to_irq_map[i] = wmt_gpio_ext_irq[i];
229
230         regbase = ioremap(wmt_gpio_base, SZ_64K);
231         if (!regbase) {
232                 printk(KERN_ERR "Failed to map MMIO registers for GPIO\n");
233                 return;
234         }
235
236         gpiochip_add(&vt8500_external_gpios);
237
238         for (i = 0; i < ARRAY_SIZE(vt8500_muxed_gpios); i++)
239                 gpiochip_add(&vt8500_muxed_gpios[i].chip);
240 }