ixp4xx: New patch to support FSG-3 buttons
[openwrt.git] / target / linux / ixp4xx / patches / 997-fsg3_buttons.patch
1 diff -Nur linux-2.6.21.6-orig/arch/arm/mach-ixp4xx/fsg-power.c linux-2.6.21.6/arch/arm/mach-ixp4xx/fsg-power.c
2 --- linux-2.6.21.6-orig/arch/arm/mach-ixp4xx/fsg-power.c        1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.6.21.6/arch/arm/mach-ixp4xx/fsg-power.c     2007-10-12 22:32:27.000000000 +0200
4 @@ -0,0 +1,168 @@
5 +/*
6 + * arch/arm/mach-ixp4xx/fsg-power.c
7 + *
8 + * FSG buttons driver
9 + *
10 + * This program is free software; you can redistribute it and/or modify
11 + * it under the terms of the GNU General Public License version 2 as
12 + * published by the Free Software Foundation.
13 + *
14 + */
15 +
16 +#include <linux/module.h>
17 +#include <linux/reboot.h>
18 +#include <linux/irq.h>
19 +#include <linux/interrupt.h>
20 +#include <asm/mach-types.h>
21 +#include <linux/kernel.h>
22 +
23 +struct event_t {
24 +       struct work_struct wq;
25 +       char *button_name;
26 +       int action;
27 +};
28 +
29 +static void hotplug_button(struct event_t *event)
30 +{
31 +       static char buf[128];
32 +       char *argv[3], *envp[6], *action;
33 +       int i;
34 +
35 +        i = 0;
36 +        argv[i++] = "/sbin/hotplug";
37 +        argv[i++] = "button";
38 +        argv[i] = 0;
39 +
40 +       i = 0;
41 +       /* minimal command environment */
42 +       envp [i++] = "HOME=/";
43 +       envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
44 +       envp [i++] = "SUBSYSTEM=button";
45 +
46 +       snprintf(buf, 128, "BUTTON=%s", event->button_name);
47 +       envp [i++] = buf;
48 +
49 +       action = event->action ? "released" : "pressed";
50 +       snprintf(buf, 128, "ACTION=%s", action);
51 +       envp [i++] = buf;
52 +
53 +       envp [i] = 0;
54 +
55 +       // create hotplug event
56 +       call_usermodehelper (argv[0], argv, envp, 0);
57 +
58 +       //destroy event structure
59 +       kfree(event);
60 +}
61 +
62 +static irqreturn_t fsg_sync_button_handler(int irq, void *dev_id)
63 +{
64 +       int holdkey;
65 +
66 +       //check button status
67 +       gpio_line_get(FSG_SB_GPIO, &holdkey);
68 +
69 +       struct event_t *event;
70 +       //create event
71 +       if ((event = (struct event_t *)kzalloc (sizeof(struct event_t), GFP_ATOMIC))) {
72 +               event->action = holdkey;
73 +               event->button_name = "sync";
74 +                       
75 +               INIT_WORK(&event->wq, (void *)(void *)hotplug_button);
76 +               schedule_work(&event->wq);                      
77 +       }
78 +
79 +       return IRQ_HANDLED;
80 +}
81 +
82 +static irqreturn_t fsg_reset_button_handler(int irq, void *dev_id)
83 +{
84 +       int holdkey;
85 +
86 +       //check button status
87 +       gpio_line_get(FSG_RB_GPIO, &holdkey);
88 +
89 +       struct event_t *event;
90 +       //create event
91 +       if ((event = (struct event_t *)kzalloc (sizeof(struct event_t), GFP_ATOMIC))) {
92 +               event->action = holdkey;
93 +               event->button_name = "reset";
94 +                       
95 +               INIT_WORK(&event->wq, (void *)(void *)hotplug_button);
96 +               schedule_work(&event->wq);                      
97 +       }
98 +
99 +       return IRQ_HANDLED;
100 +}
101 +
102 +static irqreturn_t fsg_unplug_button_handler(int irq, void *dev_id)
103 +{
104 +       int holdkey;
105 +
106 +       //check button status
107 +       gpio_line_get(FSG_UB_GPIO, &holdkey);
108 +
109 +       struct event_t *event;
110 +       //create event
111 +       if ((event = (struct event_t *)kzalloc (sizeof(struct event_t), GFP_ATOMIC))) {
112 +               event->action = holdkey;
113 +               event->button_name = "unplug";
114 +                       
115 +               INIT_WORK(&event->wq, (void *)(void *)hotplug_button);
116 +               schedule_work(&event->wq);                      
117 +       }
118 +
119 +       return IRQ_HANDLED;
120 +}
121 +
122 +static int __init fsg_buttons_init(void)
123 +{
124 +       if (!(machine_is_fsg()))
125 +               return;
126 +
127 +       /* Configure interrupt input for SYNC button */
128 +       set_irq_type(FSG_SB_IRQ, IRQT_BOTHEDGE);
129 +       if (request_irq(FSG_SB_IRQ, &fsg_sync_button_handler, IRQF_DISABLED, "SYNC", NULL) < 0) {
130 +               printk(KERN_DEBUG "SYNC button IRQ %d not available\n", FSG_SB_IRQ);
131 +               return -EIO;
132 +       }
133 +       else
134 +               printk("SYNC button registered on IRQ%d\n", FSG_SB_IRQ);
135 +
136 +       /* Configure interrupt input for RESET button */
137 +       set_irq_type(FSG_RB_IRQ, IRQT_BOTHEDGE);
138 +       if (request_irq(FSG_RB_IRQ, &fsg_reset_button_handler, IRQF_DISABLED, "RESET", NULL) < 0) {
139 +               printk(KERN_DEBUG "RESET button IRQ %d not available\n", FSG_RB_IRQ);
140 +               return -EIO;
141 +       }
142 +       else
143 +               printk("RESET button registered on IRQ%d\n", FSG_RB_IRQ);
144 +
145 +       /* Configure interrupt input for UNPLUG button */
146 +       set_irq_type(FSG_UB_IRQ, IRQT_BOTHEDGE);
147 +       if (request_irq(FSG_UB_IRQ, &fsg_unplug_button_handler, IRQF_DISABLED, "RESET", NULL) < 0) {
148 +               printk(KERN_DEBUG "UNPLUG button IRQ %d not available\n", FSG_UB_IRQ);
149 +               return -EIO;
150 +       }
151 +       else
152 +               printk("UNPLUG button registered on IRQ%d\n", FSG_UB_IRQ);
153 +
154 +       return 0;
155 +}
156 +
157 +static void __exit fsg_buttons_exit(void)
158 +{
159 +       if (!(machine_is_fsg()))
160 +               return;
161 +
162 +       free_irq(FSG_SB_IRQ, NULL);
163 +       free_irq(FSG_RB_IRQ, NULL);
164 +       free_irq(FSG_UB_IRQ, NULL);
165 +}
166 +
167 +module_init(fsg_buttons_init);
168 +module_exit(fsg_buttons_exit);
169 +
170 +MODULE_AUTHOR("Zintis Petersons <Zintis.Petersons@e-mail.lv>");
171 +MODULE_DESCRIPTION("FSG buttons driver");
172 +MODULE_LICENSE("GPL");
173 diff -Nur linux-2.6.21.6-orig/arch/arm/mach-ixp4xx/Makefile linux-2.6.21.6/arch/arm/mach-ixp4xx/Makefile
174 --- linux-2.6.21.6-orig/arch/arm/mach-ixp4xx/Makefile   2007-10-12 14:34:18.000000000 +0200
175 +++ linux-2.6.21.6/arch/arm/mach-ixp4xx/Makefile        2007-10-12 22:34:06.000000000 +0200
176 @@ -30,7 +30,7 @@
177  obj-$(CONFIG_MACH_NSLU2)       += nslu2-setup.o nslu2-power.o
178  obj-$(CONFIG_MACH_NAS100D)     += nas100d-setup.o nas100d-power.o
179  obj-$(CONFIG_MACH_DSMG600)      += dsmg600-setup.o dsmg600-power.o
180 -obj-$(CONFIG_MACH_FSG)          += fsg-setup.o
181 +obj-$(CONFIG_MACH_FSG)          += fsg-setup.o fsg-power.o
182  obj-$(CONFIG_MACH_GATEWAY7001) += gateway7001-setup.o
183  obj-$(CONFIG_MACH_WG302V2)     += wg302v2-setup.o
184  obj-$(CONFIG_MACH_PRONGHORNMETRO)      += pronghornmetro-setup.o