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
)
133 rst_button_timer
.expires
= jiffies
+ (HZ
/ 4);
134 add_timer(&rst_button_timer
);
139 void ar531x_disable_reset_button(void)
141 disable_irq(AR531X_RESET_GPIO_IRQ
);
144 EXPORT_SYMBOL(ar531x_disable_reset_button
);
146 int __init
ar531x_init_reset(void)
148 bcfg
= (struct ar531x_boarddata
*) board_config
;
152 init_timer(&rst_button_timer
);
153 rst_button_timer
.function
= reset_button_poll
;
154 rst_button_timer
.expires
= jiffies
+ HZ
/ 50;
155 add_timer(&rst_button_timer
);
157 request_irq(AR531X_RESET_GPIO_IRQ
, &button_handler
, IRQF_SAMPLE_RANDOM
, "ar531x_reset", NULL
);
164 module_init(ar531x_init_reset
);