2 * linux/arch/arm/plat-omap/gpio-switch.c
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>
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.
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 <asm/arch/hardware.h>
23 #include <asm/arch/gpio.h>
24 #include <asm/arch/irqs.h>
25 #include <asm/arch/mux.h>
26 #include <asm/arch/board.h>
27 #include <asm/arch/gpio-switch.h>
35 unsigned both_edges:1;
40 void (* notify)(void *data, int state);
43 struct work_struct work;
44 struct timer_list timer;
45 struct platform_device pdev;
47 struct list_head node;
50 static LIST_HEAD(gpio_switches);
51 static struct platform_device *gpio_sw_platform_dev;
52 static struct platform_driver gpio_sw_driver;
54 static const struct omap_gpio_switch *board_gpio_sw_table;
55 static int board_gpio_sw_count;
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" };
62 * GPIO switch state default debounce delay in ms
64 #define OMAP_GPIO_SW_DEFAULT_DEBOUNCE 10
66 static const char **get_sw_str(struct gpio_switch *sw)
69 case OMAP_GPIO_SWITCH_TYPE_COVER:
71 case OMAP_GPIO_SWITCH_TYPE_CONNECTION:
72 return connection_str;
73 case OMAP_GPIO_SWITCH_TYPE_ACTIVITY:
81 static const char *get_sw_type(struct gpio_switch *sw)
84 case OMAP_GPIO_SWITCH_TYPE_COVER:
86 case OMAP_GPIO_SWITCH_TYPE_CONNECTION:
88 case OMAP_GPIO_SWITCH_TYPE_ACTIVITY:
96 static void print_sw_state(struct gpio_switch *sw, int state)
100 str = get_sw_str(sw);
102 printk(KERN_INFO "%s (GPIO %d) is now %s\n", sw->name, sw->gpio, str[state]);
105 static int gpio_sw_get_state(struct gpio_switch *sw)
109 state = omap_get_gpio_datain(sw->gpio);
110 if (sw->flags & OMAP_GPIO_SWITCH_FLAG_INVERTED)
116 static ssize_t gpio_sw_state_store(struct device *dev,
117 struct device_attribute *attr,
121 struct gpio_switch *sw = dev_get_drvdata(dev);
126 if (!(sw->flags & OMAP_GPIO_SWITCH_FLAG_OUTPUT))
129 if (sscanf(buf, "%15s", state) != 1)
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;
140 if (sw->flags & OMAP_GPIO_SWITCH_FLAG_INVERTED)
142 omap_set_gpio_dataout(sw->gpio, enable);
147 static ssize_t gpio_sw_state_show(struct device *dev,
148 struct device_attribute *attr,
151 struct gpio_switch *sw = dev_get_drvdata(dev);
154 str = get_sw_str(sw);
155 return sprintf(buf, "%s\n", str[sw->state]);
158 static DEVICE_ATTR(state, S_IRUGO | S_IWUSR, gpio_sw_state_show,
159 gpio_sw_state_store);
161 static ssize_t gpio_sw_type_show(struct device *dev,
162 struct device_attribute *attr,
165 struct gpio_switch *sw = dev_get_drvdata(dev);
167 return sprintf(buf, "%s\n", get_sw_type(sw));
170 static DEVICE_ATTR(type, S_IRUGO, gpio_sw_type_show, NULL);
172 static ssize_t gpio_sw_direction_show(struct device *dev,
173 struct device_attribute *attr,
176 struct gpio_switch *sw = dev_get_drvdata(dev);
179 is_output = sw->flags & OMAP_GPIO_SWITCH_FLAG_OUTPUT;
180 return sprintf(buf, "%s\n", is_output ? "output" : "input");
183 static DEVICE_ATTR(direction, S_IRUGO, gpio_sw_direction_show, NULL);
186 static irqreturn_t gpio_sw_irq_handler(int irq, void *arg)
188 struct gpio_switch *sw = arg;
189 unsigned long timeout;
192 if (!sw->both_edges) {
193 if (omap_get_gpio_datain(sw->gpio))
194 set_irq_type(OMAP_GPIO_IRQ(sw->gpio), IRQ_TYPE_EDGE_FALLING);
196 set_irq_type(OMAP_GPIO_IRQ(sw->gpio), IRQ_TYPE_EDGE_RISING);
199 state = gpio_sw_get_state(sw);
200 if (sw->state == state)
204 timeout = sw->debounce_rising;
206 timeout = sw->debounce_falling;
208 schedule_work(&sw->work);
210 mod_timer(&sw->timer, jiffies + msecs_to_jiffies(timeout));
215 static void gpio_sw_timer(unsigned long arg)
217 struct gpio_switch *sw = (struct gpio_switch *) arg;
219 schedule_work(&sw->work);
222 static void gpio_sw_handler(struct work_struct *work)
224 struct gpio_switch *sw = container_of(work, struct gpio_switch, work);
227 state = gpio_sw_get_state(sw);
228 if (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);
238 static int __init can_do_both_edges(struct gpio_switch *sw)
240 if (!cpu_class_is_omap1())
242 if (OMAP_GPIO_IS_MPUIO(sw->gpio))
248 static void gpio_sw_release(struct device *dev)
252 static int __init new_switch(struct gpio_switch *sw)
254 int r, direction, trigger;
257 case OMAP_GPIO_SWITCH_TYPE_COVER:
258 case OMAP_GPIO_SWITCH_TYPE_CONNECTION:
259 case OMAP_GPIO_SWITCH_TYPE_ACTIVITY:
262 printk(KERN_ERR "invalid GPIO switch type: %d\n", sw->type);
266 sw->pdev.name = sw->name;
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;
273 r = platform_device_register(&sw->pdev);
275 printk(KERN_ERR "gpio-switch: platform device registration "
276 "failed for %s", sw->name);
279 dev_set_drvdata(&sw->pdev.dev, sw);
281 r = omap_request_gpio(sw->gpio);
283 platform_device_unregister(&sw->pdev);
287 /* input: 1, output: 0 */
288 direction = !(sw->flags & OMAP_GPIO_SWITCH_FLAG_OUTPUT);
289 omap_set_gpio_direction(sw->gpio, direction);
291 sw->state = gpio_sw_get_state(sw);
294 r |= device_create_file(&sw->pdev.dev, &dev_attr_state);
295 r |= device_create_file(&sw->pdev.dev, &dev_attr_type);
296 r |= device_create_file(&sw->pdev.dev, &dev_attr_direction);
298 printk(KERN_ERR "gpio-switch: attribute file creation "
299 "failed for %s\n", sw->name);
304 if (can_do_both_edges(sw)) {
305 trigger = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING;
308 if (omap_get_gpio_datain(sw->gpio))
309 trigger = IRQF_TRIGGER_FALLING;
311 trigger = IRQF_TRIGGER_RISING;
313 r = request_irq(OMAP_GPIO_IRQ(sw->gpio), gpio_sw_irq_handler,
314 IRQF_SHARED | trigger, sw->name, sw);
316 printk(KERN_ERR "gpio-switch: request_irq() failed "
317 "for GPIO %d\n", sw->gpio);
318 platform_device_unregister(&sw->pdev);
319 omap_free_gpio(sw->gpio);
323 INIT_WORK(&sw->work, gpio_sw_handler);
324 init_timer(&sw->timer);
326 sw->timer.function = gpio_sw_timer;
327 sw->timer.data = (unsigned long)sw;
329 list_add(&sw->node, &gpio_switches);
334 static int __init add_atag_switches(void)
336 const struct omap_gpio_switch_config *cfg;
337 struct gpio_switch *sw;
341 cfg = omap_get_nr_config(OMAP_TAG_GPIO_SWITCH,
342 struct omap_gpio_switch_config, i);
345 sw = kzalloc(sizeof(*sw), GFP_KERNEL);
347 printk(KERN_ERR "gpio-switch: kmalloc failed\n");
350 strncpy(sw->name, cfg->name, sizeof(cfg->name));
351 sw->gpio = cfg->gpio;
352 sw->flags = cfg->flags;
353 sw->type = cfg->type;
354 sw->debounce_rising = OMAP_GPIO_SW_DEFAULT_DEBOUNCE;
355 sw->debounce_falling = OMAP_GPIO_SW_DEFAULT_DEBOUNCE;
356 if ((r = new_switch(sw)) < 0) {
364 static struct gpio_switch * __init find_switch(int gpio, const char *name)
366 struct gpio_switch *sw;
368 list_for_each_entry(sw, &gpio_switches, node) {
369 if ((gpio < 0 || sw->gpio != gpio) &&
370 (name == NULL || strcmp(sw->name, name) != 0))
373 if (gpio < 0 || name == NULL)
376 if (strcmp(sw->name, name) != 0)
377 printk("gpio-switch: name mismatch for %d (%s, %s)\n",
378 gpio, name, sw->name);
379 else if (sw->gpio != gpio)
380 printk("gpio-switch: GPIO mismatch for %s (%d, %d)\n",
381 name, gpio, sw->gpio);
388 static int __init add_board_switches(void)
392 for (i = 0; i < board_gpio_sw_count; i++) {
393 const struct omap_gpio_switch *cfg;
394 struct gpio_switch *sw;
397 cfg = board_gpio_sw_table + i;
398 if (strlen(cfg->name) > sizeof(sw->name) - 1)
400 /* Check whether we only update an existing switch
401 * or add a new switch. */
402 sw = find_switch(cfg->gpio, cfg->name);
404 sw->debounce_rising = cfg->debounce_rising;
405 sw->debounce_falling = cfg->debounce_falling;
406 sw->notify = cfg->notify;
407 sw->notify_data = cfg->notify_data;
410 if (cfg->gpio < 0 || cfg->name == NULL) {
411 printk("gpio-switch: required switch not "
412 "found (%d, %s)\n", cfg->gpio,
417 sw = kzalloc(sizeof(*sw), GFP_KERNEL);
419 printk(KERN_ERR "gpio-switch: kmalloc failed\n");
422 strlcpy(sw->name, cfg->name, sizeof(sw->name));
423 sw->gpio = cfg->gpio;
424 sw->flags = cfg->flags;
425 sw->type = cfg->type;
426 sw->debounce_rising = cfg->debounce_rising;
427 sw->debounce_falling = cfg->debounce_falling;
428 sw->notify = cfg->notify;
429 sw->notify_data = cfg->notify_data;
430 if ((r = new_switch(sw)) < 0) {
438 static void gpio_sw_cleanup(void)
440 struct gpio_switch *sw = NULL, *old = NULL;
442 list_for_each_entry(sw, &gpio_switches, node) {
445 flush_scheduled_work();
446 del_timer_sync(&sw->timer);
448 free_irq(OMAP_GPIO_IRQ(sw->gpio), sw);
450 device_remove_file(&sw->pdev.dev, &dev_attr_state);
451 device_remove_file(&sw->pdev.dev, &dev_attr_type);
452 device_remove_file(&sw->pdev.dev, &dev_attr_direction);
454 platform_device_unregister(&sw->pdev);
455 omap_free_gpio(sw->gpio);
461 static void __init report_initial_state(void)
463 struct gpio_switch *sw;
465 list_for_each_entry(sw, &gpio_switches, node) {
468 state = omap_get_gpio_datain(sw->gpio);
469 if (sw->flags & OMAP_GPIO_SWITCH_FLAG_INVERTED)
471 if (sw->notify != NULL)
472 sw->notify(sw->notify_data, state);
473 print_sw_state(sw, state);
477 static int gpio_sw_remove(struct platform_device *dev)
482 static struct platform_driver gpio_sw_driver = {
483 .remove = gpio_sw_remove,
485 .name = "gpio-switch",
489 void __init omap_register_gpio_switches(const struct omap_gpio_switch *tbl,
492 BUG_ON(board_gpio_sw_table != NULL);
494 board_gpio_sw_table = tbl;
495 board_gpio_sw_count = count;
498 static int __init gpio_sw_init(void)
502 printk(KERN_INFO "OMAP GPIO switch handler initializing\n");
504 r = platform_driver_register(&gpio_sw_driver);
508 gpio_sw_platform_dev = platform_device_register_simple("gpio-switch",
510 if (IS_ERR(gpio_sw_platform_dev)) {
511 r = PTR_ERR(gpio_sw_platform_dev);
515 r = add_atag_switches();
519 r = add_board_switches();
523 report_initial_state();
528 platform_device_unregister(gpio_sw_platform_dev);
530 platform_driver_unregister(&gpio_sw_driver);
534 static void __exit gpio_sw_exit(void)
537 platform_device_unregister(gpio_sw_platform_dev);
538 platform_driver_unregister(&gpio_sw_driver);
542 late_initcall(gpio_sw_init);
544 module_init(gpio_sw_init);
546 module_exit(gpio_sw_exit);
548 MODULE_AUTHOR("Juha Yrjölä <juha.yrjola@nokia.com>, Paul Mundt <paul.mundt@nokia.com");
549 MODULE_DESCRIPTION("GPIO switch driver");
550 MODULE_LICENSE("GPL");