#include <linux/netlink.h>
#include <net/sock.h>
#include <asm/uaccess.h>
-#include "ar531x.h"
-#include "ar5315/ar5315.h"
+#include <ar531x.h>
-#define AR531X_RESET_GPIO_IRQ (AR531X_GPIO_IRQ_BASE + bcfg->resetConfigGpio)
+#define AR531X_RESET_GPIO_IRQ (AR531X_GPIO_IRQ(bcfg->resetConfigGpio))
struct event_t {
struct work_struct wq;
};
static struct ar531x_boarddata *bcfg;
+static struct timer_list rst_button_timer;
extern struct sock *uevent_sock;
extern u64 uevent_next_seqnum(void);
size_t len;
char *scratch, *s;
char buf[128];
-
+
event = container_of(wq, struct event_t, wq);
if (!uevent_sock)
goto done;
skb = alloc_skb(len + 2048, GFP_KERNEL);
if (!skb)
goto done;
-
+
/* add header */
scratch = skb_put(skb, len);
sprintf(scratch, "%s@",s);
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;
event = (struct event_t *) kzalloc(sizeof(struct event_t), GFP_ATOMIC);
if (!event)
return IRQ_NONE;
-
+
pressed = !pressed;
DO_AR5315(gpio = sysRegRead(AR5315_GPIO_DI);)
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;
}
void ar531x_disable_reset_button(void)
{
- disable_irq(AR531X_RESET_GPIO_IRQ);
+ disable_irq(AR531X_RESET_GPIO_IRQ);
}
EXPORT_SYMBOL(ar531x_disable_reset_button);
bcfg = (struct ar531x_boarddata *) board_config;
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;