summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target/linux/atheros/base-files/etc/config/system17
-rw-r--r--target/linux/atheros/base-files/etc/hotplug.d/button/00-button24
-rw-r--r--target/linux/atheros/files/arch/mips/atheros/reset.c46
3 files changed, 86 insertions, 1 deletions
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;