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