]> git.zerfleddert.de Git - ms2-fixes/blob - debounce.c
46c0a63acf465469bc076fd6170c8c9ae751bc1a
[ms2-fixes] / debounce.c
1 #include <linux/module.h>
2 #include <linux/device.h>
3 #include <linux/platform_device.h>
4 #include <linux/gpio_event.h>
5 #include <mach/gpio.h>
6
7 /* hardware debounce: (value + 1) * 31us */
8 #define GPIO_DEBOUNCE_TIME 10240
9
10 #define PREFIX "debounce: "
11
12 static unsigned old_flags = 0;
13 ktime_t old_debounce_delay;
14 ktime_t old_settle_time;
15 ktime_t old_poll_time;
16 static struct gpio_event_matrix_info *gpio_evmi = NULL;
17
18 static int find_ms2_dev(struct device *dev, void *data)
19 {
20 if (!strncmp((char*)data, dev_name(dev), strlen((char*)data))) {
21 printk(KERN_INFO PREFIX "Found it\n");
22 return 1;
23 }
24 return 0;
25 }
26
27 static ssize_t show_debounce_delay(struct device *dev, struct device_attribute *attr, char *buf)
28 {
29 if (!gpio_evmi)
30 return -ENODEV;
31
32 return snprintf(buf, PAGE_SIZE, "%ld\n", (gpio_evmi->debounce_delay.tv.nsec / NSEC_PER_MSEC));
33 }
34
35 static void set_debounce_delay(long delay)
36 {
37 if (gpio_evmi->debounce_delay.tv.nsec != delay * NSEC_PER_MSEC) {
38 printk(KERN_INFO PREFIX "Changing debounce_delay\n");
39 gpio_evmi->debounce_delay.tv.nsec = delay * NSEC_PER_MSEC;
40 printk(KERN_INFO PREFIX "debounce_delay: %u\n", gpio_evmi->debounce_delay.tv.nsec);
41 }
42
43 #if 0
44 if (gpio_evmi->debounce_delay.tv.nsec != 0) {
45 if (!(gpio_evmi->flags & GPIOKPF_DEBOUNCE)) {
46 printk(KERN_INFO PREFIX "Activating debounce\n");
47 gpio_evmi->flags |= GPIOKPF_DEBOUNCE;
48 }
49 } else {
50 if (gpio_evmi->flags & GPIOKPF_DEBOUNCE) {
51 printk(KERN_INFO PREFIX "Deactivating debounce\n");
52 gpio_evmi->flags &= ~GPIOKPF_DEBOUNCE;
53 }
54 }
55 #endif
56 }
57
58 static ssize_t store_debounce_delay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
59 {
60 long int delay;
61
62 if (!gpio_evmi)
63 return -ENODEV;
64
65 sscanf(buf, "%ld", &delay);
66 set_debounce_delay(delay);
67
68 return count;
69 }
70
71 static ssize_t show_settle_time(struct device *dev, struct device_attribute *attr, char *buf)
72 {
73 if (!gpio_evmi)
74 return -ENODEV;
75
76 return snprintf(buf, PAGE_SIZE, "%ld\n", (gpio_evmi->settle_time.tv.nsec / NSEC_PER_USEC));
77 }
78
79 static ssize_t store_settle_time(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
80 {
81 long int delay;
82
83 if (!gpio_evmi)
84 return -ENODEV;
85
86 sscanf(buf, "%ld", &delay);
87 gpio_evmi->settle_time.tv.nsec = delay * NSEC_PER_USEC;
88
89 return count;
90 }
91
92 static ssize_t show_poll_time(struct device *dev, struct device_attribute *attr, char *buf)
93 {
94 if (!gpio_evmi)
95 return -ENODEV;
96
97 return snprintf(buf, PAGE_SIZE, "%ld\n", (gpio_evmi->poll_time.tv.nsec / NSEC_PER_MSEC));
98 }
99
100 static ssize_t store_poll_time(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
101 {
102 long int delay;
103
104 if (!gpio_evmi)
105 return -ENODEV;
106
107 sscanf(buf, "%ld", &delay);
108 gpio_evmi->poll_time.tv.nsec = delay * NSEC_PER_MSEC;
109
110 return count;
111 }
112
113 static ssize_t show_flags(struct device *dev, struct device_attribute *attr, char *buf)
114 {
115 if (!gpio_evmi)
116 return -ENODEV;
117
118 return snprintf(buf, PAGE_SIZE, "0x%x\n", gpio_evmi->flags);
119 }
120
121 static ssize_t store_flags(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
122 {
123 unsigned flags;
124
125 if (!gpio_evmi)
126 return -ENODEV;
127
128 sscanf(buf, "0x%x", &flags);
129
130 printk(KERN_INFO PREFIX "flags: 0x%x\n", flags);
131
132 gpio_evmi->flags = flags;
133
134 return count;
135 }
136
137 static ssize_t show_debounce_flag(struct device *dev, struct device_attribute *attr, char *buf)
138 {
139 if (!gpio_evmi)
140 return -ENODEV;
141
142 return snprintf(buf, PAGE_SIZE, "%u\n", (gpio_evmi->flags & GPIOKPF_DEBOUNCE) ? 1 : 0);
143 }
144
145 static ssize_t store_debounce_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
146 {
147 unsigned flag;
148
149 if (!gpio_evmi)
150 return -ENODEV;
151
152 sscanf(buf, "%u", &flag);
153
154 if (flag) {
155 gpio_evmi->flags |= GPIOKPF_DEBOUNCE;
156 } else {
157 gpio_evmi->flags &= ~GPIOKPF_DEBOUNCE;
158 }
159
160 return count;
161 }
162
163 static ssize_t show_remove_some_phantom_keys_flag(struct device *dev, struct device_attribute *attr, char *buf)
164 {
165 if (!gpio_evmi)
166 return -ENODEV;
167
168 return snprintf(buf, PAGE_SIZE, "%u\n", (gpio_evmi->flags & GPIOKPF_REMOVE_SOME_PHANTOM_KEYS) ? 1 : 0);
169 }
170
171 static ssize_t store_remove_some_phantom_keys_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
172 {
173 unsigned flag;
174
175 if (!gpio_evmi)
176 return -ENODEV;
177
178 sscanf(buf, "%u", &flag);
179
180 if (flag) {
181 gpio_evmi->flags |= GPIOKPF_REMOVE_SOME_PHANTOM_KEYS;
182 } else {
183 gpio_evmi->flags &= ~GPIOKPF_REMOVE_SOME_PHANTOM_KEYS;
184 }
185
186 return count;
187 }
188
189 static ssize_t show_print_unmapped_keys_flag(struct device *dev, struct device_attribute *attr, char *buf)
190 {
191 if (!gpio_evmi)
192 return -ENODEV;
193
194 return snprintf(buf, PAGE_SIZE, "%u\n", (gpio_evmi->flags & GPIOKPF_PRINT_UNMAPPED_KEYS) ? 1 : 0);
195 }
196
197 static ssize_t store_print_unmapped_keys_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
198 {
199 unsigned flag;
200
201 if (!gpio_evmi)
202 return -ENODEV;
203
204 sscanf(buf, "%u", &flag);
205
206 if (flag) {
207 gpio_evmi->flags |= GPIOKPF_PRINT_UNMAPPED_KEYS;
208 } else {
209 gpio_evmi->flags &= ~GPIOKPF_PRINT_UNMAPPED_KEYS;
210 }
211
212 return count;
213 }
214
215 static ssize_t show_print_mapped_keys_flag(struct device *dev, struct device_attribute *attr, char *buf)
216 {
217 if (!gpio_evmi)
218 return -ENODEV;
219
220 return snprintf(buf, PAGE_SIZE, "%u\n", (gpio_evmi->flags & GPIOKPF_PRINT_MAPPED_KEYS) ? 1 : 0);
221 }
222
223 static ssize_t store_print_mapped_keys_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
224 {
225 unsigned flag;
226
227 if (!gpio_evmi)
228 return -ENODEV;
229
230 sscanf(buf, "%u", &flag);
231
232 if (flag) {
233 gpio_evmi->flags |= GPIOKPF_PRINT_MAPPED_KEYS;
234 } else {
235 gpio_evmi->flags &= ~GPIOKPF_PRINT_MAPPED_KEYS;
236 }
237
238 return count;
239 }
240
241 static ssize_t show_print_phantom_keys_flag(struct device *dev, struct device_attribute *attr, char *buf)
242 {
243 if (!gpio_evmi)
244 return -ENODEV;
245
246 return snprintf(buf, PAGE_SIZE, "%u\n", (gpio_evmi->flags & GPIOKPF_PRINT_PHANTOM_KEYS) ? 1 : 0);
247 }
248
249 static ssize_t store_print_phantom_keys_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
250 {
251 unsigned flag;
252
253 if (!gpio_evmi)
254 return -ENODEV;
255
256 sscanf(buf, "%u", &flag);
257
258 if (flag) {
259 gpio_evmi->flags |= GPIOKPF_PRINT_PHANTOM_KEYS;
260 } else {
261 gpio_evmi->flags &= ~GPIOKPF_PRINT_PHANTOM_KEYS;
262 }
263
264 return count;
265 }
266
267 static ssize_t show_active_high_flag(struct device *dev, struct device_attribute *attr, char *buf)
268 {
269 if (!gpio_evmi)
270 return -ENODEV;
271
272 return snprintf(buf, PAGE_SIZE, "%u\n", (gpio_evmi->flags & GPIOKPF_ACTIVE_HIGH) ? 1 : 0);
273 }
274
275 static ssize_t store_active_high_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
276 {
277 unsigned flag;
278
279 if (!gpio_evmi)
280 return -ENODEV;
281
282 sscanf(buf, "%u", &flag);
283
284 if (flag) {
285 gpio_evmi->flags |= GPIOKPF_ACTIVE_HIGH;
286 } else {
287 gpio_evmi->flags &= ~GPIOKPF_ACTIVE_HIGH;
288 }
289
290 return count;
291 }
292
293 static ssize_t show_drive_inactive_flag(struct device *dev, struct device_attribute *attr, char *buf)
294 {
295 if (!gpio_evmi)
296 return -ENODEV;
297
298 return snprintf(buf, PAGE_SIZE, "%u\n", (gpio_evmi->flags & GPIOKPF_DRIVE_INACTIVE) ? 1 : 0);
299 }
300
301 static ssize_t store_drive_inactive_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
302 {
303 unsigned flag;
304
305 if (!gpio_evmi)
306 return -ENODEV;
307
308 sscanf(buf, "%u", &flag);
309
310 if (flag) {
311 gpio_evmi->flags |= GPIOKPF_DRIVE_INACTIVE;
312 } else {
313 gpio_evmi->flags &= ~GPIOKPF_DRIVE_INACTIVE;
314 }
315
316 return count;
317 }
318
319 static DEVICE_ATTR(debounce_delay, (S_IRUGO | S_IWUGO), show_debounce_delay, store_debounce_delay);
320 static DEVICE_ATTR(settle_time, (S_IRUGO | S_IWUGO), show_settle_time, store_settle_time);
321 static DEVICE_ATTR(poll_time, (S_IRUGO | S_IWUGO), show_poll_time, store_poll_time);
322 static DEVICE_ATTR(flags, (S_IRUGO), show_flags, store_flags);
323 static DEVICE_ATTR(debounce_flag, (S_IRUGO | S_IWUGO), show_debounce_flag, store_debounce_flag);
324 static DEVICE_ATTR(remove_some_phantom_keys_flag, (S_IRUGO | S_IWUGO), show_remove_some_phantom_keys_flag, store_remove_some_phantom_keys_flag);
325 static DEVICE_ATTR(print_unmapped_keys_flag, (S_IRUGO | S_IWUGO), show_print_unmapped_keys_flag, store_print_unmapped_keys_flag);
326 static DEVICE_ATTR(print_mapped_keys_flag, (S_IRUGO | S_IWUGO), show_print_mapped_keys_flag, store_print_mapped_keys_flag);
327 static DEVICE_ATTR(print_phantom_keys_flag, (S_IRUGO | S_IWUGO), show_print_phantom_keys_flag, store_print_phantom_keys_flag);
328 static DEVICE_ATTR(active_high_flag, (S_IRUGO), show_active_high_flag, store_active_high_flag);
329 static DEVICE_ATTR(drive_inactive_flag, (S_IRUGO | S_IWUGO), show_drive_inactive_flag, store_drive_inactive_flag);
330
331 static void debounce_release(struct device *dev)
332 {
333 }
334
335 static struct device debounce_device = {
336 .init_name = "debounce",
337 .release = debounce_release,
338 };
339
340 static unsigned int mapphone_col_gpios[] = { 43, 53, 54, 55, 56, 57, 58, 63 };
341 static unsigned int mapphone_row_gpios[] = { 34, 35, 36, 37, 38, 39, 40, 41 };
342
343 static void hw_debounce_pin(int gpio, int enable) {
344 printk(KERN_INFO PREFIX "%sabling hardware debounce for GPIO %d\n", (enable?"En":"Dis"), gpio);
345 if (enable)
346 omap_set_gpio_debounce_time(gpio, GPIO_DEBOUNCE_TIME);
347 omap_set_gpio_debounce(gpio, enable);
348 }
349
350 static void hw_debounce(int enable) {
351 int i;
352
353 for (i = 0; i < (sizeof(mapphone_col_gpios) / sizeof(mapphone_col_gpios[0])); i++) {
354 hw_debounce_pin(mapphone_col_gpios[i], enable);
355 }
356
357 for (i = 0; i < (sizeof(mapphone_row_gpios) / sizeof(mapphone_row_gpios[0])); i++) {
358 hw_debounce_pin(mapphone_row_gpios[i], enable);
359 }
360 }
361
362 static int __init debounce_init(void)
363 {
364 struct device *event_dev = NULL;
365 struct gpio_event_platform_data *gpio_epd;
366 struct gpio_event_info *gpio_ei;
367 int err = 0;
368
369 printk(KERN_INFO PREFIX "Searching for " GPIO_EVENT_DEV_NAME "...\n");
370
371 event_dev = device_find_child(&platform_bus, GPIO_EVENT_DEV_NAME, find_ms2_dev);
372 if (event_dev == NULL)
373 return -ENODEV;
374
375 gpio_epd = (struct gpio_event_platform_data*)event_dev->platform_data;
376 printk(KERN_INFO PREFIX "And there is a %s connected...\n", gpio_epd->name);
377 if (strcmp(gpio_epd->name, "sholes-keypad"))
378 return -ENODEV;
379
380 gpio_ei = (struct gpio_event_info*)gpio_epd->info[0];
381 gpio_evmi = container_of(gpio_ei, struct gpio_event_matrix_info, info);
382
383 err = device_register(&debounce_device);
384 if (err) {
385 return err;
386 }
387
388 hw_debounce(1);
389
390 err = device_create_file(&debounce_device, &dev_attr_debounce_delay);
391 err = device_create_file(&debounce_device, &dev_attr_settle_time);
392 err = device_create_file(&debounce_device, &dev_attr_poll_time);
393 err = device_create_file(&debounce_device, &dev_attr_flags);
394 err = device_create_file(&debounce_device, &dev_attr_debounce_flag);
395 err = device_create_file(&debounce_device, &dev_attr_remove_some_phantom_keys_flag);
396 err = device_create_file(&debounce_device, &dev_attr_print_unmapped_keys_flag);
397 err = device_create_file(&debounce_device, &dev_attr_print_mapped_keys_flag);
398 err = device_create_file(&debounce_device, &dev_attr_print_phantom_keys_flag);
399 err = device_create_file(&debounce_device, &dev_attr_active_high_flag);
400 err = device_create_file(&debounce_device, &dev_attr_drive_inactive_flag);
401
402 printk(KERN_INFO PREFIX "settle_time: %u\n", gpio_evmi->settle_time.tv.nsec);
403 printk(KERN_INFO PREFIX "poll_time: %u\n", gpio_evmi->poll_time.tv.nsec);
404 printk(KERN_INFO PREFIX "debounce_delay: %u\n", gpio_evmi->debounce_delay.tv.nsec);
405 printk(KERN_INFO PREFIX "flags: 0x%x\n", gpio_evmi->flags);
406
407 old_debounce_delay = gpio_evmi->debounce_delay;
408 old_settle_time = gpio_evmi->settle_time;
409 old_poll_time = gpio_evmi->poll_time;
410 old_flags = gpio_evmi->flags;
411
412 printk(KERN_INFO PREFIX "flags: 0x%x\n", gpio_evmi->flags);
413
414 return 0;
415 }
416
417 static void __exit debounce_exit(void)
418 {
419 if (gpio_evmi) {
420 if (gpio_evmi->debounce_delay.tv.nsec != old_debounce_delay.tv.nsec) {
421 printk(KERN_INFO PREFIX "Restoring debounce_delay\n");
422 gpio_evmi->debounce_delay = old_debounce_delay;
423 printk(KERN_INFO PREFIX "debounce_delay: %u\n", gpio_evmi->debounce_delay.tv.nsec);
424 }
425 if (gpio_evmi->flags != old_flags) {
426 printk(KERN_INFO PREFIX "Restoring flags\n");
427 gpio_evmi->flags = old_flags;
428 printk(KERN_INFO PREFIX "flags: 0x%x\n", gpio_evmi->flags);
429 }
430 gpio_evmi->settle_time = old_settle_time;
431 gpio_evmi->poll_time = old_poll_time;
432 }
433 hw_debounce(0);
434 device_remove_file(&debounce_device, &dev_attr_debounce_delay);
435 device_remove_file(&debounce_device, &dev_attr_settle_time);
436 device_remove_file(&debounce_device, &dev_attr_poll_time);
437 device_remove_file(&debounce_device, &dev_attr_flags);
438 device_remove_file(&debounce_device, &dev_attr_debounce_flag);
439 device_remove_file(&debounce_device, &dev_attr_remove_some_phantom_keys_flag);
440 device_remove_file(&debounce_device, &dev_attr_print_unmapped_keys_flag);
441 device_remove_file(&debounce_device, &dev_attr_print_mapped_keys_flag);
442 device_remove_file(&debounce_device, &dev_attr_print_phantom_keys_flag);
443 device_remove_file(&debounce_device, &dev_attr_active_high_flag);
444 device_remove_file(&debounce_device, &dev_attr_drive_inactive_flag);
445 device_unregister(&debounce_device);
446 }
447
448 module_init(debounce_init);
449 module_exit(debounce_exit);
450
451 MODULE_LICENSE("GPL");
452 MODULE_AUTHOR("Michael Gernoth <michael@gernoth.net>");
Impressum, Datenschutz