danube gpio clean up
[openwrt.git] / target / linux / danube / files / drivers / char / danube_gpio.c
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
15 *
16 * Copyright (C) 2005 infineon
17 * Copyright (C) 2007 John Crispin <blogic@openwrt.org>
18 *
19 */
20
21 #include <linux/module.h>
22 #include <linux/types.h>
23 #include <linux/errno.h>
24 #include <linux/proc_fs.h>
25 #include <linux/init.h>
26 #include <linux/ioctl.h>
27 #include <asm/semaphore.h>
28 #include <asm/uaccess.h>
29 #include <asm/danube/danube.h>
30 #include <asm/danube/danube_ioctl.h>
31
32
33 #define PORT_IOC_CALL(ret,port,pin,func) \
34 ret=danube_port_reserve_pin(port,pin,PORT_MODULE_ID); \
35 if (ret == 0) ret=func(port,pin,PORT_MODULE_ID); \
36 if (ret == 0) ret=danube_port_free_pin(port,pin,PORT_MODULE_ID);
37
38
39 #define MAX_PORTS 2
40 #define PINS_PER_PORT 16
41
42 static unsigned int danube_gpio_major = 0;
43
44 /* TODO do we need this ? */
45 static struct semaphore port_sem;
46
47 /* TODO do we really need this ? return in a define is forbidden by coding style */
48 #define DANUBE_GPIO_SANITY {if (port > MAX_PORTS || pin > PINS_PER_PORT) return -EINVAL; }
49
50 int
51 danube_port_reserve_pin (unsigned int port, unsigned int pin)
52 {
53 DANUBE_GPIO_SANITY;
54 printk("%s : call to obseleted function\n", __func__);
55
56 return 0;
57 }
58 EXPORT_SYMBOL(danube_port_reserve_pin);
59
60 int
61 danube_port_free_pin (unsigned int port, unsigned int pin)
62 {
63 DANUBE_GPIO_SANITY;
64 printk("%s : call to obseleted function\n", __func__);
65
66 return 0;
67 }
68 EXPORT_SYMBOL(danube_port_free_pin);
69
70 int
71 danube_port_set_open_drain (unsigned int port, unsigned int pin)
72 {
73 DANUBE_GPIO_SANITY;
74 writel(readl(DANUBE_GPIO_P0_OD + (port * 0x30)) | (1 << pin), DANUBE_GPIO_P0_OD);
75
76 return 0;
77 }
78 EXPORT_SYMBOL(danube_port_set_open_drain);
79
80 int
81 danube_port_clear_open_drain (unsigned int port, unsigned int pin)
82 {
83 DANUBE_GPIO_SANITY;
84 writel(readl(DANUBE_GPIO_P0_OD + (port * 0x30)) & ~(1 << pin), DANUBE_GPIO_P0_OD);
85
86 return 0;
87 }
88 EXPORT_SYMBOL(danube_port_clear_open_drain);
89
90 int
91 danube_port_set_pudsel (unsigned int port, unsigned int pin)
92 {
93 DANUBE_GPIO_SANITY;
94 writel(readl(DANUBE_GPIO_P0_PUDSEL + (port * 0x30)) | (1 << pin), DANUBE_GPIO_P0_PUDSEL);
95
96 return 0;
97 }
98 EXPORT_SYMBOL(danube_port_set_pudsel);
99
100 int
101 danube_port_clear_pudsel (unsigned int port, unsigned int pin)
102 {
103 DANUBE_GPIO_SANITY;
104 writel(readl(DANUBE_GPIO_P0_PUDSEL + (port * 0x30)) & ~(1 << pin), DANUBE_GPIO_P0_PUDSEL);
105
106 return 0;
107 }
108 EXPORT_SYMBOL(danube_port_clear_pudsel);
109
110 int
111 danube_port_set_puden (unsigned int port, unsigned int pin)
112 {
113 DANUBE_GPIO_SANITY;
114 writel(readl(DANUBE_GPIO_P0_PUDEN + (port * 0x30)) | (1 << pin), DANUBE_GPIO_P0_PUDEN);
115
116 return 0;
117 }
118 EXPORT_SYMBOL(danube_port_set_puden);
119
120 int
121 danube_port_clear_puden (unsigned int port, unsigned int pin)
122 {
123 DANUBE_GPIO_SANITY;
124 writel(readl(DANUBE_GPIO_P0_PUDEN + (port * 0x30)) & ~(1 << pin), DANUBE_GPIO_P0_PUDEN);
125
126 return 0;
127 }
128 EXPORT_SYMBOL(danube_port_clear_puden);
129
130 int
131 danube_port_set_stoff (unsigned int port, unsigned int pin)
132 {
133 DANUBE_GPIO_SANITY;
134 writel(readl(DANUBE_GPIO_P0_STOFF + (port * 0x30)) | (1 << pin), DANUBE_GPIO_P0_STOFF);
135
136 return 0;
137 }
138 EXPORT_SYMBOL(danube_port_set_stoff);
139
140 int
141 danube_port_clear_stoff (unsigned int port, unsigned int pin)
142 {
143 DANUBE_GPIO_SANITY;
144 writel(readl(DANUBE_GPIO_P0_STOFF + (port * 0x30)) & ~(1 << pin), DANUBE_GPIO_P0_STOFF);
145
146 return 0;
147 }
148 EXPORT_SYMBOL(danube_port_clear_stoff);
149
150 int
151 danube_port_set_dir_out (unsigned int port, unsigned int pin)
152 {
153 DANUBE_GPIO_SANITY;
154 writel(readl(DANUBE_GPIO_P0_DIR + (port * 0x30)) | (1 << pin), DANUBE_GPIO_P0_DIR);
155
156 return 0;
157 }
158 EXPORT_SYMBOL(danube_port_set_dir_out);
159
160 int
161 danube_port_set_dir_in (unsigned int port, unsigned int pin)
162 {
163 DANUBE_GPIO_SANITY;
164 writel(readl(DANUBE_GPIO_P0_DIR + (port * 0x30)) & ~(1 << pin), DANUBE_GPIO_P0_DIR);
165
166 return 0;
167 }
168 EXPORT_SYMBOL(danube_port_set_dir_in);
169
170 int
171 danube_port_set_output (unsigned int port, unsigned int pin)
172 {
173 DANUBE_GPIO_SANITY;
174 writel(readl(DANUBE_GPIO_P0_OUT + (port * 0x30)) | (1 << pin), DANUBE_GPIO_P0_OUT);
175
176 return 0;
177 }
178 EXPORT_SYMBOL(danube_port_set_output);
179
180 int
181 danube_port_clear_output (unsigned int port, unsigned int pin)
182 {
183 DANUBE_GPIO_SANITY;
184 writel(readl(DANUBE_GPIO_P0_OUT + (port * 0x30)) & ~(1 << pin), DANUBE_GPIO_P0_OUT);
185
186 return 0;
187 }
188 EXPORT_SYMBOL(danube_port_clear_output);
189
190 int
191 danube_port_get_input (unsigned int port, unsigned int pin)
192 {
193 DANUBE_GPIO_SANITY;
194
195 if (readl(DANUBE_GPIO_P0_IN + (port * 0x30)) & (1 << pin))
196 return 0;
197 else
198 return 1;
199 }
200 EXPORT_SYMBOL(danube_port_get_input);
201
202 int
203 danube_port_set_altsel0 (unsigned int port, unsigned int pin)
204 {
205 DANUBE_GPIO_SANITY;
206 writel(readl(DANUBE_GPIO_P0_ALTSEL0 + (port * 0x30)) | (1 << pin), DANUBE_GPIO_P0_ALTSEL0);
207
208 return 0;
209 }
210 EXPORT_SYMBOL(danube_port_set_altsel0);
211
212 int
213 danube_port_clear_altsel0 (unsigned int port, unsigned int pin)
214 {
215 DANUBE_GPIO_SANITY;
216 writel(readl(DANUBE_GPIO_P0_ALTSEL0 + (port * 0x30)) & ~(1 << pin), DANUBE_GPIO_P0_ALTSEL0);
217
218 return 0;
219 }
220 EXPORT_SYMBOL(danube_port_clear_altsel0);
221
222 int
223 danube_port_set_altsel1 (unsigned int port, unsigned int pin)
224 {
225 DANUBE_GPIO_SANITY;
226 writel(readl(DANUBE_GPIO_P0_ALTSEL1 + (port * 0x30)) | (1 << pin), DANUBE_GPIO_P0_ALTSEL1);
227
228 return 0;
229 }
230 EXPORT_SYMBOL(danube_port_set_altsel1);
231
232 int
233 danube_port_clear_altsel1 (unsigned int port, unsigned int pin)
234 {
235 DANUBE_GPIO_SANITY;
236 writel(readl(DANUBE_GPIO_P0_ALTSEL1 + (port * 0x30)) & ~(1 << pin), DANUBE_GPIO_P0_ALTSEL1);
237
238 return 0;
239 }
240 EXPORT_SYMBOL(danube_port_clear_altsel1);
241
242 long danube_port_read_procmem_helper(char* tag, u32* in_reg, char *buf)
243 {
244 u32 reg, bit = 0;
245 unsigned int len, t;
246
247 len = sprintf(buf, "\n%s: ", tag);
248 reg = readl(in_reg);
249 bit = 0x80000000;
250 for (t = 0; t < 32; t++) {
251 if ((reg & bit) > 0)
252 len = len + sprintf(buf + len, "X");
253 else
254 len = len + sprintf(buf + len, " ");
255 bit = bit >> 1;
256 }
257
258 return len;
259 }
260
261 int
262 danube_port_read_procmem (char *buf, char **start, off_t offset, int count,
263 int *eof, void *data)
264 {
265 long len = sprintf (buf, "\nDanube Port Settings\n");
266
267 len += sprintf (buf + len,
268 " 3 2 1 0\n");
269 len += sprintf (buf + len,
270 " 10987654321098765432109876543210\n");
271 len += sprintf (buf + len,
272 "----------------------------------------\n");
273
274 len += danube_port_read_procmem_helper("P0-OUT", DANUBE_GPIO_P0_OUT, &buf[len]);
275 len += danube_port_read_procmem_helper("P1-OUT", DANUBE_GPIO_P1_OUT, &buf[len]);
276 len += danube_port_read_procmem_helper("P0-IN ", DANUBE_GPIO_P0_IN, &buf[len]);
277 len += danube_port_read_procmem_helper("P1-IN ", DANUBE_GPIO_P1_IN, &buf[len]);
278 len += danube_port_read_procmem_helper("P0-DIR", DANUBE_GPIO_P0_DIR, &buf[len]);
279 len += danube_port_read_procmem_helper("P1-DIR", DANUBE_GPIO_P1_DIR, &buf[len]);
280 len += danube_port_read_procmem_helper("P0-STO ", DANUBE_GPIO_P0_STOFF, &buf[len]);
281 len += danube_port_read_procmem_helper("P1-STO ", DANUBE_GPIO_P1_STOFF, &buf[len]);
282 len += danube_port_read_procmem_helper("P0-PUDE", DANUBE_GPIO_P0_PUDEN, &buf[len]);
283 len += danube_port_read_procmem_helper("P1-PUDE", DANUBE_GPIO_P1_PUDEN, &buf[len]);
284 len += danube_port_read_procmem_helper("P0-OD ", DANUBE_GPIO_P0_OD, &buf[len]);
285 len += danube_port_read_procmem_helper("P1-OD ", DANUBE_GPIO_P1_OD, &buf[len]);
286 len += danube_port_read_procmem_helper("P0-PUDS", DANUBE_GPIO_P0_PUDSEL, &buf[len]);
287 len += danube_port_read_procmem_helper("P1-PUDS", DANUBE_GPIO_P1_PUDSEL, &buf[len]);
288 len += danube_port_read_procmem_helper("P0-ALT0", DANUBE_GPIO_P0_ALTSEL0, &buf[len]);
289 len += danube_port_read_procmem_helper("P1-ALT0", DANUBE_GPIO_P1_ALTSEL0, &buf[len]);
290 len += danube_port_read_procmem_helper("P0-ALT1", DANUBE_GPIO_P0_ALTSEL1, &buf[len]);
291 len += danube_port_read_procmem_helper("P1-ALT1", DANUBE_GPIO_P1_ALTSEL1, &buf[len]);
292 len = len + sprintf (buf + len, "\n\n");
293
294 *eof = 1;
295
296 return len;
297 }
298
299 static int
300 danube_port_open (struct inode *inode, struct file *filep)
301 {
302 return 0;
303 }
304
305 static int
306 danube_port_release (struct inode *inode, struct file *filelp)
307 {
308 return 0;
309 }
310
311 static int
312 danube_port_ioctl (struct inode *inode, struct file *filp,
313 unsigned int cmd, unsigned long arg)
314 {
315 int ret = 0;
316 volatile struct danube_port_ioctl_parm parm;
317
318 if (_IOC_TYPE (cmd) != DANUBE_PORT_IOC_MAGIC)
319 return -EINVAL;
320
321 if (_IOC_DIR (cmd) & _IOC_WRITE) {
322 if (!access_ok
323 (VERIFY_READ, arg,
324 sizeof (struct danube_port_ioctl_parm)))
325 return -EFAULT;
326 ret = copy_from_user ((void *) &parm, (void *) arg,
327 sizeof (struct danube_port_ioctl_parm));
328 }
329 if (_IOC_DIR (cmd) & _IOC_READ) {
330 if (!access_ok
331 (VERIFY_WRITE, arg,
332 sizeof (struct danube_port_ioctl_parm)))
333 return -EFAULT;
334 }
335
336 if (down_trylock (&port_sem) != 0)
337 return -EBUSY;
338
339 switch (cmd) {
340 case DANUBE_PORT_IOCOD:
341 if (parm.value == 0x00) {
342 PORT_IOC_CALL (ret, parm.port, parm.pin,
343 danube_port_clear_open_drain);
344 }
345 else {
346 PORT_IOC_CALL (ret, parm.port, parm.pin,
347 danube_port_set_open_drain);
348 }
349 break;
350 case DANUBE_PORT_IOCPUDSEL:
351 if (parm.value == 0x00) {
352 PORT_IOC_CALL (ret, parm.port, parm.pin,
353 danube_port_clear_pudsel);
354 }
355 else {
356 PORT_IOC_CALL (ret, parm.port, parm.pin,
357 danube_port_set_pudsel);
358 }
359 break;
360 case DANUBE_PORT_IOCPUDEN:
361 if (parm.value == 0x00) {
362 PORT_IOC_CALL (ret, parm.port, parm.pin,
363 danube_port_clear_puden);
364 }
365 else {
366 PORT_IOC_CALL (ret, parm.port, parm.pin,
367 danube_port_set_puden);
368 }
369 break;
370 case DANUBE_PORT_IOCSTOFF:
371 if (parm.value == 0x00) {
372 PORT_IOC_CALL (ret, parm.port, parm.pin,
373 danube_port_clear_stoff);
374 }
375 else {
376 PORT_IOC_CALL (ret, parm.port, parm.pin,
377 danube_port_set_stoff);
378 }
379 break;
380 case DANUBE_PORT_IOCDIR:
381 if (parm.value == 0x00) {
382 PORT_IOC_CALL (ret, parm.port, parm.pin,
383 danube_port_set_dir_in);
384 }
385 else {
386 PORT_IOC_CALL (ret, parm.port, parm.pin,
387 danube_port_set_dir_out);
388 }
389 break;
390 case DANUBE_PORT_IOCOUTPUT:
391 if (parm.value == 0x00) {
392 PORT_IOC_CALL (ret, parm.port, parm.pin,
393 danube_port_clear_output);
394 }
395 else {
396 PORT_IOC_CALL (ret, parm.port, parm.pin,
397 danube_port_set_output);
398 }
399 break;
400 case DANUBE_PORT_IOCALTSEL0:
401 if (parm.value == 0x00) {
402 PORT_IOC_CALL (ret, parm.port, parm.pin,
403 danube_port_clear_altsel0);
404 }
405 else {
406 PORT_IOC_CALL (ret, parm.port, parm.pin,
407 danube_port_set_altsel0);
408 }
409 break;
410 case DANUBE_PORT_IOCALTSEL1:
411 if (parm.value == 0x00) {
412 PORT_IOC_CALL (ret, parm.port, parm.pin,
413 danube_port_clear_altsel1);
414 }
415 else {
416 PORT_IOC_CALL (ret, parm.port, parm.pin,
417 danube_port_set_altsel1);
418 }
419 break;
420 case DANUBE_PORT_IOCINPUT:
421 ret = danube_port_reserve_pin (parm.port, parm.pin,
422 PORT_MODULE_ID);
423 if (ret == 0)
424 parm.value =
425 danube_port_get_input (parm.port, parm.pin,
426 PORT_MODULE_ID);
427 ret = danube_port_free_pin (parm.port, parm.pin,
428 PORT_MODULE_ID);
429 copy_to_user ((void *) arg, (void *) &parm,
430 sizeof (struct danube_port_ioctl_parm));
431 break;
432 default:
433 ret = -EINVAL;
434 }
435
436 up (&port_sem);
437
438 return ret;
439 }
440
441 static struct file_operations port_fops = {
442 .open = danube_port_open,
443 .release = danube_port_release,
444 .ioctl = danube_port_ioctl
445 };
446
447 int __init
448 danube_gpio_init (void)
449 {
450 int retval = 0;
451
452 sema_init (&port_sem, 1);
453
454 danube_gpio_major = register_chrdev(0, "danube_gpio", &port_fops);
455 if (!danube_gpio_major)
456 {
457 printk("danube-port: Error! Could not register port device. #%d\n", danube_gpio_major);
458 retval = -EINVAL;
459 goto out;
460 }
461
462 create_proc_read_entry("driver/danube_port", 0, NULL,
463 danube_port_read_procmem, NULL);
464
465 printk("registered danube gpio driver\n");
466
467 out:
468 return retval;
469 }
470
471 void __exit
472 danube_gpio_exit (void)
473 {
474 unregister_chrdev(danube_gpio_major, "danube_gpio");
475 remove_proc_entry("danube_wdt", NULL);
476 }
477
478 module_init(danube_gpio_init);
479 module_exit(danube_gpio_exit);
This page took 0.08103 seconds and 5 git commands to generate.