Add new function omap_update_gpio_switch() to support dynamically changing the GPIO switch notify callback functions and debounce timeouts. Signed-off-by: Jani Nikula <ext-jani.1.nikula@xxxxxxxxx> --- arch/arm/plat-omap/gpio-switch.c | 39 +++++++++++++++++++++++- arch/arm/plat-omap/include/mach/gpio-switch.h | 7 ++++- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/arch/arm/plat-omap/gpio-switch.c b/arch/arm/plat-omap/gpio-switch.c index 2b5665d..955cd29 100644 --- a/arch/arm/plat-omap/gpio-switch.c +++ b/arch/arm/plat-omap/gpio-switch.c @@ -40,6 +40,7 @@ struct gpio_switch { void (* notify)(void *data, int state); void *notify_data; + spinlock_t lock; struct work_struct work; struct timer_list timer; struct platform_device pdev; @@ -188,6 +189,7 @@ static irqreturn_t gpio_sw_irq_handler(int irq, void *arg) struct gpio_switch *sw = arg; unsigned long timeout; int state; + unsigned long flags; if (!sw->both_edges) { if (gpio_get_value(sw->gpio)) @@ -200,10 +202,13 @@ static irqreturn_t gpio_sw_irq_handler(int irq, void *arg) if (sw->state == state) return IRQ_HANDLED; + spin_lock_irqsave(&sw->lock, flags); if (state) timeout = sw->debounce_rising; else timeout = sw->debounce_falling; + spin_unlock_irqrestore(&sw->lock, flags); + if (!timeout) schedule_work(&sw->work); else @@ -223,14 +228,24 @@ static void gpio_sw_handler(struct work_struct *work) { struct gpio_switch *sw = container_of(work, struct gpio_switch, work); int state; + unsigned long flags; + void (*notify)(void *data, int state); + void *notify_data; state = gpio_sw_get_state(sw); if (sw->state == state) return; sw->state = state; - if (sw->notify != NULL) - sw->notify(sw->notify_data, state); + + spin_lock_irqsave(&sw->lock, flags); + notify = sw->notify; + notify_data = sw->notify_data; + spin_unlock_irqrestore(&sw->lock, flags); + + if (notify != NULL) + notify(notify_data, state); + sysfs_notify(&sw->pdev.dev.kobj, NULL, "state"); print_sw_state(sw, state); } @@ -323,6 +338,7 @@ static int __init new_switch(struct gpio_switch *sw) return r; } + spin_lock_init(&sw->lock); INIT_WORK(&sw->work, gpio_sw_handler); init_timer(&sw->timer); @@ -388,6 +404,25 @@ no_check: return NULL; } +int omap_update_gpio_switch(const struct omap_gpio_switch *cfg) +{ + unsigned long flags; + struct gpio_switch *sw = find_switch(cfg->gpio, cfg->name); + + if (!sw) + return -EINVAL; + + spin_lock_irqsave(&sw->lock, flags); + sw->debounce_rising = cfg->debounce_rising; + sw->debounce_falling = cfg->debounce_falling; + sw->notify = cfg->notify; + sw->notify_data = cfg->notify_data; + spin_unlock_irqrestore(&sw->lock, flags); + + return 0; +} +EXPORT_SYMBOL(omap_update_gpio_switch); + static int __init add_board_switches(void) { int i; diff --git a/arch/arm/plat-omap/include/mach/gpio-switch.h b/arch/arm/plat-omap/include/mach/gpio-switch.h index a143253..53c1fd5 100644 --- a/arch/arm/plat-omap/include/mach/gpio-switch.h +++ b/arch/arm/plat-omap/include/mach/gpio-switch.h @@ -47,12 +47,17 @@ struct omap_gpio_switch { void *notify_data; }; -/* Call at init time only */ #ifdef CONFIG_OMAP_GPIO_SWITCH +/* Call at init time only */ extern void omap_register_gpio_switches(const struct omap_gpio_switch *tbl, int count); +extern int omap_update_gpio_switch(const struct omap_gpio_switch *cfg); #else #define omap_register_gpio_switches(tbl, count) do { } while (0) +static inline int omap_update_gpio_switch(const struct omap_gpio_switch *cfg) +{ + return 0; +} #endif #endif -- 1.6.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html