Merge remote-tracking branch 's5p/for-next'
[linux-2.6/next.git] / arch / arm / mach-vt8500 / gpio.c
blob2bcc0ec783df793a981d84346d8eedc8d733d36d
1 /* linux/arch/arm/mach-vt8500/gpio.c
3 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
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.
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.
16 #include <linux/gpio.h>
17 #include <linux/init.h>
18 #include <linux/irq.h>
19 #include <linux/io.h>
21 #include "devices.h"
23 #define to_vt8500(__chip) container_of(__chip, struct vt8500_gpio_chip, chip)
25 #define ENABLE_REGS 0x0
26 #define DIRECTION_REGS 0x20
27 #define OUTVALUE_REGS 0x40
28 #define INVALUE_REGS 0x60
30 #define EXT_REGOFF 0x1c
32 static void __iomem *regbase;
34 struct vt8500_gpio_chip {
35 struct gpio_chip chip;
36 unsigned int shift;
37 unsigned int regoff;
40 static int gpio_to_irq_map[8];
42 static int vt8500_muxed_gpio_request(struct gpio_chip *chip,
43 unsigned offset)
45 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
46 unsigned val = readl(regbase + ENABLE_REGS + vt8500_chip->regoff);
48 val |= (1 << vt8500_chip->shift << offset);
49 writel(val, regbase + ENABLE_REGS + vt8500_chip->regoff);
51 return 0;
54 static void vt8500_muxed_gpio_free(struct gpio_chip *chip,
55 unsigned offset)
57 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
58 unsigned val = readl(regbase + ENABLE_REGS + vt8500_chip->regoff);
60 val &= ~(1 << vt8500_chip->shift << offset);
61 writel(val, regbase + ENABLE_REGS + vt8500_chip->regoff);
64 static int vt8500_muxed_gpio_direction_input(struct gpio_chip *chip,
65 unsigned offset)
67 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
68 unsigned val = readl(regbase + DIRECTION_REGS + vt8500_chip->regoff);
70 val &= ~(1 << vt8500_chip->shift << offset);
71 writel(val, regbase + DIRECTION_REGS + vt8500_chip->regoff);
73 return 0;
76 static int vt8500_muxed_gpio_direction_output(struct gpio_chip *chip,
77 unsigned offset, int value)
79 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
80 unsigned val = readl(regbase + DIRECTION_REGS + vt8500_chip->regoff);
82 val |= (1 << vt8500_chip->shift << offset);
83 writel(val, regbase + DIRECTION_REGS + vt8500_chip->regoff);
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);
90 return 0;
93 static int vt8500_muxed_gpio_get_value(struct gpio_chip *chip,
94 unsigned offset)
96 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
98 return (readl(regbase + INVALUE_REGS + vt8500_chip->regoff)
99 >> vt8500_chip->shift >> offset) & 1;
102 static void vt8500_muxed_gpio_set_value(struct gpio_chip *chip,
103 unsigned offset, int value)
105 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
106 unsigned val = readl(regbase + INVALUE_REGS + vt8500_chip->regoff);
108 if (value)
109 val |= (1 << vt8500_chip->shift << offset);
110 else
111 val &= ~(1 << vt8500_chip->shift << offset);
113 writel(val, regbase + INVALUE_REGS + vt8500_chip->regoff);
116 #define VT8500_GPIO_BANK(__name, __shift, __off, __base, __num) \
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, \
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),
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),
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),
151 VT8500_GPIO_BANK("ccir", 0, 0xc, 83, 19),
153 VT8500_GPIO_BANK("ts", 8, 0x10, 102, 11),
155 VT8500_GPIO_BANK("lcd", 0, 0x14, 113, 23),
158 static int vt8500_gpio_direction_input(struct gpio_chip *chip,
159 unsigned offset)
161 unsigned val = readl(regbase + DIRECTION_REGS + EXT_REGOFF);
163 val &= ~(1 << offset);
164 writel(val, regbase + DIRECTION_REGS + EXT_REGOFF);
165 return 0;
168 static int vt8500_gpio_direction_output(struct gpio_chip *chip,
169 unsigned offset, int value)
171 unsigned val = readl(regbase + DIRECTION_REGS + EXT_REGOFF);
173 val |= (1 << offset);
174 writel(val, regbase + DIRECTION_REGS + EXT_REGOFF);
176 if (value) {
177 val = readl(regbase + OUTVALUE_REGS + EXT_REGOFF);
178 val |= (1 << offset);
179 writel(val, regbase + OUTVALUE_REGS + EXT_REGOFF);
181 return 0;
184 static int vt8500_gpio_get_value(struct gpio_chip *chip,
185 unsigned offset)
187 return (readl(regbase + INVALUE_REGS + EXT_REGOFF) >> offset) & 1;
190 static void vt8500_gpio_set_value(struct gpio_chip *chip,
191 unsigned offset, int value)
193 unsigned val = readl(regbase + OUTVALUE_REGS + EXT_REGOFF);
195 if (value)
196 val |= (1 << offset);
197 else
198 val &= ~(1 << offset);
200 writel(val, regbase + OUTVALUE_REGS + EXT_REGOFF);
203 static int vt8500_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
205 if (offset > 7)
206 return -EINVAL;
208 return gpio_to_irq_map[offset];
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,
223 void __init vt8500_gpio_init(void)
225 int i;
227 for (i = 0; i < 8; i++)
228 gpio_to_irq_map[i] = wmt_gpio_ext_irq[i];
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;
236 gpiochip_add(&vt8500_external_gpios);
238 for (i = 0; i < ARRAY_SIZE(vt8500_muxed_gpios); i++)
239 gpiochip_add(&vt8500_muxed_gpios[i].chip);