move new files out from platform support patch
[openwrt/staging/yousong.git] / target / linux / ubicom32 / files / arch / ubicom32 / mach-common / ubicom32input.c
1 /*
2 * arch/ubicom32/mach-common/ubicom32input.c
3 * Ubicom32 Input driver
4 *
5 * based on gpio-keys
6 *
7 * (C) Copyright 2009, Ubicom, Inc.
8 *
9 * This file is part of the Ubicom32 Linux Kernel Port.
10 *
11 * The Ubicom32 Linux Kernel Port is free software: you can redistribute
12 * it and/or modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation, either version 2 of the
14 * License, or (at your option) any later version.
15 *
16 * The Ubicom32 Linux Kernel Port is distributed in the hope that it
17 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
18 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
19 * the GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with the Ubicom32 Linux Kernel Port. If not,
23 * see <http://www.gnu.org/licenses/>.
24 *
25 * Ubicom32 implementation derived from (with many thanks):
26 * arch/m68knommu
27 * arch/blackfin
28 * arch/parisc
29 *
30 *
31 * TODO: add groups for inputs which can be sampled together (i.e. I2C)
32 */
33
34 #include <linux/kernel.h>
35 #include <linux/module.h>
36 #include <linux/platform_device.h>
37 #include <linux/input.h>
38 #include <linux/input-polldev.h>
39 #include <linux/delay.h>
40 #include <linux/gpio.h>
41
42 #include <asm/ubicom32input.h>
43
44 struct ubicom32input_data {
45 struct ubicom32input_platform_data *pdata;
46
47 struct input_polled_dev *poll_dev;
48
49 /*
50 * collection of previous states for buttons
51 */
52 u8 prev_state[0];
53 };
54
55 /*
56 * ubicom32input_poll
57 */
58 static void ubicom32input_poll(struct input_polled_dev *dev)
59 {
60 struct ubicom32input_data *ud =
61 (struct ubicom32input_data *)dev->private;
62 struct ubicom32input_platform_data *pdata = ud->pdata;
63 struct input_dev *id = dev->input;
64 int i;
65 int sync_needed = 0;
66
67 for (i = 0; i < pdata->nbuttons; i++) {
68 const struct ubicom32input_button *ub = &pdata->buttons[i];
69 int state = 0;
70
71 int val = gpio_get_value(ub->gpio);
72
73 /*
74 * Check to see if the state changed from the last time we
75 * looked
76 */
77 if (val == ud->prev_state[i]) {
78 continue;
79 }
80
81 /*
82 * The state has changed, determine if we are "up" or "down"
83 */
84 ud->prev_state[i] = val;
85
86 if ((!val && ub->active_low) || (val && !ub->active_low)) {
87 state = 1;
88 }
89
90 input_event(id, ub->type, ub->code, state);
91 sync_needed = 1;
92 }
93
94 if (sync_needed) {
95 input_sync(id);
96 }
97 }
98
99 /*
100 * ubicom32input_probe
101 */
102 static int __devinit ubicom32input_probe(struct platform_device *pdev)
103 {
104 int i;
105 struct ubicom32input_data *ud;
106 struct input_polled_dev *poll_dev;
107 struct input_dev *input_dev;
108 struct ubicom32input_platform_data *pdata;
109 int ret;
110
111 pdata = pdev->dev.platform_data;
112 if (!pdata) {
113 return -EINVAL;
114 }
115
116 ud = kzalloc(sizeof(struct ubicom32input_data) +
117 pdata->nbuttons, GFP_KERNEL);
118 if (!ud) {
119 return -ENOMEM;
120 }
121 ud->pdata = pdata;
122
123 poll_dev = input_allocate_polled_device();
124 if (!poll_dev) {
125 ret = -ENOMEM;
126 goto fail;
127 }
128
129 platform_set_drvdata(pdev, ud);
130
131 ud->poll_dev = poll_dev;
132 poll_dev->private = ud;
133 poll_dev->poll = ubicom32input_poll;
134
135 /*
136 * Set the poll interval requested, default to 50 msec
137 */
138 if (pdata->poll_interval) {
139 poll_dev->poll_interval = pdata->poll_interval;
140 } else {
141 poll_dev->poll_interval = 50;
142 }
143
144 /*
145 * Setup the input device
146 */
147 input_dev = poll_dev->input;
148 input_dev->name = pdata->name ? pdata->name : "Ubicom32 Input";
149 input_dev->phys = "ubicom32input/input0";
150 input_dev->dev.parent = &pdev->dev;
151 input_dev->id.bustype = BUS_HOST;
152
153 /*
154 * Reserve the GPIOs
155 */
156 for (i = 0; i < pdata->nbuttons; i++) {
157 const struct ubicom32input_button *ub = &pdata->buttons[i];
158
159 ret = gpio_request(ub->gpio,
160 ub->desc ? ub->desc : "ubicom32input");
161 if (ret < 0) {
162 pr_err("ubicom32input: failed to request "
163 "GPIO %d ret=%d\n", ub->gpio, ret);
164 goto fail2;
165 }
166
167 ret = gpio_direction_input(ub->gpio);
168 if (ret < 0) {
169 pr_err("ubicom32input: failed to set "
170 "GPIO %d to input ret=%d\n", ub->gpio, ret);
171 goto fail2;
172 }
173
174 /*
175 * Set the previous state to the non-active stae
176 */
177 ud->prev_state[i] = ub->active_low;
178
179 input_set_capability(input_dev,
180 ub->type ? ub->type : EV_KEY, ub->code);
181 }
182
183 /*
184 * Register
185 */
186 ret = input_register_polled_device(ud->poll_dev);
187 if (ret) {
188 goto fail2;
189 }
190
191 return 0;
192
193 fail2:
194 /*
195 * release the GPIOs we have already requested.
196 */
197 while (--i >= 0) {
198 gpio_free(pdata->buttons[i].gpio);
199 }
200
201 fail:
202 printk(KERN_ERR "Ubicom32Input: Failed to register driver %d", ret);
203 platform_set_drvdata(pdev, NULL);
204 input_free_polled_device(poll_dev);
205 kfree(ud);
206 return ret;
207 }
208
209 /*
210 * ubicom32input_remove
211 */
212 static int __devexit ubicom32input_remove(struct platform_device *dev)
213 {
214 struct ubicom32input_data *ud =
215 (struct ubicom32input_data *)platform_get_drvdata(dev);
216 int i;
217
218 /*
219 * Free the GPIOs
220 */
221 for (i = 0; i < ud->pdata->nbuttons; i++) {
222 gpio_free(ud->pdata->buttons[i].gpio);
223 }
224
225 platform_set_drvdata(dev, NULL);
226 input_unregister_polled_device(ud->poll_dev);
227 input_free_polled_device(ud->poll_dev);
228
229 kfree(ud);
230
231 return 0;
232 }
233
234 static struct platform_driver ubicom32input_driver = {
235 .driver = {
236 .name = "ubicom32input",
237 .owner = THIS_MODULE,
238 },
239 .probe = ubicom32input_probe,
240 .remove = __devexit_p(ubicom32input_remove),
241 };
242
243 /*
244 * ubicom32input_init
245 */
246 static int __devinit ubicom32input_init(void)
247 {
248 return platform_driver_register(&ubicom32input_driver);
249 }
250
251 /*
252 * ubicom32input_exit
253 */
254 static void __exit ubicom32input_exit(void)
255 {
256 platform_driver_unregister(&ubicom32input_driver);
257 }
258
259 module_init(ubicom32input_init);
260 module_exit(ubicom32input_exit);
261
262 MODULE_AUTHOR("Pat Tjin <pattjin@ubicom.com>");
263 MODULE_DESCRIPTION("Ubicom32 Input Driver");
264 MODULE_LICENSE("GPL");
265 MODULE_ALIAS("platform:ubicom32-input");