]>
Commit | Line | Data |
---|---|---|
8a87a996 AV |
1 | /* |
2 | * arch/arm/mach-ks8695/gpio.c | |
3 | * | |
4 | * Copyright (C) 2006 Andrew Victor | |
72880ad8 DS |
5 | * Updated to GPIOLIB, Copyright 2008 Simtec Electronics |
6 | * Daniel Silverstone <[email protected]> | |
8a87a996 AV |
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 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to the Free Software | |
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
20 | */ | |
2f8163ba | 21 | #include <linux/gpio.h> |
8a87a996 AV |
22 | #include <linux/kernel.h> |
23 | #include <linux/mm.h> | |
24 | #include <linux/init.h> | |
20118ff9 AV |
25 | #include <linux/debugfs.h> |
26 | #include <linux/seq_file.h> | |
8a87a996 | 27 | #include <linux/module.h> |
fced80c7 | 28 | #include <linux/io.h> |
8a87a996 | 29 | |
a09e64fb | 30 | #include <mach/hardware.h> |
8a87a996 AV |
31 | #include <asm/mach/irq.h> |
32 | ||
a09e64fb | 33 | #include <mach/regs-gpio.h> |
e24e4498 | 34 | #include <mach/gpio-ks8695.h> |
8a87a996 AV |
35 | |
36 | /* | |
37 | * Configure a GPIO line for either GPIO function, or its internal | |
38 | * function (Interrupt, Timer, etc). | |
39 | */ | |
72880ad8 | 40 | static void ks8695_gpio_mode(unsigned int pin, short gpio) |
8a87a996 AV |
41 | { |
42 | unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN }; | |
43 | unsigned long x, flags; | |
44 | ||
45 | if (pin > KS8695_GPIO_5) /* only GPIO 0..5 have internal functions */ | |
46 | return; | |
47 | ||
48 | local_irq_save(flags); | |
49 | ||
50 | x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC); | |
51 | if (gpio) /* GPIO: set bit to 0 */ | |
52 | x &= ~enable[pin]; | |
53 | else /* Internal function: set bit to 1 */ | |
54 | x |= enable[pin]; | |
55 | __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC); | |
56 | ||
57 | local_irq_restore(flags); | |
58 | } | |
59 | ||
60 | ||
61 | static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 }; | |
62 | ||
63 | /* | |
64 | * Configure GPIO pin as external interrupt source. | |
65 | */ | |
72880ad8 | 66 | int ks8695_gpio_interrupt(unsigned int pin, unsigned int type) |
8a87a996 AV |
67 | { |
68 | unsigned long x, flags; | |
69 | ||
70 | if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */ | |
71 | return -EINVAL; | |
72 | ||
73 | local_irq_save(flags); | |
74 | ||
75 | /* set pin as input */ | |
76 | x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); | |
8d163b3f | 77 | x &= ~IOPM(pin); |
8a87a996 AV |
78 | __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); |
79 | ||
80 | local_irq_restore(flags); | |
81 | ||
82 | /* Set IRQ triggering type */ | |
6845664a | 83 | irq_set_irq_type(gpio_irq[pin], type); |
8a87a996 AV |
84 | |
85 | /* enable interrupt mode */ | |
86 | ks8695_gpio_mode(pin, 0); | |
87 | ||
88 | return 0; | |
89 | } | |
90 | EXPORT_SYMBOL(ks8695_gpio_interrupt); | |
91 | ||
92 | ||
93 | ||
94 | /* .... Generic GPIO interface .............................................. */ | |
95 | ||
96 | /* | |
97 | * Configure the GPIO line as an input. | |
98 | */ | |
72880ad8 | 99 | static int ks8695_gpio_direction_input(struct gpio_chip *gc, unsigned int pin) |
8a87a996 AV |
100 | { |
101 | unsigned long x, flags; | |
102 | ||
103 | if (pin > KS8695_GPIO_15) | |
104 | return -EINVAL; | |
105 | ||
106 | /* set pin to GPIO mode */ | |
107 | ks8695_gpio_mode(pin, 1); | |
108 | ||
109 | local_irq_save(flags); | |
110 | ||
111 | /* set pin as input */ | |
112 | x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); | |
8d163b3f | 113 | x &= ~IOPM(pin); |
8a87a996 AV |
114 | __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); |
115 | ||
116 | local_irq_restore(flags); | |
117 | ||
118 | return 0; | |
119 | } | |
8a87a996 AV |
120 | |
121 | ||
122 | /* | |
123 | * Configure the GPIO line as an output, with default state. | |
124 | */ | |
72880ad8 DS |
125 | static int ks8695_gpio_direction_output(struct gpio_chip *gc, |
126 | unsigned int pin, int state) | |
8a87a996 AV |
127 | { |
128 | unsigned long x, flags; | |
129 | ||
130 | if (pin > KS8695_GPIO_15) | |
131 | return -EINVAL; | |
132 | ||
133 | /* set pin to GPIO mode */ | |
134 | ks8695_gpio_mode(pin, 1); | |
135 | ||
136 | local_irq_save(flags); | |
137 | ||
138 | /* set line state */ | |
139 | x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); | |
140 | if (state) | |
8d163b3f | 141 | x |= IOPD(pin); |
8a87a996 | 142 | else |
8d163b3f | 143 | x &= ~IOPD(pin); |
8a87a996 AV |
144 | __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD); |
145 | ||
146 | /* set pin as output */ | |
147 | x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); | |
8d163b3f | 148 | x |= IOPM(pin); |
8a87a996 AV |
149 | __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); |
150 | ||
151 | local_irq_restore(flags); | |
152 | ||
153 | return 0; | |
154 | } | |
8a87a996 AV |
155 | |
156 | ||
157 | /* | |
158 | * Set the state of an output GPIO line. | |
159 | */ | |
72880ad8 DS |
160 | static void ks8695_gpio_set_value(struct gpio_chip *gc, |
161 | unsigned int pin, int state) | |
8a87a996 AV |
162 | { |
163 | unsigned long x, flags; | |
164 | ||
165 | if (pin > KS8695_GPIO_15) | |
166 | return; | |
167 | ||
168 | local_irq_save(flags); | |
169 | ||
170 | /* set output line state */ | |
171 | x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); | |
172 | if (state) | |
8d163b3f | 173 | x |= IOPD(pin); |
8a87a996 | 174 | else |
8d163b3f | 175 | x &= ~IOPD(pin); |
8a87a996 AV |
176 | __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD); |
177 | ||
178 | local_irq_restore(flags); | |
179 | } | |
8a87a996 AV |
180 | |
181 | ||
182 | /* | |
183 | * Read the state of a GPIO line. | |
184 | */ | |
72880ad8 | 185 | static int ks8695_gpio_get_value(struct gpio_chip *gc, unsigned int pin) |
8a87a996 AV |
186 | { |
187 | unsigned long x; | |
188 | ||
189 | if (pin > KS8695_GPIO_15) | |
190 | return -EINVAL; | |
191 | ||
192 | x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); | |
8d163b3f | 193 | return (x & IOPD(pin)) != 0; |
8a87a996 | 194 | } |
8a87a996 AV |
195 | |
196 | ||
197 | /* | |
198 | * Map GPIO line to IRQ number. | |
199 | */ | |
7ef71320 | 200 | static int ks8695_gpio_to_irq(struct gpio_chip *gc, unsigned int pin) |
8a87a996 AV |
201 | { |
202 | if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */ | |
203 | return -EINVAL; | |
204 | ||
205 | return gpio_irq[pin]; | |
206 | } | |
8a87a996 | 207 | |
72880ad8 DS |
208 | /* GPIOLIB interface */ |
209 | ||
210 | static struct gpio_chip ks8695_gpio_chip = { | |
211 | .label = "KS8695", | |
212 | .direction_input = ks8695_gpio_direction_input, | |
213 | .direction_output = ks8695_gpio_direction_output, | |
214 | .get = ks8695_gpio_get_value, | |
215 | .set = ks8695_gpio_set_value, | |
7ef71320 | 216 | .to_irq = ks8695_gpio_to_irq, |
72880ad8 DS |
217 | .base = 0, |
218 | .ngpio = 16, | |
9fb1f39e | 219 | .can_sleep = false, |
72880ad8 DS |
220 | }; |
221 | ||
222 | /* Register the GPIOs */ | |
223 | void ks8695_register_gpios(void) | |
224 | { | |
4eab22e7 | 225 | if (gpiochip_add_data(&ks8695_gpio_chip, NULL)) |
72880ad8 DS |
226 | printk(KERN_ERR "Unable to register core GPIOs\n"); |
227 | } | |
20118ff9 AV |
228 | |
229 | /* .... Debug interface ..................................................... */ | |
230 | ||
231 | #ifdef CONFIG_DEBUG_FS | |
232 | ||
233 | static int ks8695_gpio_show(struct seq_file *s, void *unused) | |
234 | { | |
235 | unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN }; | |
236 | unsigned int intmask[] = { IOPC_IOEINT0TM, IOPC_IOEINT1TM, IOPC_IOEINT2TM, IOPC_IOEINT3TM }; | |
237 | unsigned long mode, ctrl, data; | |
238 | int i; | |
239 | ||
240 | mode = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); | |
241 | ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC); | |
242 | data = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); | |
243 | ||
244 | seq_printf(s, "Pin\tI/O\tFunction\tState\n\n"); | |
245 | ||
246 | for (i = KS8695_GPIO_0; i <= KS8695_GPIO_15 ; i++) { | |
247 | seq_printf(s, "%i:\t", i); | |
248 | ||
8d163b3f | 249 | seq_printf(s, "%s\t", (mode & IOPM(i)) ? "Output" : "Input"); |
20118ff9 AV |
250 | |
251 | if (i <= KS8695_GPIO_3) { | |
252 | if (ctrl & enable[i]) { | |
253 | seq_printf(s, "EXT%i ", i); | |
254 | ||
255 | switch ((ctrl & intmask[i]) >> (4 * i)) { | |
0397375d VB |
256 | case IOPC_TM_LOW: |
257 | seq_printf(s, "(Low)"); break; | |
258 | case IOPC_TM_HIGH: | |
259 | seq_printf(s, "(High)"); break; | |
260 | case IOPC_TM_RISING: | |
261 | seq_printf(s, "(Rising)"); break; | |
262 | case IOPC_TM_FALLING: | |
263 | seq_printf(s, "(Falling)"); break; | |
264 | case IOPC_TM_EDGE: | |
265 | seq_printf(s, "(Edges)"); break; | |
20118ff9 | 266 | } |
36905a33 | 267 | } else |
20118ff9 | 268 | seq_printf(s, "GPIO\t"); |
36905a33 | 269 | } else if (i <= KS8695_GPIO_5) { |
20118ff9 AV |
270 | if (ctrl & enable[i]) |
271 | seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4); | |
272 | else | |
273 | seq_printf(s, "GPIO\t"); | |
36905a33 | 274 | } else { |
20118ff9 | 275 | seq_printf(s, "GPIO\t"); |
36905a33 | 276 | } |
20118ff9 AV |
277 | |
278 | seq_printf(s, "\t"); | |
279 | ||
8d163b3f | 280 | seq_printf(s, "%i\n", (data & IOPD(i)) ? 1 : 0); |
20118ff9 AV |
281 | } |
282 | return 0; | |
283 | } | |
284 | ||
285 | static int ks8695_gpio_open(struct inode *inode, struct file *file) | |
286 | { | |
287 | return single_open(file, ks8695_gpio_show, NULL); | |
288 | } | |
289 | ||
290 | static const struct file_operations ks8695_gpio_operations = { | |
291 | .open = ks8695_gpio_open, | |
292 | .read = seq_read, | |
293 | .llseek = seq_lseek, | |
294 | .release = single_release, | |
295 | }; | |
296 | ||
297 | static int __init ks8695_gpio_debugfs_init(void) | |
298 | { | |
299 | /* /sys/kernel/debug/ks8695_gpio */ | |
300 | (void) debugfs_create_file("ks8695_gpio", S_IFREG | S_IRUGO, NULL, NULL, &ks8695_gpio_operations); | |
301 | return 0; | |
302 | } | |
303 | postcore_initcall(ks8695_gpio_debugfs_init); | |
304 | ||
305 | #endif |