diff options
Diffstat (limited to 'drivers/input/keyboard')
24 files changed, 608 insertions, 149 deletions
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 62a2c0e4cc99..269d4c3658cb 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -418,6 +418,16 @@ config KEYBOARD_NOMADIK | |||
418 | To compile this driver as a module, choose M here: the | 418 | To compile this driver as a module, choose M here: the |
419 | module will be called nmk-ske-keypad. | 419 | module will be called nmk-ske-keypad. |
420 | 420 | ||
421 | config KEYBOARD_NSPIRE | ||
422 | tristate "TI-NSPIRE built-in keyboard" | ||
423 | depends on ARCH_NSPIRE && OF | ||
424 | select INPUT_MATRIXKMAP | ||
425 | help | ||
426 | Say Y here if you want to use the built-in keypad on TI-NSPIRE. | ||
427 | |||
428 | To compile this driver as a module, choose M here: the | ||
429 | module will be called nspire-keypad. | ||
430 | |||
421 | config KEYBOARD_TEGRA | 431 | config KEYBOARD_TEGRA |
422 | tristate "NVIDIA Tegra internal matrix keyboard controller support" | 432 | tristate "NVIDIA Tegra internal matrix keyboard controller support" |
423 | depends on ARCH_TEGRA && OF | 433 | depends on ARCH_TEGRA && OF |
@@ -431,6 +441,7 @@ config KEYBOARD_TEGRA | |||
431 | 441 | ||
432 | config KEYBOARD_OPENCORES | 442 | config KEYBOARD_OPENCORES |
433 | tristate "OpenCores Keyboard Controller" | 443 | tristate "OpenCores Keyboard Controller" |
444 | depends on HAS_IOMEM | ||
434 | help | 445 | help |
435 | Say Y here if you want to use the OpenCores Keyboard Controller | 446 | Say Y here if you want to use the OpenCores Keyboard Controller |
436 | http://www.opencores.org/project,keyboardcontroller | 447 | http://www.opencores.org/project,keyboardcontroller |
@@ -441,6 +452,7 @@ config KEYBOARD_OPENCORES | |||
441 | config KEYBOARD_PXA27x | 452 | config KEYBOARD_PXA27x |
442 | tristate "PXA27x/PXA3xx keypad support" | 453 | tristate "PXA27x/PXA3xx keypad support" |
443 | depends on PXA27x || PXA3xx || ARCH_MMP | 454 | depends on PXA27x || PXA3xx || ARCH_MMP |
455 | select INPUT_MATRIXKMAP | ||
444 | help | 456 | help |
445 | Enable support for PXA27x/PXA3xx keypad controller. | 457 | Enable support for PXA27x/PXA3xx keypad controller. |
446 | 458 | ||
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 0c43e8cf8d0e..a699b6172303 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -36,6 +36,7 @@ obj-$(CONFIG_KEYBOARD_MCS) += mcs_touchkey.o | |||
36 | obj-$(CONFIG_KEYBOARD_MPR121) += mpr121_touchkey.o | 36 | obj-$(CONFIG_KEYBOARD_MPR121) += mpr121_touchkey.o |
37 | obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o | 37 | obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o |
38 | obj-$(CONFIG_KEYBOARD_NOMADIK) += nomadik-ske-keypad.o | 38 | obj-$(CONFIG_KEYBOARD_NOMADIK) += nomadik-ske-keypad.o |
39 | obj-$(CONFIG_KEYBOARD_NSPIRE) += nspire-keypad.o | ||
39 | obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o | 40 | obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o |
40 | obj-$(CONFIG_KEYBOARD_OMAP4) += omap4-keypad.o | 41 | obj-$(CONFIG_KEYBOARD_OMAP4) += omap4-keypad.o |
41 | obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.o | 42 | obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.o |
diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c index ba0b36f7daea..096d6067ae1f 100644 --- a/drivers/input/keyboard/amikbd.c +++ b/drivers/input/keyboard/amikbd.c | |||
@@ -246,7 +246,6 @@ static int __exit amikbd_remove(struct platform_device *pdev) | |||
246 | { | 246 | { |
247 | struct input_dev *dev = platform_get_drvdata(pdev); | 247 | struct input_dev *dev = platform_get_drvdata(pdev); |
248 | 248 | ||
249 | platform_set_drvdata(pdev, NULL); | ||
250 | free_irq(IRQ_AMIGA_CIAA_SP, dev); | 249 | free_irq(IRQ_AMIGA_CIAA_SP, dev); |
251 | input_unregister_device(dev); | 250 | input_unregister_device(dev); |
252 | return 0; | 251 | return 0; |
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index 20b9fa91fb9e..fc88fb48d70d 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c | |||
@@ -326,7 +326,6 @@ out0: | |||
326 | kfree(bf54x_kpad->keycode); | 326 | kfree(bf54x_kpad->keycode); |
327 | out: | 327 | out: |
328 | kfree(bf54x_kpad); | 328 | kfree(bf54x_kpad); |
329 | platform_set_drvdata(pdev, NULL); | ||
330 | 329 | ||
331 | return error; | 330 | return error; |
332 | } | 331 | } |
@@ -346,7 +345,6 @@ static int bfin_kpad_remove(struct platform_device *pdev) | |||
346 | 345 | ||
347 | kfree(bf54x_kpad->keycode); | 346 | kfree(bf54x_kpad->keycode); |
348 | kfree(bf54x_kpad); | 347 | kfree(bf54x_kpad); |
349 | platform_set_drvdata(pdev, NULL); | ||
350 | 348 | ||
351 | return 0; | 349 | return 0; |
352 | } | 350 | } |
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index 49557f27bfa6..7e8b0a52af25 100644 --- a/drivers/input/keyboard/cros_ec_keyb.c +++ b/drivers/input/keyboard/cros_ec_keyb.c | |||
@@ -206,33 +206,6 @@ static int cros_ec_keyb_work(struct notifier_block *nb, | |||
206 | return NOTIFY_DONE; | 206 | return NOTIFY_DONE; |
207 | } | 207 | } |
208 | 208 | ||
209 | /* Clear any keys in the buffer */ | ||
210 | static void cros_ec_keyb_clear_keyboard(struct cros_ec_keyb *ckdev) | ||
211 | { | ||
212 | uint8_t old_state[ckdev->cols]; | ||
213 | uint8_t new_state[ckdev->cols]; | ||
214 | unsigned long duration; | ||
215 | int i, ret; | ||
216 | |||
217 | /* | ||
218 | * Keep reading until we see that the scan state does not change. | ||
219 | * That indicates that we are done. | ||
220 | * | ||
221 | * Assume that the EC keyscan buffer is at most 32 deep. | ||
222 | */ | ||
223 | duration = jiffies; | ||
224 | ret = cros_ec_keyb_get_state(ckdev, new_state); | ||
225 | for (i = 1; !ret && i < 32; i++) { | ||
226 | memcpy(old_state, new_state, sizeof(old_state)); | ||
227 | ret = cros_ec_keyb_get_state(ckdev, new_state); | ||
228 | if (0 == memcmp(old_state, new_state, sizeof(old_state))) | ||
229 | break; | ||
230 | } | ||
231 | duration = jiffies - duration; | ||
232 | dev_info(ckdev->dev, "Discarded %d keyscan(s) in %dus\n", i, | ||
233 | jiffies_to_usecs(duration)); | ||
234 | } | ||
235 | |||
236 | static int cros_ec_keyb_probe(struct platform_device *pdev) | 209 | static int cros_ec_keyb_probe(struct platform_device *pdev) |
237 | { | 210 | { |
238 | struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent); | 211 | struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent); |
@@ -299,6 +272,33 @@ static int cros_ec_keyb_probe(struct platform_device *pdev) | |||
299 | } | 272 | } |
300 | 273 | ||
301 | #ifdef CONFIG_PM_SLEEP | 274 | #ifdef CONFIG_PM_SLEEP |
275 | /* Clear any keys in the buffer */ | ||
276 | static void cros_ec_keyb_clear_keyboard(struct cros_ec_keyb *ckdev) | ||
277 | { | ||
278 | uint8_t old_state[ckdev->cols]; | ||
279 | uint8_t new_state[ckdev->cols]; | ||
280 | unsigned long duration; | ||
281 | int i, ret; | ||
282 | |||
283 | /* | ||
284 | * Keep reading until we see that the scan state does not change. | ||
285 | * That indicates that we are done. | ||
286 | * | ||
287 | * Assume that the EC keyscan buffer is at most 32 deep. | ||
288 | */ | ||
289 | duration = jiffies; | ||
290 | ret = cros_ec_keyb_get_state(ckdev, new_state); | ||
291 | for (i = 1; !ret && i < 32; i++) { | ||
292 | memcpy(old_state, new_state, sizeof(old_state)); | ||
293 | ret = cros_ec_keyb_get_state(ckdev, new_state); | ||
294 | if (0 == memcmp(old_state, new_state, sizeof(old_state))) | ||
295 | break; | ||
296 | } | ||
297 | duration = jiffies - duration; | ||
298 | dev_info(ckdev->dev, "Discarded %d keyscan(s) in %dus\n", i, | ||
299 | jiffies_to_usecs(duration)); | ||
300 | } | ||
301 | |||
302 | static int cros_ec_keyb_resume(struct device *dev) | 302 | static int cros_ec_keyb_resume(struct device *dev) |
303 | { | 303 | { |
304 | struct cros_ec_keyb *ckdev = dev_get_drvdata(dev); | 304 | struct cros_ec_keyb *ckdev = dev_get_drvdata(dev); |
diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c index 829753702b62..d15977a8361e 100644 --- a/drivers/input/keyboard/davinci_keyscan.c +++ b/drivers/input/keyboard/davinci_keyscan.c | |||
@@ -314,8 +314,6 @@ static int davinci_ks_remove(struct platform_device *pdev) | |||
314 | iounmap(davinci_ks->base); | 314 | iounmap(davinci_ks->base); |
315 | release_mem_region(davinci_ks->pbase, davinci_ks->base_size); | 315 | release_mem_region(davinci_ks->pbase, davinci_ks->base_size); |
316 | 316 | ||
317 | platform_set_drvdata(pdev, NULL); | ||
318 | |||
319 | kfree(davinci_ks); | 317 | kfree(davinci_ks); |
320 | 318 | ||
321 | return 0; | 319 | return 0; |
diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c index 9857e8fd0987..47206bdba411 100644 --- a/drivers/input/keyboard/ep93xx_keypad.c +++ b/drivers/input/keyboard/ep93xx_keypad.c | |||
@@ -329,8 +329,7 @@ static int ep93xx_keypad_probe(struct platform_device *pdev) | |||
329 | return 0; | 329 | return 0; |
330 | 330 | ||
331 | failed_free_irq: | 331 | failed_free_irq: |
332 | free_irq(keypad->irq, pdev); | 332 | free_irq(keypad->irq, keypad); |
333 | platform_set_drvdata(pdev, NULL); | ||
334 | failed_free_dev: | 333 | failed_free_dev: |
335 | input_free_device(input_dev); | 334 | input_free_device(input_dev); |
336 | failed_put_clk: | 335 | failed_put_clk: |
@@ -351,9 +350,7 @@ static int ep93xx_keypad_remove(struct platform_device *pdev) | |||
351 | struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); | 350 | struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); |
352 | struct resource *res; | 351 | struct resource *res; |
353 | 352 | ||
354 | free_irq(keypad->irq, pdev); | 353 | free_irq(keypad->irq, keypad); |
355 | |||
356 | platform_set_drvdata(pdev, NULL); | ||
357 | 354 | ||
358 | if (keypad->enabled) | 355 | if (keypad->enabled) |
359 | clk_disable(keypad->clk); | 356 | clk_disable(keypad->clk); |
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index b29ca651a395..440ce32462ba 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
@@ -767,7 +767,6 @@ static int gpio_keys_probe(struct platform_device *pdev) | |||
767 | while (--i >= 0) | 767 | while (--i >= 0) |
768 | gpio_remove_key(&ddata->data[i]); | 768 | gpio_remove_key(&ddata->data[i]); |
769 | 769 | ||
770 | platform_set_drvdata(pdev, NULL); | ||
771 | fail1: | 770 | fail1: |
772 | input_free_device(input); | 771 | input_free_device(input); |
773 | kfree(ddata); | 772 | kfree(ddata); |
diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index 21147164874d..cd5ed9e22168 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c | |||
@@ -324,7 +324,6 @@ err_free_gpio: | |||
324 | 324 | ||
325 | err_free_bdev: | 325 | err_free_bdev: |
326 | kfree(bdev); | 326 | kfree(bdev); |
327 | platform_set_drvdata(pdev, NULL); | ||
328 | 327 | ||
329 | err_free_pdata: | 328 | err_free_pdata: |
330 | /* If we have no platform_data, we allocated pdata dynamically. */ | 329 | /* If we have no platform_data, we allocated pdata dynamically. */ |
@@ -355,7 +354,6 @@ static int gpio_keys_polled_remove(struct platform_device *pdev) | |||
355 | kfree(pdata); | 354 | kfree(pdata); |
356 | 355 | ||
357 | kfree(bdev); | 356 | kfree(bdev); |
358 | platform_set_drvdata(pdev, NULL); | ||
359 | 357 | ||
360 | return 0; | 358 | return 0; |
361 | } | 359 | } |
diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c index 74e75a6e8deb..a2a034c25f0b 100644 --- a/drivers/input/keyboard/jornada680_kbd.c +++ b/drivers/input/keyboard/jornada680_kbd.c | |||
@@ -233,7 +233,6 @@ static int jornada680kbd_probe(struct platform_device *pdev) | |||
233 | failed: | 233 | failed: |
234 | printk(KERN_ERR "Jornadakbd: failed to register driver, error: %d\n", | 234 | printk(KERN_ERR "Jornadakbd: failed to register driver, error: %d\n", |
235 | error); | 235 | error); |
236 | platform_set_drvdata(pdev, NULL); | ||
237 | input_free_polled_device(poll_dev); | 236 | input_free_polled_device(poll_dev); |
238 | kfree(jornadakbd); | 237 | kfree(jornadakbd); |
239 | return error; | 238 | return error; |
@@ -244,7 +243,6 @@ static int jornada680kbd_remove(struct platform_device *pdev) | |||
244 | { | 243 | { |
245 | struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); | 244 | struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); |
246 | 245 | ||
247 | platform_set_drvdata(pdev, NULL); | ||
248 | input_unregister_polled_device(jornadakbd->poll_dev); | 246 | input_unregister_polled_device(jornadakbd->poll_dev); |
249 | input_free_polled_device(jornadakbd->poll_dev); | 247 | input_free_polled_device(jornadakbd->poll_dev); |
250 | kfree(jornadakbd); | 248 | kfree(jornadakbd); |
diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c index 5ceef636df2f..b0ad457ca9d8 100644 --- a/drivers/input/keyboard/jornada720_kbd.c +++ b/drivers/input/keyboard/jornada720_kbd.c | |||
@@ -146,7 +146,6 @@ static int jornada720_kbd_probe(struct platform_device *pdev) | |||
146 | fail2: /* IRQ, DEVICE, MEMORY */ | 146 | fail2: /* IRQ, DEVICE, MEMORY */ |
147 | free_irq(IRQ_GPIO0, pdev); | 147 | free_irq(IRQ_GPIO0, pdev); |
148 | fail1: /* DEVICE, MEMORY */ | 148 | fail1: /* DEVICE, MEMORY */ |
149 | platform_set_drvdata(pdev, NULL); | ||
150 | input_free_device(input_dev); | 149 | input_free_device(input_dev); |
151 | kfree(jornadakbd); | 150 | kfree(jornadakbd); |
152 | return err; | 151 | return err; |
@@ -157,7 +156,6 @@ static int jornada720_kbd_remove(struct platform_device *pdev) | |||
157 | struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); | 156 | struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); |
158 | 157 | ||
159 | free_irq(IRQ_GPIO0, pdev); | 158 | free_irq(IRQ_GPIO0, pdev); |
160 | platform_set_drvdata(pdev, NULL); | ||
161 | input_unregister_device(jornadakbd->input); | 159 | input_unregister_device(jornadakbd->input); |
162 | kfree(jornadakbd); | 160 | kfree(jornadakbd); |
163 | 161 | ||
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 71d77192ac1e..90ff73ace424 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c | |||
@@ -549,8 +549,6 @@ static int matrix_keypad_remove(struct platform_device *pdev) | |||
549 | input_unregister_device(keypad->input_dev); | 549 | input_unregister_device(keypad->input_dev); |
550 | kfree(keypad); | 550 | kfree(keypad); |
551 | 551 | ||
552 | platform_set_drvdata(pdev, NULL); | ||
553 | |||
554 | return 0; | 552 | return 0; |
555 | } | 553 | } |
556 | 554 | ||
diff --git a/drivers/input/keyboard/nspire-keypad.c b/drivers/input/keyboard/nspire-keypad.c new file mode 100644 index 000000000000..e0a1339e40e6 --- /dev/null +++ b/drivers/input/keyboard/nspire-keypad.c | |||
@@ -0,0 +1,283 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2, as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/input/matrix_keypad.h> | ||
10 | #include <linux/platform_device.h> | ||
11 | #include <linux/interrupt.h> | ||
12 | #include <linux/io.h> | ||
13 | #include <linux/delay.h> | ||
14 | #include <linux/input.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/clk.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/of.h> | ||
19 | |||
20 | #define KEYPAD_SCAN_MODE 0x00 | ||
21 | #define KEYPAD_CNTL 0x04 | ||
22 | #define KEYPAD_INT 0x08 | ||
23 | #define KEYPAD_INTMSK 0x0C | ||
24 | |||
25 | #define KEYPAD_DATA 0x10 | ||
26 | #define KEYPAD_GPIO 0x30 | ||
27 | |||
28 | #define KEYPAD_UNKNOWN_INT 0x40 | ||
29 | #define KEYPAD_UNKNOWN_INT_STS 0x44 | ||
30 | |||
31 | #define KEYPAD_BITMASK_COLS 11 | ||
32 | #define KEYPAD_BITMASK_ROWS 8 | ||
33 | |||
34 | struct nspire_keypad { | ||
35 | void __iomem *reg_base; | ||
36 | u32 int_mask; | ||
37 | |||
38 | struct input_dev *input; | ||
39 | struct clk *clk; | ||
40 | |||
41 | struct matrix_keymap_data *keymap; | ||
42 | int row_shift; | ||
43 | |||
44 | /* Maximum delay estimated assuming 33MHz APB */ | ||
45 | u32 scan_interval; /* In microseconds (~2000us max) */ | ||
46 | u32 row_delay; /* In microseconds (~500us max) */ | ||
47 | |||
48 | u16 state[KEYPAD_BITMASK_ROWS]; | ||
49 | |||
50 | bool active_low; | ||
51 | }; | ||
52 | |||
53 | static irqreturn_t nspire_keypad_irq(int irq, void *dev_id) | ||
54 | { | ||
55 | struct nspire_keypad *keypad = dev_id; | ||
56 | struct input_dev *input = keypad->input; | ||
57 | unsigned short *keymap = input->keycode; | ||
58 | unsigned int code; | ||
59 | int row, col; | ||
60 | u32 int_sts; | ||
61 | u16 state[8]; | ||
62 | u16 bits, changed; | ||
63 | |||
64 | int_sts = readl(keypad->reg_base + KEYPAD_INT) & keypad->int_mask; | ||
65 | if (!int_sts) | ||
66 | return IRQ_NONE; | ||
67 | |||
68 | memcpy_fromio(state, keypad->reg_base + KEYPAD_DATA, sizeof(state)); | ||
69 | |||
70 | for (row = 0; row < KEYPAD_BITMASK_ROWS; row++) { | ||
71 | bits = state[row]; | ||
72 | if (keypad->active_low) | ||
73 | bits = ~bits; | ||
74 | |||
75 | changed = bits ^ keypad->state[row]; | ||
76 | if (!changed) | ||
77 | continue; | ||
78 | |||
79 | keypad->state[row] = bits; | ||
80 | |||
81 | for (col = 0; col < KEYPAD_BITMASK_COLS; col++) { | ||
82 | if (!(changed & (1U << col))) | ||
83 | continue; | ||
84 | |||
85 | code = MATRIX_SCAN_CODE(row, col, keypad->row_shift); | ||
86 | input_event(input, EV_MSC, MSC_SCAN, code); | ||
87 | input_report_key(input, keymap[code], | ||
88 | bits & (1U << col)); | ||
89 | } | ||
90 | } | ||
91 | |||
92 | input_sync(input); | ||
93 | |||
94 | writel(0x3, keypad->reg_base + KEYPAD_INT); | ||
95 | |||
96 | return IRQ_HANDLED; | ||
97 | } | ||
98 | |||
99 | static int nspire_keypad_chip_init(struct nspire_keypad *keypad) | ||
100 | { | ||
101 | unsigned long val = 0, cycles_per_us, delay_cycles, row_delay_cycles; | ||
102 | |||
103 | cycles_per_us = (clk_get_rate(keypad->clk) / 1000000); | ||
104 | if (cycles_per_us == 0) | ||
105 | cycles_per_us = 1; | ||
106 | |||
107 | delay_cycles = cycles_per_us * keypad->scan_interval; | ||
108 | WARN_ON(delay_cycles >= (1 << 16)); /* Overflow */ | ||
109 | delay_cycles &= 0xffff; | ||
110 | |||
111 | row_delay_cycles = cycles_per_us * keypad->row_delay; | ||
112 | WARN_ON(row_delay_cycles >= (1 << 14)); /* Overflow */ | ||
113 | row_delay_cycles &= 0x3fff; | ||
114 | |||
115 | val |= 3 << 0; /* Set scan mode to 3 (continuous scan) */ | ||
116 | val |= row_delay_cycles << 2; /* Delay between scanning each row */ | ||
117 | val |= delay_cycles << 16; /* Delay between scans */ | ||
118 | writel(val, keypad->reg_base + KEYPAD_SCAN_MODE); | ||
119 | |||
120 | val = (KEYPAD_BITMASK_ROWS & 0xff) | (KEYPAD_BITMASK_COLS & 0xff)<<8; | ||
121 | writel(val, keypad->reg_base + KEYPAD_CNTL); | ||
122 | |||
123 | /* Enable interrupts */ | ||
124 | keypad->int_mask = 1 << 1; | ||
125 | writel(keypad->int_mask, keypad->reg_base + 0xc); | ||
126 | |||
127 | /* Disable GPIO interrupts to prevent hanging on touchpad */ | ||
128 | /* Possibly used to detect touchpad events */ | ||
129 | writel(0, keypad->reg_base + KEYPAD_UNKNOWN_INT); | ||
130 | /* Acknowledge existing interrupts */ | ||
131 | writel(~0, keypad->reg_base + KEYPAD_UNKNOWN_INT_STS); | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static int nspire_keypad_open(struct input_dev *input) | ||
137 | { | ||
138 | struct nspire_keypad *keypad = input_get_drvdata(input); | ||
139 | int error; | ||
140 | |||
141 | error = clk_prepare_enable(keypad->clk); | ||
142 | if (error) | ||
143 | return error; | ||
144 | |||
145 | error = nspire_keypad_chip_init(keypad); | ||
146 | if (error) | ||
147 | return error; | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static void nspire_keypad_close(struct input_dev *input) | ||
153 | { | ||
154 | struct nspire_keypad *keypad = input_get_drvdata(input); | ||
155 | |||
156 | clk_disable_unprepare(keypad->clk); | ||
157 | } | ||
158 | |||
159 | static int nspire_keypad_probe(struct platform_device *pdev) | ||
160 | { | ||
161 | const struct device_node *of_node = pdev->dev.of_node; | ||
162 | struct nspire_keypad *keypad; | ||
163 | struct input_dev *input; | ||
164 | struct resource *res; | ||
165 | int irq; | ||
166 | int error; | ||
167 | |||
168 | irq = platform_get_irq(pdev, 0); | ||
169 | if (irq < 0) { | ||
170 | dev_err(&pdev->dev, "failed to get keypad irq\n"); | ||
171 | return -EINVAL; | ||
172 | } | ||
173 | |||
174 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
175 | if (!res) { | ||
176 | dev_err(&pdev->dev, "missing platform resources\n"); | ||
177 | return -EINVAL; | ||
178 | } | ||
179 | |||
180 | keypad = devm_kzalloc(&pdev->dev, sizeof(struct nspire_keypad), | ||
181 | GFP_KERNEL); | ||
182 | if (!keypad) { | ||
183 | dev_err(&pdev->dev, "failed to allocate keypad memory\n"); | ||
184 | return -ENOMEM; | ||
185 | } | ||
186 | |||
187 | keypad->row_shift = get_count_order(KEYPAD_BITMASK_COLS); | ||
188 | |||
189 | error = of_property_read_u32(of_node, "scan-interval", | ||
190 | &keypad->scan_interval); | ||
191 | if (error) { | ||
192 | dev_err(&pdev->dev, "failed to get scan-interval\n"); | ||
193 | return error; | ||
194 | } | ||
195 | |||
196 | error = of_property_read_u32(of_node, "row-delay", | ||
197 | &keypad->row_delay); | ||
198 | if (error) { | ||
199 | dev_err(&pdev->dev, "failed to get row-delay\n"); | ||
200 | return error; | ||
201 | } | ||
202 | |||
203 | keypad->active_low = of_property_read_bool(of_node, "active-low"); | ||
204 | |||
205 | keypad->clk = devm_clk_get(&pdev->dev, NULL); | ||
206 | if (IS_ERR(keypad->clk)) { | ||
207 | dev_err(&pdev->dev, "unable to get clock\n"); | ||
208 | return PTR_ERR(keypad->clk); | ||
209 | } | ||
210 | |||
211 | keypad->reg_base = devm_ioremap_resource(&pdev->dev, res); | ||
212 | if (IS_ERR(keypad->reg_base)) | ||
213 | return PTR_ERR(keypad->reg_base); | ||
214 | |||
215 | keypad->input = input = devm_input_allocate_device(&pdev->dev); | ||
216 | if (!input) { | ||
217 | dev_err(&pdev->dev, "failed to allocate input device\n"); | ||
218 | return -ENOMEM; | ||
219 | } | ||
220 | |||
221 | input_set_drvdata(input, keypad); | ||
222 | |||
223 | input->id.bustype = BUS_HOST; | ||
224 | input->name = "nspire-keypad"; | ||
225 | input->open = nspire_keypad_open; | ||
226 | input->close = nspire_keypad_close; | ||
227 | |||
228 | __set_bit(EV_KEY, input->evbit); | ||
229 | __set_bit(EV_REP, input->evbit); | ||
230 | input_set_capability(input, EV_MSC, MSC_SCAN); | ||
231 | |||
232 | error = matrix_keypad_build_keymap(NULL, NULL, | ||
233 | KEYPAD_BITMASK_ROWS, | ||
234 | KEYPAD_BITMASK_COLS, | ||
235 | NULL, input); | ||
236 | if (error) { | ||
237 | dev_err(&pdev->dev, "building keymap failed\n"); | ||
238 | return error; | ||
239 | } | ||
240 | |||
241 | error = devm_request_irq(&pdev->dev, irq, nspire_keypad_irq, 0, | ||
242 | "nspire_keypad", keypad); | ||
243 | if (error) { | ||
244 | dev_err(&pdev->dev, "allocate irq %d failed\n", irq); | ||
245 | return error; | ||
246 | } | ||
247 | |||
248 | error = input_register_device(input); | ||
249 | if (error) { | ||
250 | dev_err(&pdev->dev, | ||
251 | "unable to register input device: %d\n", error); | ||
252 | return error; | ||
253 | } | ||
254 | |||
255 | platform_set_drvdata(pdev, keypad); | ||
256 | |||
257 | dev_dbg(&pdev->dev, | ||
258 | "TI-NSPIRE keypad at %pR (scan_interval=%uus, row_delay=%uus%s)\n", | ||
259 | res, keypad->row_delay, keypad->scan_interval, | ||
260 | keypad->active_low ? ", active_low" : ""); | ||
261 | |||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | static const struct of_device_id nspire_keypad_dt_match[] = { | ||
266 | { .compatible = "ti,nspire-keypad" }, | ||
267 | { }, | ||
268 | }; | ||
269 | MODULE_DEVICE_TABLE(of, nspire_keypad_dt_match); | ||
270 | |||
271 | static struct platform_driver nspire_keypad_driver = { | ||
272 | .driver = { | ||
273 | .name = "nspire-keypad", | ||
274 | .owner = THIS_MODULE, | ||
275 | .of_match_table = of_match_ptr(nspire_keypad_dt_match), | ||
276 | }, | ||
277 | .probe = nspire_keypad_probe, | ||
278 | }; | ||
279 | |||
280 | module_platform_driver(nspire_keypad_driver); | ||
281 | |||
282 | MODULE_LICENSE("GPL"); | ||
283 | MODULE_DESCRIPTION("TI-NSPIRE Keypad Driver"); | ||
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c index 1b289092f4e3..f4aa53a1fd69 100644 --- a/drivers/input/keyboard/omap4-keypad.c +++ b/drivers/input/keyboard/omap4-keypad.c | |||
@@ -419,8 +419,6 @@ static int omap4_keypad_remove(struct platform_device *pdev) | |||
419 | kfree(keypad_data->keymap); | 419 | kfree(keypad_data->keymap); |
420 | kfree(keypad_data); | 420 | kfree(keypad_data); |
421 | 421 | ||
422 | platform_set_drvdata(pdev, NULL); | ||
423 | |||
424 | return 0; | 422 | return 0; |
425 | } | 423 | } |
426 | 424 | ||
diff --git a/drivers/input/keyboard/opencores-kbd.c b/drivers/input/keyboard/opencores-kbd.c index 7ac5f174c6f7..7b9b44158ad1 100644 --- a/drivers/input/keyboard/opencores-kbd.c +++ b/drivers/input/keyboard/opencores-kbd.c | |||
@@ -151,8 +151,6 @@ static int opencores_kbd_remove(struct platform_device *pdev) | |||
151 | input_unregister_device(opencores_kbd->input); | 151 | input_unregister_device(opencores_kbd->input); |
152 | kfree(opencores_kbd); | 152 | kfree(opencores_kbd); |
153 | 153 | ||
154 | platform_set_drvdata(pdev, NULL); | ||
155 | |||
156 | return 0; | 154 | return 0; |
157 | } | 155 | } |
158 | 156 | ||
diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c index 74339e139d43..2c9f19ac35ea 100644 --- a/drivers/input/keyboard/pmic8xxx-keypad.c +++ b/drivers/input/keyboard/pmic8xxx-keypad.c | |||
@@ -707,7 +707,6 @@ err_gpio_config: | |||
707 | err_get_irq: | 707 | err_get_irq: |
708 | input_free_device(kp->input); | 708 | input_free_device(kp->input); |
709 | err_alloc_device: | 709 | err_alloc_device: |
710 | platform_set_drvdata(pdev, NULL); | ||
711 | kfree(kp); | 710 | kfree(kp); |
712 | return rc; | 711 | return rc; |
713 | } | 712 | } |
@@ -722,7 +721,6 @@ static int pmic8xxx_kp_remove(struct platform_device *pdev) | |||
722 | input_unregister_device(kp->input); | 721 | input_unregister_device(kp->input); |
723 | kfree(kp); | 722 | kfree(kp); |
724 | 723 | ||
725 | platform_set_drvdata(pdev, NULL); | ||
726 | return 0; | 724 | return 0; |
727 | } | 725 | } |
728 | 726 | ||
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 5330d8fbf6c0..134c3b404a54 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c | |||
@@ -100,7 +100,7 @@ | |||
100 | #define MAX_KEYPAD_KEYS (MAX_MATRIX_KEY_NUM + MAX_DIRECT_KEY_NUM) | 100 | #define MAX_KEYPAD_KEYS (MAX_MATRIX_KEY_NUM + MAX_DIRECT_KEY_NUM) |
101 | 101 | ||
102 | struct pxa27x_keypad { | 102 | struct pxa27x_keypad { |
103 | struct pxa27x_keypad_platform_data *pdata; | 103 | const struct pxa27x_keypad_platform_data *pdata; |
104 | 104 | ||
105 | struct clk *clk; | 105 | struct clk *clk; |
106 | struct input_dev *input_dev; | 106 | struct input_dev *input_dev; |
@@ -118,25 +118,254 @@ struct pxa27x_keypad { | |||
118 | unsigned int direct_key_mask; | 118 | unsigned int direct_key_mask; |
119 | }; | 119 | }; |
120 | 120 | ||
121 | static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) | 121 | #ifdef CONFIG_OF |
122 | static int pxa27x_keypad_matrix_key_parse_dt(struct pxa27x_keypad *keypad, | ||
123 | struct pxa27x_keypad_platform_data *pdata) | ||
122 | { | 124 | { |
123 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | ||
124 | struct input_dev *input_dev = keypad->input_dev; | 125 | struct input_dev *input_dev = keypad->input_dev; |
125 | unsigned short keycode; | 126 | struct device *dev = input_dev->dev.parent; |
127 | u32 rows, cols; | ||
128 | int error; | ||
129 | |||
130 | error = matrix_keypad_parse_of_params(dev, &rows, &cols); | ||
131 | if (error) | ||
132 | return error; | ||
133 | |||
134 | if (rows > MAX_MATRIX_KEY_ROWS || cols > MAX_MATRIX_KEY_COLS) { | ||
135 | dev_err(dev, "rows or cols exceeds maximum value\n"); | ||
136 | return -EINVAL; | ||
137 | } | ||
138 | |||
139 | pdata->matrix_key_rows = rows; | ||
140 | pdata->matrix_key_cols = cols; | ||
141 | |||
142 | error = matrix_keypad_build_keymap(NULL, NULL, | ||
143 | pdata->matrix_key_rows, | ||
144 | pdata->matrix_key_cols, | ||
145 | keypad->keycodes, input_dev); | ||
146 | if (error) | ||
147 | return error; | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static int pxa27x_keypad_direct_key_parse_dt(struct pxa27x_keypad *keypad, | ||
153 | struct pxa27x_keypad_platform_data *pdata) | ||
154 | { | ||
155 | struct input_dev *input_dev = keypad->input_dev; | ||
156 | struct device *dev = input_dev->dev.parent; | ||
157 | struct device_node *np = dev->of_node; | ||
158 | const __be16 *prop; | ||
159 | unsigned short code; | ||
160 | unsigned int proplen, size; | ||
126 | int i; | 161 | int i; |
162 | int error; | ||
127 | 163 | ||
128 | for (i = 0; i < pdata->matrix_key_map_size; i++) { | 164 | error = of_property_read_u32(np, "marvell,direct-key-count", |
129 | unsigned int key = pdata->matrix_key_map[i]; | 165 | &pdata->direct_key_num); |
130 | unsigned int row = KEY_ROW(key); | 166 | if (error) { |
131 | unsigned int col = KEY_COL(key); | 167 | /* |
132 | unsigned int scancode = MATRIX_SCAN_CODE(row, col, | 168 | * If do not have marvel,direct-key-count defined, |
133 | MATRIX_ROW_SHIFT); | 169 | * it means direct key is not supported. |
170 | */ | ||
171 | return error == -EINVAL ? 0 : error; | ||
172 | } | ||
134 | 173 | ||
135 | keycode = KEY_VAL(key); | 174 | error = of_property_read_u32(np, "marvell,direct-key-mask", |
136 | keypad->keycodes[scancode] = keycode; | 175 | &pdata->direct_key_mask); |
137 | __set_bit(keycode, input_dev->keybit); | 176 | if (error) { |
177 | if (error != -EINVAL) | ||
178 | return error; | ||
179 | |||
180 | /* | ||
181 | * If marvell,direct-key-mask is not defined, driver will use | ||
182 | * default value. Default value is set when configure the keypad. | ||
183 | */ | ||
184 | pdata->direct_key_mask = 0; | ||
185 | } | ||
186 | |||
187 | pdata->direct_key_low_active = of_property_read_bool(np, | ||
188 | "marvell,direct-key-low-active"); | ||
189 | |||
190 | prop = of_get_property(np, "marvell,direct-key-map", &proplen); | ||
191 | if (!prop) | ||
192 | return -EINVAL; | ||
193 | |||
194 | if (proplen % sizeof(u16)) | ||
195 | return -EINVAL; | ||
196 | |||
197 | size = proplen / sizeof(u16); | ||
198 | |||
199 | /* Only MAX_DIRECT_KEY_NUM is accepted.*/ | ||
200 | if (size > MAX_DIRECT_KEY_NUM) | ||
201 | return -EINVAL; | ||
202 | |||
203 | for (i = 0; i < size; i++) { | ||
204 | code = be16_to_cpup(prop + i); | ||
205 | keypad->keycodes[MAX_MATRIX_KEY_NUM + i] = code; | ||
206 | __set_bit(code, input_dev->keybit); | ||
207 | } | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static int pxa27x_keypad_rotary_parse_dt(struct pxa27x_keypad *keypad, | ||
213 | struct pxa27x_keypad_platform_data *pdata) | ||
214 | { | ||
215 | const __be32 *prop; | ||
216 | int i, relkey_ret; | ||
217 | unsigned int code, proplen; | ||
218 | const char *rotaryname[2] = { | ||
219 | "marvell,rotary0", "marvell,rotary1"}; | ||
220 | const char relkeyname[] = {"marvell,rotary-rel-key"}; | ||
221 | struct input_dev *input_dev = keypad->input_dev; | ||
222 | struct device *dev = input_dev->dev.parent; | ||
223 | struct device_node *np = dev->of_node; | ||
224 | |||
225 | relkey_ret = of_property_read_u32(np, relkeyname, &code); | ||
226 | /* if can read correct rotary key-code, we do not need this. */ | ||
227 | if (relkey_ret == 0) { | ||
228 | unsigned short relcode; | ||
229 | |||
230 | /* rotary0 taks lower half, rotary1 taks upper half. */ | ||
231 | relcode = code & 0xffff; | ||
232 | pdata->rotary0_rel_code = (code & 0xffff); | ||
233 | __set_bit(relcode, input_dev->relbit); | ||
234 | |||
235 | relcode = code >> 16; | ||
236 | pdata->rotary1_rel_code = relcode; | ||
237 | __set_bit(relcode, input_dev->relbit); | ||
238 | } | ||
239 | |||
240 | for (i = 0; i < 2; i++) { | ||
241 | prop = of_get_property(np, rotaryname[i], &proplen); | ||
242 | /* | ||
243 | * If the prop is not set, it means keypad does not need | ||
244 | * initialize the rotaryX. | ||
245 | */ | ||
246 | if (!prop) | ||
247 | continue; | ||
248 | |||
249 | code = be32_to_cpup(prop); | ||
250 | /* | ||
251 | * Not all up/down key code are valid. | ||
252 | * Now we depends on direct-rel-code. | ||
253 | */ | ||
254 | if ((!(code & 0xffff) || !(code >> 16)) && relkey_ret) { | ||
255 | return relkey_ret; | ||
256 | } else { | ||
257 | unsigned int n = MAX_MATRIX_KEY_NUM + (i << 1); | ||
258 | unsigned short keycode; | ||
259 | |||
260 | keycode = code & 0xffff; | ||
261 | keypad->keycodes[n] = keycode; | ||
262 | __set_bit(keycode, input_dev->keybit); | ||
263 | |||
264 | keycode = code >> 16; | ||
265 | keypad->keycodes[n + 1] = keycode; | ||
266 | __set_bit(keycode, input_dev->keybit); | ||
267 | |||
268 | if (i == 0) | ||
269 | pdata->rotary0_rel_code = -1; | ||
270 | else | ||
271 | pdata->rotary1_rel_code = -1; | ||
272 | } | ||
273 | if (i == 0) | ||
274 | pdata->enable_rotary0 = 1; | ||
275 | else | ||
276 | pdata->enable_rotary1 = 1; | ||
277 | } | ||
278 | |||
279 | keypad->rotary_rel_code[0] = pdata->rotary0_rel_code; | ||
280 | keypad->rotary_rel_code[1] = pdata->rotary1_rel_code; | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static int pxa27x_keypad_build_keycode_from_dt(struct pxa27x_keypad *keypad) | ||
286 | { | ||
287 | struct input_dev *input_dev = keypad->input_dev; | ||
288 | struct device *dev = input_dev->dev.parent; | ||
289 | struct device_node *np = dev->of_node; | ||
290 | struct pxa27x_keypad_platform_data *pdata; | ||
291 | int error; | ||
292 | |||
293 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
294 | if (!pdata) { | ||
295 | dev_err(dev, "failed to allocate memory for pdata\n"); | ||
296 | return -ENOMEM; | ||
297 | } | ||
298 | |||
299 | error = pxa27x_keypad_matrix_key_parse_dt(keypad, pdata); | ||
300 | if (error) { | ||
301 | dev_err(dev, "failed to parse matrix key\n"); | ||
302 | return error; | ||
303 | } | ||
304 | |||
305 | error = pxa27x_keypad_direct_key_parse_dt(keypad, pdata); | ||
306 | if (error) { | ||
307 | dev_err(dev, "failed to parse direct key\n"); | ||
308 | return error; | ||
309 | } | ||
310 | |||
311 | error = pxa27x_keypad_rotary_parse_dt(keypad, pdata); | ||
312 | if (error) { | ||
313 | dev_err(dev, "failed to parse rotary key\n"); | ||
314 | return error; | ||
315 | } | ||
316 | |||
317 | error = of_property_read_u32(np, "marvell,debounce-interval", | ||
318 | &pdata->debounce_interval); | ||
319 | if (error) { | ||
320 | dev_err(dev, "failed to parse debpunce-interval\n"); | ||
321 | return error; | ||
138 | } | 322 | } |
139 | 323 | ||
324 | /* | ||
325 | * The keycodes may not only includes matrix key but also the direct | ||
326 | * key or rotary key. | ||
327 | */ | ||
328 | input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes); | ||
329 | |||
330 | keypad->pdata = pdata; | ||
331 | return 0; | ||
332 | } | ||
333 | |||
334 | #else | ||
335 | |||
336 | static int pxa27x_keypad_build_keycode_from_dt(struct pxa27x_keypad *keypad) | ||
337 | { | ||
338 | dev_info(keypad->input_dev->dev.parent, "missing platform data\n"); | ||
339 | |||
340 | return -EINVAL; | ||
341 | } | ||
342 | |||
343 | #endif | ||
344 | |||
345 | static int pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) | ||
346 | { | ||
347 | const struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | ||
348 | struct input_dev *input_dev = keypad->input_dev; | ||
349 | const struct matrix_keymap_data *keymap_data = | ||
350 | pdata ? pdata->matrix_keymap_data : NULL; | ||
351 | unsigned short keycode; | ||
352 | int i; | ||
353 | int error; | ||
354 | |||
355 | error = matrix_keypad_build_keymap(keymap_data, NULL, | ||
356 | pdata->matrix_key_rows, | ||
357 | pdata->matrix_key_cols, | ||
358 | keypad->keycodes, input_dev); | ||
359 | if (error) | ||
360 | return error; | ||
361 | |||
362 | /* | ||
363 | * The keycodes may not only include matrix keys but also the direct | ||
364 | * or rotary keys. | ||
365 | */ | ||
366 | input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes); | ||
367 | |||
368 | /* For direct keys. */ | ||
140 | for (i = 0; i < pdata->direct_key_num; i++) { | 369 | for (i = 0; i < pdata->direct_key_num; i++) { |
141 | keycode = pdata->direct_key_map[i]; | 370 | keycode = pdata->direct_key_map[i]; |
142 | keypad->keycodes[MAX_MATRIX_KEY_NUM + i] = keycode; | 371 | keypad->keycodes[MAX_MATRIX_KEY_NUM + i] = keycode; |
@@ -178,11 +407,13 @@ static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) | |||
178 | } | 407 | } |
179 | 408 | ||
180 | __clear_bit(KEY_RESERVED, input_dev->keybit); | 409 | __clear_bit(KEY_RESERVED, input_dev->keybit); |
410 | |||
411 | return 0; | ||
181 | } | 412 | } |
182 | 413 | ||
183 | static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad) | 414 | static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad) |
184 | { | 415 | { |
185 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | 416 | const struct pxa27x_keypad_platform_data *pdata = keypad->pdata; |
186 | struct input_dev *input_dev = keypad->input_dev; | 417 | struct input_dev *input_dev = keypad->input_dev; |
187 | int row, col, num_keys_pressed = 0; | 418 | int row, col, num_keys_pressed = 0; |
188 | uint32_t new_state[MAX_MATRIX_KEY_COLS]; | 419 | uint32_t new_state[MAX_MATRIX_KEY_COLS]; |
@@ -284,7 +515,7 @@ static void report_rotary_event(struct pxa27x_keypad *keypad, int r, int delta) | |||
284 | 515 | ||
285 | static void pxa27x_keypad_scan_rotary(struct pxa27x_keypad *keypad) | 516 | static void pxa27x_keypad_scan_rotary(struct pxa27x_keypad *keypad) |
286 | { | 517 | { |
287 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | 518 | const struct pxa27x_keypad_platform_data *pdata = keypad->pdata; |
288 | uint32_t kprec; | 519 | uint32_t kprec; |
289 | 520 | ||
290 | /* read and reset to default count value */ | 521 | /* read and reset to default count value */ |
@@ -300,7 +531,7 @@ static void pxa27x_keypad_scan_rotary(struct pxa27x_keypad *keypad) | |||
300 | 531 | ||
301 | static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) | 532 | static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) |
302 | { | 533 | { |
303 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | 534 | const struct pxa27x_keypad_platform_data *pdata = keypad->pdata; |
304 | struct input_dev *input_dev = keypad->input_dev; | 535 | struct input_dev *input_dev = keypad->input_dev; |
305 | unsigned int new_state; | 536 | unsigned int new_state; |
306 | uint32_t kpdk, bits_changed; | 537 | uint32_t kpdk, bits_changed; |
@@ -340,7 +571,7 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) | |||
340 | 571 | ||
341 | static void clear_wakeup_event(struct pxa27x_keypad *keypad) | 572 | static void clear_wakeup_event(struct pxa27x_keypad *keypad) |
342 | { | 573 | { |
343 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | 574 | const struct pxa27x_keypad_platform_data *pdata = keypad->pdata; |
344 | 575 | ||
345 | if (pdata->clear_wakeup_event) | 576 | if (pdata->clear_wakeup_event) |
346 | (pdata->clear_wakeup_event)(); | 577 | (pdata->clear_wakeup_event)(); |
@@ -364,7 +595,7 @@ static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id) | |||
364 | 595 | ||
365 | static void pxa27x_keypad_config(struct pxa27x_keypad *keypad) | 596 | static void pxa27x_keypad_config(struct pxa27x_keypad *keypad) |
366 | { | 597 | { |
367 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | 598 | const struct pxa27x_keypad_platform_data *pdata = keypad->pdata; |
368 | unsigned int mask = 0, direct_key_num = 0; | 599 | unsigned int mask = 0, direct_key_num = 0; |
369 | unsigned long kpc = 0; | 600 | unsigned long kpc = 0; |
370 | 601 | ||
@@ -431,7 +662,7 @@ static void pxa27x_keypad_close(struct input_dev *dev) | |||
431 | clk_disable_unprepare(keypad->clk); | 662 | clk_disable_unprepare(keypad->clk); |
432 | } | 663 | } |
433 | 664 | ||
434 | #ifdef CONFIG_PM | 665 | #ifdef CONFIG_PM_SLEEP |
435 | static int pxa27x_keypad_suspend(struct device *dev) | 666 | static int pxa27x_keypad_suspend(struct device *dev) |
436 | { | 667 | { |
437 | struct platform_device *pdev = to_platform_device(dev); | 668 | struct platform_device *pdev = to_platform_device(dev); |
@@ -475,25 +706,25 @@ static int pxa27x_keypad_resume(struct device *dev) | |||
475 | 706 | ||
476 | return 0; | 707 | return 0; |
477 | } | 708 | } |
478 | |||
479 | static const struct dev_pm_ops pxa27x_keypad_pm_ops = { | ||
480 | .suspend = pxa27x_keypad_suspend, | ||
481 | .resume = pxa27x_keypad_resume, | ||
482 | }; | ||
483 | #endif | 709 | #endif |
484 | 710 | ||
711 | static SIMPLE_DEV_PM_OPS(pxa27x_keypad_pm_ops, | ||
712 | pxa27x_keypad_suspend, pxa27x_keypad_resume); | ||
713 | |||
714 | |||
485 | static int pxa27x_keypad_probe(struct platform_device *pdev) | 715 | static int pxa27x_keypad_probe(struct platform_device *pdev) |
486 | { | 716 | { |
487 | struct pxa27x_keypad_platform_data *pdata = pdev->dev.platform_data; | 717 | const struct pxa27x_keypad_platform_data *pdata = |
718 | dev_get_platdata(&pdev->dev); | ||
719 | struct device_node *np = pdev->dev.of_node; | ||
488 | struct pxa27x_keypad *keypad; | 720 | struct pxa27x_keypad *keypad; |
489 | struct input_dev *input_dev; | 721 | struct input_dev *input_dev; |
490 | struct resource *res; | 722 | struct resource *res; |
491 | int irq, error; | 723 | int irq, error; |
492 | 724 | ||
493 | if (pdata == NULL) { | 725 | /* Driver need build keycode from device tree or pdata */ |
494 | dev_err(&pdev->dev, "no platform data defined\n"); | 726 | if (!np && !pdata) |
495 | return -EINVAL; | 727 | return -EINVAL; |
496 | } | ||
497 | 728 | ||
498 | irq = platform_get_irq(pdev, 0); | 729 | irq = platform_get_irq(pdev, 0); |
499 | if (irq < 0) { | 730 | if (irq < 0) { |
@@ -555,7 +786,14 @@ static int pxa27x_keypad_probe(struct platform_device *pdev) | |||
555 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | 786 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); |
556 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | 787 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); |
557 | 788 | ||
558 | pxa27x_keypad_build_keycode(keypad); | 789 | if (pdata) |
790 | error = pxa27x_keypad_build_keycode(keypad); | ||
791 | else | ||
792 | error = pxa27x_keypad_build_keycode_from_dt(keypad); | ||
793 | if (error) { | ||
794 | dev_err(&pdev->dev, "failed to build keycode\n"); | ||
795 | goto failed_put_clk; | ||
796 | } | ||
559 | 797 | ||
560 | if ((pdata->enable_rotary0 && keypad->rotary_rel_code[0] != -1) || | 798 | if ((pdata->enable_rotary0 && keypad->rotary_rel_code[0] != -1) || |
561 | (pdata->enable_rotary1 && keypad->rotary_rel_code[1] != -1)) { | 799 | (pdata->enable_rotary1 && keypad->rotary_rel_code[1] != -1)) { |
@@ -582,7 +820,7 @@ static int pxa27x_keypad_probe(struct platform_device *pdev) | |||
582 | return 0; | 820 | return 0; |
583 | 821 | ||
584 | failed_free_irq: | 822 | failed_free_irq: |
585 | free_irq(irq, pdev); | 823 | free_irq(irq, keypad); |
586 | failed_put_clk: | 824 | failed_put_clk: |
587 | clk_put(keypad->clk); | 825 | clk_put(keypad->clk); |
588 | failed_free_io: | 826 | failed_free_io: |
@@ -600,7 +838,7 @@ static int pxa27x_keypad_remove(struct platform_device *pdev) | |||
600 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); | 838 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); |
601 | struct resource *res; | 839 | struct resource *res; |
602 | 840 | ||
603 | free_irq(keypad->irq, pdev); | 841 | free_irq(keypad->irq, keypad); |
604 | clk_put(keypad->clk); | 842 | clk_put(keypad->clk); |
605 | 843 | ||
606 | input_unregister_device(keypad->input_dev); | 844 | input_unregister_device(keypad->input_dev); |
@@ -609,7 +847,6 @@ static int pxa27x_keypad_remove(struct platform_device *pdev) | |||
609 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 847 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
610 | release_mem_region(res->start, resource_size(res)); | 848 | release_mem_region(res->start, resource_size(res)); |
611 | 849 | ||
612 | platform_set_drvdata(pdev, NULL); | ||
613 | kfree(keypad); | 850 | kfree(keypad); |
614 | 851 | ||
615 | return 0; | 852 | return 0; |
@@ -618,15 +855,22 @@ static int pxa27x_keypad_remove(struct platform_device *pdev) | |||
618 | /* work with hotplug and coldplug */ | 855 | /* work with hotplug and coldplug */ |
619 | MODULE_ALIAS("platform:pxa27x-keypad"); | 856 | MODULE_ALIAS("platform:pxa27x-keypad"); |
620 | 857 | ||
858 | #ifdef CONFIG_OF | ||
859 | static const struct of_device_id pxa27x_keypad_dt_match[] = { | ||
860 | { .compatible = "marvell,pxa27x-keypad" }, | ||
861 | {}, | ||
862 | }; | ||
863 | MODULE_DEVICE_TABLE(of, pxa27x_keypad_dt_match); | ||
864 | #endif | ||
865 | |||
621 | static struct platform_driver pxa27x_keypad_driver = { | 866 | static struct platform_driver pxa27x_keypad_driver = { |
622 | .probe = pxa27x_keypad_probe, | 867 | .probe = pxa27x_keypad_probe, |
623 | .remove = pxa27x_keypad_remove, | 868 | .remove = pxa27x_keypad_remove, |
624 | .driver = { | 869 | .driver = { |
625 | .name = "pxa27x-keypad", | 870 | .name = "pxa27x-keypad", |
871 | .of_match_table = of_match_ptr(pxa27x_keypad_dt_match), | ||
626 | .owner = THIS_MODULE, | 872 | .owner = THIS_MODULE, |
627 | #ifdef CONFIG_PM | ||
628 | .pm = &pxa27x_keypad_pm_ops, | 873 | .pm = &pxa27x_keypad_pm_ops, |
629 | #endif | ||
630 | }, | 874 | }, |
631 | }; | 875 | }; |
632 | module_platform_driver(pxa27x_keypad_driver); | 876 | module_platform_driver(pxa27x_keypad_driver); |
diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c index bcad95be73aa..248cdcf95296 100644 --- a/drivers/input/keyboard/pxa930_rotary.c +++ b/drivers/input/keyboard/pxa930_rotary.c | |||
@@ -181,7 +181,6 @@ static int pxa930_rotary_remove(struct platform_device *pdev) | |||
181 | free_irq(platform_get_irq(pdev, 0), r); | 181 | free_irq(platform_get_irq(pdev, 0), r); |
182 | input_unregister_device(r->input_dev); | 182 | input_unregister_device(r->input_dev); |
183 | iounmap(r->mmio_base); | 183 | iounmap(r->mmio_base); |
184 | platform_set_drvdata(pdev, NULL); | ||
185 | kfree(r); | 184 | kfree(r); |
186 | 185 | ||
187 | return 0; | 186 | return 0; |
diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c index 22e357b51024..ac43a486c775 100644 --- a/drivers/input/keyboard/samsung-keypad.c +++ b/drivers/input/keyboard/samsung-keypad.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/pm_runtime.h> | 24 | #include <linux/pm_runtime.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/of.h> | 26 | #include <linux/of.h> |
27 | #include <linux/of_gpio.h> | ||
28 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
29 | #include <linux/input/samsung-keypad.h> | 28 | #include <linux/input/samsung-keypad.h> |
30 | 29 | ||
@@ -79,10 +78,6 @@ struct samsung_keypad { | |||
79 | unsigned int rows; | 78 | unsigned int rows; |
80 | unsigned int cols; | 79 | unsigned int cols; |
81 | unsigned int row_state[SAMSUNG_MAX_COLS]; | 80 | unsigned int row_state[SAMSUNG_MAX_COLS]; |
82 | #ifdef CONFIG_OF | ||
83 | int row_gpios[SAMSUNG_MAX_ROWS]; | ||
84 | int col_gpios[SAMSUNG_MAX_COLS]; | ||
85 | #endif | ||
86 | unsigned short keycodes[]; | 81 | unsigned short keycodes[]; |
87 | }; | 82 | }; |
88 | 83 | ||
@@ -304,45 +299,6 @@ static struct samsung_keypad_platdata *samsung_keypad_parse_dt( | |||
304 | 299 | ||
305 | return pdata; | 300 | return pdata; |
306 | } | 301 | } |
307 | |||
308 | static void samsung_keypad_parse_dt_gpio(struct device *dev, | ||
309 | struct samsung_keypad *keypad) | ||
310 | { | ||
311 | struct device_node *np = dev->of_node; | ||
312 | int gpio, error, row, col; | ||
313 | |||
314 | for (row = 0; row < keypad->rows; row++) { | ||
315 | gpio = of_get_named_gpio(np, "row-gpios", row); | ||
316 | keypad->row_gpios[row] = gpio; | ||
317 | if (!gpio_is_valid(gpio)) { | ||
318 | dev_err(dev, "keypad row[%d]: invalid gpio %d\n", | ||
319 | row, gpio); | ||
320 | continue; | ||
321 | } | ||
322 | |||
323 | error = devm_gpio_request(dev, gpio, "keypad-row"); | ||
324 | if (error) | ||
325 | dev_err(dev, | ||
326 | "keypad row[%d] gpio request failed: %d\n", | ||
327 | row, error); | ||
328 | } | ||
329 | |||
330 | for (col = 0; col < keypad->cols; col++) { | ||
331 | gpio = of_get_named_gpio(np, "col-gpios", col); | ||
332 | keypad->col_gpios[col] = gpio; | ||
333 | if (!gpio_is_valid(gpio)) { | ||
334 | dev_err(dev, "keypad column[%d]: invalid gpio %d\n", | ||
335 | col, gpio); | ||
336 | continue; | ||
337 | } | ||
338 | |||
339 | error = devm_gpio_request(dev, gpio, "keypad-col"); | ||
340 | if (error) | ||
341 | dev_err(dev, | ||
342 | "keypad column[%d] gpio request failed: %d\n", | ||
343 | col, error); | ||
344 | } | ||
345 | } | ||
346 | #else | 302 | #else |
347 | static | 303 | static |
348 | struct samsung_keypad_platdata *samsung_keypad_parse_dt(struct device *dev) | 304 | struct samsung_keypad_platdata *samsung_keypad_parse_dt(struct device *dev) |
@@ -424,15 +380,11 @@ static int samsung_keypad_probe(struct platform_device *pdev) | |||
424 | keypad->stopped = true; | 380 | keypad->stopped = true; |
425 | init_waitqueue_head(&keypad->wait); | 381 | init_waitqueue_head(&keypad->wait); |
426 | 382 | ||
427 | if (pdev->dev.of_node) { | 383 | if (pdev->dev.of_node) |
428 | #ifdef CONFIG_OF | ||
429 | samsung_keypad_parse_dt_gpio(&pdev->dev, keypad); | ||
430 | keypad->type = of_device_is_compatible(pdev->dev.of_node, | 384 | keypad->type = of_device_is_compatible(pdev->dev.of_node, |
431 | "samsung,s5pv210-keypad"); | 385 | "samsung,s5pv210-keypad"); |
432 | #endif | 386 | else |
433 | } else { | ||
434 | keypad->type = platform_get_device_id(pdev)->driver_data; | 387 | keypad->type = platform_get_device_id(pdev)->driver_data; |
435 | } | ||
436 | 388 | ||
437 | input_dev->name = pdev->name; | 389 | input_dev->name = pdev->name; |
438 | input_dev->id.bustype = BUS_HOST; | 390 | input_dev->id.bustype = BUS_HOST; |
@@ -487,7 +439,6 @@ static int samsung_keypad_probe(struct platform_device *pdev) | |||
487 | err_disable_runtime_pm: | 439 | err_disable_runtime_pm: |
488 | pm_runtime_disable(&pdev->dev); | 440 | pm_runtime_disable(&pdev->dev); |
489 | device_init_wakeup(&pdev->dev, 0); | 441 | device_init_wakeup(&pdev->dev, 0); |
490 | platform_set_drvdata(pdev, NULL); | ||
491 | err_unprepare_clk: | 442 | err_unprepare_clk: |
492 | clk_unprepare(keypad->clk); | 443 | clk_unprepare(keypad->clk); |
493 | return error; | 444 | return error; |
@@ -499,7 +450,6 @@ static int samsung_keypad_remove(struct platform_device *pdev) | |||
499 | 450 | ||
500 | pm_runtime_disable(&pdev->dev); | 451 | pm_runtime_disable(&pdev->dev); |
501 | device_init_wakeup(&pdev->dev, 0); | 452 | device_init_wakeup(&pdev->dev, 0); |
502 | platform_set_drvdata(pdev, NULL); | ||
503 | 453 | ||
504 | input_unregister_device(keypad->input_dev); | 454 | input_unregister_device(keypad->input_dev); |
505 | 455 | ||
diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index fdb9eb2df380..fe0e498d2479 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c | |||
@@ -266,7 +266,6 @@ static int sh_keysc_probe(struct platform_device *pdev) | |||
266 | err2: | 266 | err2: |
267 | iounmap(priv->iomem_base); | 267 | iounmap(priv->iomem_base); |
268 | err1: | 268 | err1: |
269 | platform_set_drvdata(pdev, NULL); | ||
270 | kfree(priv); | 269 | kfree(priv); |
271 | err0: | 270 | err0: |
272 | return error; | 271 | return error; |
@@ -285,7 +284,6 @@ static int sh_keysc_remove(struct platform_device *pdev) | |||
285 | pm_runtime_put_sync(&pdev->dev); | 284 | pm_runtime_put_sync(&pdev->dev); |
286 | pm_runtime_disable(&pdev->dev); | 285 | pm_runtime_disable(&pdev->dev); |
287 | 286 | ||
288 | platform_set_drvdata(pdev, NULL); | ||
289 | kfree(priv); | 287 | kfree(priv); |
290 | 288 | ||
291 | return 0; | 289 | return 0; |
diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c index cb1e8f614631..7111124b5362 100644 --- a/drivers/input/keyboard/spear-keyboard.c +++ b/drivers/input/keyboard/spear-keyboard.c | |||
@@ -290,7 +290,6 @@ static int spear_kbd_remove(struct platform_device *pdev) | |||
290 | clk_unprepare(kbd->clk); | 290 | clk_unprepare(kbd->clk); |
291 | 291 | ||
292 | device_init_wakeup(&pdev->dev, 0); | 292 | device_init_wakeup(&pdev->dev, 0); |
293 | platform_set_drvdata(pdev, NULL); | ||
294 | 293 | ||
295 | return 0; | 294 | return 0; |
296 | } | 295 | } |
diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c index ee1635011292..5f7b427dd7ed 100644 --- a/drivers/input/keyboard/tnetv107x-keypad.c +++ b/drivers/input/keyboard/tnetv107x-keypad.c | |||
@@ -296,7 +296,6 @@ error_clk: | |||
296 | error_map: | 296 | error_map: |
297 | release_mem_region(kp->res->start, resource_size(kp->res)); | 297 | release_mem_region(kp->res->start, resource_size(kp->res)); |
298 | error_res: | 298 | error_res: |
299 | platform_set_drvdata(pdev, NULL); | ||
300 | kfree(kp); | 299 | kfree(kp); |
301 | return error; | 300 | return error; |
302 | } | 301 | } |
@@ -311,7 +310,6 @@ static int keypad_remove(struct platform_device *pdev) | |||
311 | clk_put(kp->clk); | 310 | clk_put(kp->clk); |
312 | iounmap(kp->regs); | 311 | iounmap(kp->regs); |
313 | release_mem_region(kp->res->start, resource_size(kp->res)); | 312 | release_mem_region(kp->res->start, resource_size(kp->res)); |
314 | platform_set_drvdata(pdev, NULL); | ||
315 | kfree(kp); | 313 | kfree(kp); |
316 | 314 | ||
317 | return 0; | 315 | return 0; |
diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c index 04f84fd57173..d2d178c84ea7 100644 --- a/drivers/input/keyboard/twl4030_keypad.c +++ b/drivers/input/keyboard/twl4030_keypad.c | |||
@@ -422,7 +422,7 @@ static int twl4030_kp_probe(struct platform_device *pdev) | |||
422 | err3: | 422 | err3: |
423 | /* mask all events - we don't care about the result */ | 423 | /* mask all events - we don't care about the result */ |
424 | (void) twl4030_kpwrite_u8(kp, 0xff, KEYP_IMR1); | 424 | (void) twl4030_kpwrite_u8(kp, 0xff, KEYP_IMR1); |
425 | free_irq(kp->irq, NULL); | 425 | free_irq(kp->irq, kp); |
426 | err2: | 426 | err2: |
427 | input_unregister_device(input); | 427 | input_unregister_device(input); |
428 | input = NULL; | 428 | input = NULL; |
@@ -438,7 +438,6 @@ static int twl4030_kp_remove(struct platform_device *pdev) | |||
438 | 438 | ||
439 | free_irq(kp->irq, kp); | 439 | free_irq(kp->irq, kp); |
440 | input_unregister_device(kp->input); | 440 | input_unregister_device(kp->input); |
441 | platform_set_drvdata(pdev, NULL); | ||
442 | kfree(kp); | 441 | kfree(kp); |
443 | 442 | ||
444 | return 0; | 443 | return 0; |
diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c index ee163bee8cce..7b039162a3f8 100644 --- a/drivers/input/keyboard/w90p910_keypad.c +++ b/drivers/input/keyboard/w90p910_keypad.c | |||
@@ -221,7 +221,7 @@ static int w90p910_keypad_probe(struct platform_device *pdev) | |||
221 | return 0; | 221 | return 0; |
222 | 222 | ||
223 | failed_free_irq: | 223 | failed_free_irq: |
224 | free_irq(irq, pdev); | 224 | free_irq(irq, keypad); |
225 | failed_put_clk: | 225 | failed_put_clk: |
226 | clk_put(keypad->clk); | 226 | clk_put(keypad->clk); |
227 | failed_free_io: | 227 | failed_free_io: |
@@ -239,7 +239,7 @@ static int w90p910_keypad_remove(struct platform_device *pdev) | |||
239 | struct w90p910_keypad *keypad = platform_get_drvdata(pdev); | 239 | struct w90p910_keypad *keypad = platform_get_drvdata(pdev); |
240 | struct resource *res; | 240 | struct resource *res; |
241 | 241 | ||
242 | free_irq(keypad->irq, pdev); | 242 | free_irq(keypad->irq, keypad); |
243 | 243 | ||
244 | clk_put(keypad->clk); | 244 | clk_put(keypad->clk); |
245 | 245 | ||
@@ -249,7 +249,6 @@ static int w90p910_keypad_remove(struct platform_device *pdev) | |||
249 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 249 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
250 | release_mem_region(res->start, resource_size(res)); | 250 | release_mem_region(res->start, resource_size(res)); |
251 | 251 | ||
252 | platform_set_drvdata(pdev, NULL); | ||
253 | kfree(keypad); | 252 | kfree(keypad); |
254 | 253 | ||
255 | return 0; | 254 | return 0; |