1 #include <linux/module.h>
2 #include <linux/timer.h>
3 #include <linux/interrupt.h>
4 #include <linux/kobject.h>
5 #include <linux/workqueue.h>
6 #include <linux/skbuff.h>
7 #include <linux/netlink.h>
9 #include <asm/uaccess.h>
12 #define AR531X_RESET_GPIO_IRQ (AR531X_GPIO_IRQ(bcfg->resetConfigGpio))
15 struct work_struct wq;
17 unsigned long jiffies;
20 static struct ar531x_boarddata *bcfg;
21 static struct timer_list rst_button_timer;
23 extern struct sock *uevent_sock;
24 extern u64 uevent_next_seqnum(void);
25 static unsigned long seen;
27 static inline void add_msg(struct sk_buff *skb, char *msg)
30 scratch = skb_put(skb, strlen(msg) + 1);
31 sprintf(scratch, msg);
34 static void hotplug_button(struct work_struct *wq)
37 struct event_t *event;
42 event = container_of(wq, struct event_t, wq);
46 /* allocate message with the maximum possible size */
47 s = event->set ? "pressed" : "released";
49 skb = alloc_skb(len + 2048, GFP_KERNEL);
54 scratch = skb_put(skb, len);
55 sprintf(scratch, "%s@",s);
57 /* copy keys to our continuous event payload buffer */
58 add_msg(skb, "HOME=/");
59 add_msg(skb, "PATH=/sbin:/bin:/usr/sbin:/usr/bin");
60 add_msg(skb, "SUBSYSTEM=button");
61 add_msg(skb, "BUTTON=reset");
62 add_msg(skb, (event->set ? "ACTION=pressed" : "ACTION=released"));
63 sprintf(buf, "SEEN=%ld", (event->jiffies - seen)/HZ);
65 snprintf(buf, 128, "SEQNUM=%llu", uevent_next_seqnum());
68 NETLINK_CB(skb).dst_group = 1;
69 netlink_broadcast(uevent_sock, skb, 0, 1, GFP_KERNEL);
75 static int no_release_workaround = 1;
78 reset_button_poll(unsigned long unused)
80 struct event_t *event;
83 if(!no_release_workaround)
86 DO_AR5315(gpio = sysRegRead(AR5315_GPIO_DI);)
87 gpio &= 1 << (AR531X_RESET_GPIO_IRQ - AR531X_GPIO_IRQ_BASE);
90 rst_button_timer.expires = jiffies + (HZ / 4);
91 add_timer(&rst_button_timer);
93 event = (struct event_t *) kzalloc(sizeof(struct event_t), GFP_ATOMIC);
96 printk("Could not alloc hotplug event\n");
100 event->jiffies = jiffies;
101 INIT_WORK(&event->wq, (void *)(void *)hotplug_button);
102 schedule_work(&event->wq);
106 static irqreturn_t button_handler(int irq, void *dev_id)
108 static int pressed = 0;
109 struct event_t *event;
112 event = (struct event_t *) kzalloc(sizeof(struct event_t), GFP_ATOMIC);
118 DO_AR5315(gpio = sysRegRead(AR5315_GPIO_DI);)
119 gpio &= 1 << (irq - AR531X_GPIO_IRQ_BASE);
123 no_release_workaround = 0;
125 event->jiffies = jiffies;
127 INIT_WORK(&event->wq, (void *)(void *)hotplug_button);
128 schedule_work(&event->wq);
131 if(event->set && no_release_workaround)
132 mod_timer(&rst_button_timer, jiffies + (HZ / 4));
137 void ar531x_disable_reset_button(void)
139 disable_irq(AR531X_RESET_GPIO_IRQ);
142 EXPORT_SYMBOL(ar531x_disable_reset_button);
144 int __init ar531x_init_reset(void)
146 bcfg = (struct ar531x_boarddata *) board_config;
150 init_timer(&rst_button_timer);
151 rst_button_timer.function = reset_button_poll;
152 rst_button_timer.expires = jiffies + HZ / 50;
153 add_timer(&rst_button_timer);
155 request_irq(AR531X_RESET_GPIO_IRQ, &button_handler, IRQF_SAMPLE_RANDOM, "ar531x_reset", NULL);
162 module_init(ar531x_init_reset);