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
vt8500_muxed_gpio_request(struct gpio_chip * chip,unsigned offset)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
vt8500_muxed_gpio_free(struct gpio_chip * chip,unsigned offset)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
vt8500_muxed_gpio_direction_input(struct gpio_chip * chip,unsigned offset)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
vt8500_muxed_gpio_direction_output(struct gpio_chip * chip,unsigned offset,int value)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
vt8500_muxed_gpio_get_value(struct gpio_chip * chip,unsigned offset)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
vt8500_muxed_gpio_set_value(struct gpio_chip * chip,unsigned offset,int value)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
vt8500_gpio_direction_input(struct gpio_chip * chip,unsigned offset)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
vt8500_gpio_direction_output(struct gpio_chip * chip,unsigned offset,int value)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
vt8500_gpio_get_value(struct gpio_chip * chip,unsigned offset)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
vt8500_gpio_set_value(struct gpio_chip * chip,unsigned offset,int value)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
vt8500_gpio_to_irq(struct gpio_chip * chip,unsigned offset)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
vt8500_gpio_init(void)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 }
241