From 5e5cc5a7c80c86b8780902b437354f5dcdb1be54 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 5 Aug 2008 22:17:16 +0000 Subject: [PATCH] add proper uci/hotplug based button handling on atheros and work around boards, where the gpio release irq does not fire correctly SVN-Revision: 12179 --- .../atheros/base-files/etc/config/system | 17 +++++++ .../base-files/etc/hotplug.d/button/00-button | 24 ++++++++++ .../atheros/files/arch/mips/atheros/reset.c | 46 ++++++++++++++++++- 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 target/linux/atheros/base-files/etc/config/system create mode 100644 target/linux/atheros/base-files/etc/hotplug.d/button/00-button diff --git a/target/linux/atheros/base-files/etc/config/system b/target/linux/atheros/base-files/etc/config/system new file mode 100644 index 0000000000..47faa3cc50 --- /dev/null +++ b/target/linux/atheros/base-files/etc/config/system @@ -0,0 +1,17 @@ +config system + option hostname OpenWrt + option timezone UTC + +config button + option button reset + option action released + option handler "logger reboot" + option min 0 + option max 4 + +config button + option button reset + option action released + option handler "logger factory default" + option min 5 + option max 30 diff --git a/target/linux/atheros/base-files/etc/hotplug.d/button/00-button b/target/linux/atheros/base-files/etc/hotplug.d/button/00-button new file mode 100644 index 0000000000..857a59b4a8 --- /dev/null +++ b/target/linux/atheros/base-files/etc/hotplug.d/button/00-button @@ -0,0 +1,24 @@ +. /etc/functions.sh +do_button () { + local button + local action + local handler + local min + local max + + config_get button $1 button + config_get action $1 action + config_get handler $1 handler + config_get min $1 min + config_get max $1 max + + [ "$ACTION" = "$action" -a "$BUTTON" = "$button" -a -n "$handler" ] && { + [ -z "$min" -o -z "$max" ] && eval $handler + [ -n "$min" -a -n "$max" ] && { + [ $min -le $SEEN -a $max -ge $SEEN ] && eval $handler + } + } +} + +config_load system +config_foreach do_button button diff --git a/target/linux/atheros/files/arch/mips/atheros/reset.c b/target/linux/atheros/files/arch/mips/atheros/reset.c index 876fa29ba7..a94954d091 100644 --- a/target/linux/atheros/files/arch/mips/atheros/reset.c +++ b/target/linux/atheros/files/arch/mips/atheros/reset.c @@ -18,6 +18,7 @@ struct event_t { }; static struct ar531x_boarddata *bcfg; +static struct timer_list rst_button_timer; extern struct sock *uevent_sock; extern u64 uevent_next_seqnum(void); @@ -71,6 +72,37 @@ done: kfree(event); } +static int no_release_workaround = 1; + +static void +reset_button_poll(unsigned long unused) +{ + struct event_t *event; + int gpio = ~0; + + if(!no_release_workaround) + return; + + DO_AR5315(gpio = sysRegRead(AR5315_GPIO_DI);) + gpio &= 1 << (AR531X_RESET_GPIO_IRQ - AR531X_GPIO_IRQ_BASE); + if(gpio) + { + rst_button_timer.expires = jiffies + (HZ / 4); + add_timer(&rst_button_timer); + } else { + event = (struct event_t *) kzalloc(sizeof(struct event_t), GFP_ATOMIC); + if (!event) + { + printk("Could not alloc hotplug event\n"); + return; + } + event->set = 0; + event->jiffies = jiffies; + INIT_WORK(&event->wq, (void *)(void *)hotplug_button); + schedule_work(&event->wq); + } +} + static irqreturn_t button_handler(int irq, void *dev_id) { static int pressed = 0; @@ -87,13 +119,20 @@ static irqreturn_t button_handler(int irq, void *dev_id) gpio &= 1 << (irq - AR531X_GPIO_IRQ_BASE); event->set = gpio; + if(!event->set) + no_release_workaround = 0; + event->jiffies = jiffies; INIT_WORK(&event->wq, (void *)(void *)hotplug_button); schedule_work(&event->wq); seen = jiffies; - + if(event->set && no_release_workaround) + { + rst_button_timer.expires = jiffies + (HZ / 4); + add_timer(&rst_button_timer); + } return IRQ_HANDLED; } @@ -110,6 +149,11 @@ int __init ar531x_init_reset(void) seen = jiffies; + init_timer(&rst_button_timer); + rst_button_timer.function = reset_button_poll; + rst_button_timer.expires = jiffies + HZ / 50; + add_timer(&rst_button_timer); + request_irq(AR531X_RESET_GPIO_IRQ, &button_handler, IRQF_SAMPLE_RANDOM, "ar531x_reset", NULL); return 0;