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
This commit is contained in:
John Crispin 2008-08-05 22:17:16 +00:00
parent af76ae2cb5
commit 5e5cc5a7c8
3 changed files with 86 additions and 1 deletions

View file

@ -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

View file

@ -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

View file

@ -18,6 +18,7 @@ struct event_t {
}; };
static struct ar531x_boarddata *bcfg; static struct ar531x_boarddata *bcfg;
static struct timer_list rst_button_timer;
extern struct sock *uevent_sock; extern struct sock *uevent_sock;
extern u64 uevent_next_seqnum(void); extern u64 uevent_next_seqnum(void);
@ -71,6 +72,37 @@ done:
kfree(event); 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 irqreturn_t button_handler(int irq, void *dev_id)
{ {
static int pressed = 0; 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); gpio &= 1 << (irq - AR531X_GPIO_IRQ_BASE);
event->set = gpio; event->set = gpio;
if(!event->set)
no_release_workaround = 0;
event->jiffies = jiffies; event->jiffies = jiffies;
INIT_WORK(&event->wq, (void *)(void *)hotplug_button); INIT_WORK(&event->wq, (void *)(void *)hotplug_button);
schedule_work(&event->wq); schedule_work(&event->wq);
seen = jiffies; seen = jiffies;
if(event->set && no_release_workaround)
{
rst_button_timer.expires = jiffies + (HZ / 4);
add_timer(&rst_button_timer);
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@ -110,6 +149,11 @@ int __init ar531x_init_reset(void)
seen = jiffies; 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); request_irq(AR531X_RESET_GPIO_IRQ, &button_handler, IRQF_SAMPLE_RANDOM, "ar531x_reset", NULL);
return 0; return 0;