]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/plat-omap/gpio-switch.c
Merge branch 'omap-fixes'
[linux-2.6-omap-h63xx.git] / arch / arm / plat-omap / gpio-switch.c
1 /*
2  *  linux/arch/arm/plat-omap/gpio-switch.c
3  *
4  *  Copyright (C) 2004-2006 Nokia Corporation
5  *  Written by Juha Yrjölä <juha.yrjola@nokia.com>
6  *         and Paul Mundt <paul.mundt@nokia.com>
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
13 #include <linux/sched.h>
14 #include <linux/init.h>
15 #include <linux/list.h>
16 #include <linux/irq.h>
17 #include <linux/interrupt.h>
18 #include <linux/module.h>
19 #include <linux/platform_device.h>
20 #include <linux/timer.h>
21 #include <linux/err.h>
22 #include <linux/gpio.h>
23 #include <mach/hardware.h>
24 #include <mach/irqs.h>
25 #include <mach/mux.h>
26 #include <mach/board.h>
27 #include <mach/gpio-switch.h>
28
29 struct gpio_switch {
30         char            name[14];
31         u16             gpio;
32         unsigned        flags:4;
33         unsigned        type:4;
34         unsigned        state:1;
35         unsigned        both_edges:1;
36
37         u16             debounce_rising;
38         u16             debounce_falling;
39
40         void (* notify)(void *data, int state);
41         void *notify_data;
42
43         struct work_struct      work;
44         struct timer_list       timer;
45         struct platform_device  pdev;
46
47         struct list_head        node;
48 };
49
50 static LIST_HEAD(gpio_switches);
51 static struct platform_device *gpio_sw_platform_dev;
52 static struct platform_driver gpio_sw_driver;
53
54 static const struct omap_gpio_switch *board_gpio_sw_table;
55 static int board_gpio_sw_count;
56
57 static const char *cover_str[2] = { "open", "closed" };
58 static const char *connection_str[2] = { "disconnected", "connected" };
59 static const char *activity_str[2] = { "inactive", "active" };
60
61 /*
62  * GPIO switch state default debounce delay in ms
63  */
64 #define OMAP_GPIO_SW_DEFAULT_DEBOUNCE           10
65
66 static const char **get_sw_str(struct gpio_switch *sw)
67 {
68         switch (sw->type) {
69         case OMAP_GPIO_SWITCH_TYPE_COVER:
70                 return cover_str;
71         case OMAP_GPIO_SWITCH_TYPE_CONNECTION:
72                 return connection_str;
73         case OMAP_GPIO_SWITCH_TYPE_ACTIVITY:
74                 return activity_str;
75         default:
76                 BUG();
77                 return NULL;
78         }
79 }
80
81 static const char *get_sw_type(struct gpio_switch *sw)
82 {
83         switch (sw->type) {
84         case OMAP_GPIO_SWITCH_TYPE_COVER:
85                 return "cover";
86         case OMAP_GPIO_SWITCH_TYPE_CONNECTION:
87                 return "connection";
88         case OMAP_GPIO_SWITCH_TYPE_ACTIVITY:
89                 return "activity";
90         default:
91                 BUG();
92                 return NULL;
93         }
94 }
95
96 static void print_sw_state(struct gpio_switch *sw, int state)
97 {
98         const char **str;
99
100         str = get_sw_str(sw);
101         if (str != NULL)
102                 printk(KERN_INFO "%s (GPIO %d) is now %s\n", sw->name, sw->gpio, str[state]);
103 }
104
105 static int gpio_sw_get_state(struct gpio_switch *sw)
106 {
107         int state;
108
109         state = gpio_get_value(sw->gpio);
110         if (sw->flags & OMAP_GPIO_SWITCH_FLAG_INVERTED)
111                 state = !state;
112
113         return state;
114 }
115
116 static ssize_t gpio_sw_state_store(struct device *dev,
117                                    struct device_attribute *attr,
118                                    const char *buf,
119                                    size_t count)
120 {
121         struct gpio_switch *sw = dev_get_drvdata(dev);
122         const char **str;
123         char state[16];
124         int enable;
125
126         if (!(sw->flags & OMAP_GPIO_SWITCH_FLAG_OUTPUT))
127                 return -EPERM;
128
129         if (sscanf(buf, "%15s", state) != 1)
130                 return -EINVAL;
131
132         str = get_sw_str(sw);
133         if (strcmp(state, str[0]) == 0)
134                 sw->state = enable = 0;
135         else if (strcmp(state, str[1]) == 0)
136                 sw->state = enable = 1;
137         else
138                 return -EINVAL;
139
140         if (sw->flags & OMAP_GPIO_SWITCH_FLAG_INVERTED)
141                 enable = !enable;
142         gpio_set_value(sw->gpio, enable);
143
144         return count;
145 }
146
147 static ssize_t gpio_sw_state_show(struct device *dev,
148                                   struct device_attribute *attr,
149                                   char *buf)
150 {
151         struct gpio_switch *sw = dev_get_drvdata(dev);
152         const char **str;
153
154         str = get_sw_str(sw);
155         return sprintf(buf, "%s\n", str[sw->state]);
156 }
157
158 static DEVICE_ATTR(state, S_IRUGO | S_IWUSR, gpio_sw_state_show,
159                    gpio_sw_state_store);
160
161 static ssize_t gpio_sw_type_show(struct device *dev,
162                                  struct device_attribute *attr,
163                                  char *buf)
164 {
165         struct gpio_switch *sw = dev_get_drvdata(dev);
166
167         return sprintf(buf, "%s\n", get_sw_type(sw));
168 }
169
170 static DEVICE_ATTR(type, S_IRUGO, gpio_sw_type_show, NULL);
171
172 static ssize_t gpio_sw_direction_show(struct device *dev,
173                                       struct device_attribute *attr,
174                                       char *buf)
175 {
176         struct gpio_switch *sw = dev_get_drvdata(dev);
177         int is_output;
178
179         is_output = sw->flags & OMAP_GPIO_SWITCH_FLAG_OUTPUT;
180         return sprintf(buf, "%s\n", is_output ? "output" : "input");
181 }
182
183 static DEVICE_ATTR(direction, S_IRUGO, gpio_sw_direction_show, NULL);
184
185
186 static irqreturn_t gpio_sw_irq_handler(int irq, void *arg)
187 {
188         struct gpio_switch *sw = arg;
189         unsigned long timeout;
190         int state;
191
192         if (!sw->both_edges) {
193                 if (gpio_get_value(sw->gpio))
194                         set_irq_type(gpio_to_irq(sw->gpio), IRQ_TYPE_EDGE_FALLING);
195                 else
196                         set_irq_type(gpio_to_irq(sw->gpio), IRQ_TYPE_EDGE_RISING);
197         }
198
199         state = gpio_sw_get_state(sw);
200         if (sw->state == state)
201                 return IRQ_HANDLED;
202
203         if (state)
204                 timeout = sw->debounce_rising;
205         else
206                 timeout = sw->debounce_falling;
207         if (!timeout)
208                 schedule_work(&sw->work);
209         else
210                 mod_timer(&sw->timer, jiffies + msecs_to_jiffies(timeout));
211
212         return IRQ_HANDLED;
213 }
214
215 static void gpio_sw_timer(unsigned long arg)
216 {
217         struct gpio_switch *sw = (struct gpio_switch *) arg;
218
219         schedule_work(&sw->work);
220 }
221
222 static void gpio_sw_handler(struct work_struct *work)
223 {
224         struct gpio_switch *sw = container_of(work, struct gpio_switch, work);
225         int state;
226
227         state = gpio_sw_get_state(sw);
228         if (sw->state == state)
229                 return;
230
231         sw->state = state;
232         if (sw->notify != NULL)
233                 sw->notify(sw->notify_data, state);
234         sysfs_notify(&sw->pdev.dev.kobj, NULL, "state");
235         print_sw_state(sw, state);
236 }
237
238 static int __init can_do_both_edges(struct gpio_switch *sw)
239 {
240         if (!cpu_class_is_omap1())
241                 return 1;
242         if (OMAP_GPIO_IS_MPUIO(sw->gpio))
243                 return 0;
244         else
245                 return 1;
246 }
247
248 static void gpio_sw_release(struct device *dev)
249 {
250 }
251
252 static int __init new_switch(struct gpio_switch *sw)
253 {
254         int r, direction, trigger;
255
256         switch (sw->type) {
257         case OMAP_GPIO_SWITCH_TYPE_COVER:
258         case OMAP_GPIO_SWITCH_TYPE_CONNECTION:
259         case OMAP_GPIO_SWITCH_TYPE_ACTIVITY:
260                 break;
261         default:
262                 printk(KERN_ERR "invalid GPIO switch type: %d\n", sw->type);
263                 return -EINVAL;
264         }
265
266         sw->pdev.name   = sw->name;
267         sw->pdev.id     = -1;
268
269         sw->pdev.dev.parent = &gpio_sw_platform_dev->dev;
270         sw->pdev.dev.driver = &gpio_sw_driver.driver;
271         sw->pdev.dev.release = gpio_sw_release;
272
273         r = platform_device_register(&sw->pdev);
274         if (r) {
275                 printk(KERN_ERR "gpio-switch: platform device registration "
276                        "failed for %s", sw->name);
277                 return r;
278         }
279         dev_set_drvdata(&sw->pdev.dev, sw);
280
281         r = gpio_request(sw->gpio, sw->name);
282         if (r < 0) {
283                 platform_device_unregister(&sw->pdev);
284                 return r;
285         }
286
287         /* input: 1, output: 0 */
288         direction = !(sw->flags & OMAP_GPIO_SWITCH_FLAG_OUTPUT);
289         if (direction) {
290                 gpio_direction_input(sw->gpio);
291                 sw->state = gpio_sw_get_state(sw);
292         } else {
293                 int state = sw->state = !!(sw->flags &
294                         OMAP_GPIO_SWITCH_FLAG_OUTPUT_INIT_ACTIVE);
295
296                 if (sw->flags & OMAP_GPIO_SWITCH_FLAG_INVERTED)
297                         state = !state;
298                 gpio_direction_output(sw->gpio, state);
299         }
300
301         r = 0;
302         r |= device_create_file(&sw->pdev.dev, &dev_attr_state);
303         r |= device_create_file(&sw->pdev.dev, &dev_attr_type);
304         r |= device_create_file(&sw->pdev.dev, &dev_attr_direction);
305         if (r)
306                 printk(KERN_ERR "gpio-switch: attribute file creation "
307                        "failed for %s\n", sw->name);
308
309         if (!direction)
310                 return 0;
311
312         if (can_do_both_edges(sw)) {
313                 trigger = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING;
314                 sw->both_edges = 1;
315         } else {
316                 if (gpio_get_value(sw->gpio))
317                         trigger = IRQF_TRIGGER_FALLING;
318                 else
319                         trigger = IRQF_TRIGGER_RISING;
320         }
321         r = request_irq(gpio_to_irq(sw->gpio), gpio_sw_irq_handler,
322                         IRQF_SHARED | trigger, sw->name, sw);
323         if (r < 0) {
324                 printk(KERN_ERR "gpio-switch: request_irq() failed "
325                        "for GPIO %d\n", sw->gpio);
326                 platform_device_unregister(&sw->pdev);
327                 gpio_free(sw->gpio);
328                 return r;
329         }
330
331         INIT_WORK(&sw->work, gpio_sw_handler);
332         init_timer(&sw->timer);
333
334         sw->timer.function = gpio_sw_timer;
335         sw->timer.data = (unsigned long)sw;
336
337         list_add(&sw->node, &gpio_switches);
338
339         return 0;
340 }
341
342 static int __init add_atag_switches(void)
343 {
344         const struct omap_gpio_switch_config *cfg;
345         struct gpio_switch *sw;
346         int i, r;
347
348         for (i = 0; ; i++) {
349                 cfg = omap_get_nr_config(OMAP_TAG_GPIO_SWITCH,
350                                          struct omap_gpio_switch_config, i);
351                 if (cfg == NULL)
352                         break;
353                 sw = kzalloc(sizeof(*sw), GFP_KERNEL);
354                 if (sw == NULL) {
355                         printk(KERN_ERR "gpio-switch: kmalloc failed\n");
356                         return -ENOMEM;
357                 }
358                 strncpy(sw->name, cfg->name, sizeof(cfg->name));
359                 sw->gpio = cfg->gpio;
360                 sw->flags = cfg->flags;
361                 sw->type = cfg->type;
362                 sw->debounce_rising = OMAP_GPIO_SW_DEFAULT_DEBOUNCE;
363                 sw->debounce_falling = OMAP_GPIO_SW_DEFAULT_DEBOUNCE;
364                 if ((r = new_switch(sw)) < 0) {
365                         kfree(sw);
366                         return r;
367                 }
368         }
369         return 0;
370 }
371
372 static struct gpio_switch * __init find_switch(int gpio, const char *name)
373 {
374         struct gpio_switch *sw;
375
376         list_for_each_entry(sw, &gpio_switches, node) {
377                 if ((gpio < 0 || sw->gpio != gpio) &&
378                     (name == NULL || strcmp(sw->name, name) != 0))
379                         continue;
380
381                 if (gpio < 0 || name == NULL)
382                         goto no_check;
383
384                 if (strcmp(sw->name, name) != 0)
385                         printk("gpio-switch: name mismatch for %d (%s, %s)\n",
386                                gpio, name, sw->name);
387                 else if (sw->gpio != gpio)
388                         printk("gpio-switch: GPIO mismatch for %s (%d, %d)\n",
389                                name, gpio, sw->gpio);
390 no_check:
391                 return sw;
392         }
393         return NULL;
394 }
395
396 static int __init add_board_switches(void)
397 {
398         int i;
399
400         for (i = 0; i < board_gpio_sw_count; i++) {
401                 const struct omap_gpio_switch *cfg;
402                 struct gpio_switch *sw;
403                 int r;
404
405                 cfg = board_gpio_sw_table + i;
406                 if (strlen(cfg->name) > sizeof(sw->name) - 1)
407                         return -EINVAL;
408                 /* Check whether we only update an existing switch
409                  * or add a new switch. */
410                 sw = find_switch(cfg->gpio, cfg->name);
411                 if (sw != NULL) {
412                         sw->debounce_rising = cfg->debounce_rising;
413                         sw->debounce_falling = cfg->debounce_falling;
414                         sw->notify = cfg->notify;
415                         sw->notify_data = cfg->notify_data;
416                         continue;
417                 } else {
418                         if (cfg->gpio < 0 || cfg->name == NULL) {
419                                 printk("gpio-switch: required switch not "
420                                        "found (%d, %s)\n", cfg->gpio,
421                                        cfg->name);
422                                 continue;
423                         }
424                 }
425                 sw = kzalloc(sizeof(*sw), GFP_KERNEL);
426                 if (sw == NULL) {
427                         printk(KERN_ERR "gpio-switch: kmalloc failed\n");
428                         return -ENOMEM;
429                 }
430                 strlcpy(sw->name, cfg->name, sizeof(sw->name));
431                 sw->gpio = cfg->gpio;
432                 sw->flags = cfg->flags;
433                 sw->type = cfg->type;
434                 sw->debounce_rising = cfg->debounce_rising;
435                 sw->debounce_falling = cfg->debounce_falling;
436                 sw->notify = cfg->notify;
437                 sw->notify_data = cfg->notify_data;
438                 if ((r = new_switch(sw)) < 0) {
439                         kfree(sw);
440                         return r;
441                 }
442         }
443         return 0;
444 }
445
446 static void gpio_sw_cleanup(void)
447 {
448         struct gpio_switch *sw = NULL, *old = NULL;
449
450         list_for_each_entry(sw, &gpio_switches, node) {
451                 if (old != NULL)
452                         kfree(old);
453                 flush_scheduled_work();
454                 del_timer_sync(&sw->timer);
455
456                 free_irq(gpio_to_irq(sw->gpio), sw);
457
458                 device_remove_file(&sw->pdev.dev, &dev_attr_state);
459                 device_remove_file(&sw->pdev.dev, &dev_attr_type);
460                 device_remove_file(&sw->pdev.dev, &dev_attr_direction);
461
462                 platform_device_unregister(&sw->pdev);
463                 gpio_free(sw->gpio);
464                 old = sw;
465         }
466         kfree(old);
467 }
468
469 static void __init report_initial_state(void)
470 {
471         struct gpio_switch *sw;
472
473         list_for_each_entry(sw, &gpio_switches, node) {
474                 int state;
475
476                 state = gpio_get_value(sw->gpio);
477                 if (sw->flags & OMAP_GPIO_SWITCH_FLAG_INVERTED)
478                         state = !state;
479                 if (sw->notify != NULL)
480                         sw->notify(sw->notify_data, state);
481                 print_sw_state(sw, state);
482         }
483 }
484
485 static int gpio_sw_remove(struct platform_device *dev)
486 {
487         return 0;
488 }
489
490 static struct platform_driver gpio_sw_driver = {
491         .remove         = gpio_sw_remove,
492         .driver         = {
493                 .name   = "gpio-switch",
494         },
495 };
496
497 void __init omap_register_gpio_switches(const struct omap_gpio_switch *tbl,
498                                         int count)
499 {
500         BUG_ON(board_gpio_sw_table != NULL);
501
502         board_gpio_sw_table = tbl;
503         board_gpio_sw_count = count;
504 }
505
506 static int __init gpio_sw_init(void)
507 {
508         int r;
509
510         printk(KERN_INFO "OMAP GPIO switch handler initializing\n");
511
512         r = platform_driver_register(&gpio_sw_driver);
513         if (r)
514                 return r;
515
516         gpio_sw_platform_dev = platform_device_register_simple("gpio-switch",
517                                                                -1, NULL, 0);
518         if (IS_ERR(gpio_sw_platform_dev)) {
519                 r = PTR_ERR(gpio_sw_platform_dev);
520                 goto err1;
521         }
522
523         r = add_atag_switches();
524         if (r < 0)
525                 goto err2;
526
527         r = add_board_switches();
528         if (r < 0)
529                 goto err2;
530
531         report_initial_state();
532
533         return 0;
534 err2:
535         gpio_sw_cleanup();
536         platform_device_unregister(gpio_sw_platform_dev);
537 err1:
538         platform_driver_unregister(&gpio_sw_driver);
539         return r;
540 }
541
542 static void __exit gpio_sw_exit(void)
543 {
544         gpio_sw_cleanup();
545         platform_device_unregister(gpio_sw_platform_dev);
546         platform_driver_unregister(&gpio_sw_driver);
547 }
548
549 #ifndef MODULE
550 late_initcall(gpio_sw_init);
551 #else
552 module_init(gpio_sw_init);
553 #endif
554 module_exit(gpio_sw_exit);
555
556 MODULE_AUTHOR("Juha Yrjölä <juha.yrjola@nokia.com>, Paul Mundt <paul.mundt@nokia.com");
557 MODULE_DESCRIPTION("GPIO switch driver");
558 MODULE_LICENSE("GPL");