History

Input: matrix_keypad - add support for clustered irq

This one adds support of a combined irq source for the whole matrix keypad. This can be useful if all rows and columns of the keypad are e.g. connected to a GPIO expander, which only has one interrupt line for all events on every single GPIO.

Luotao Fu committed 16 years ago

Commit fb76dd11 parent 1719ec42 files · +86 −28Browse files

Unified · Split

2 files
  1. drivers/input/keyboard/matrix_keypad.c +80 −28
  2. include/linux/input/matrix_keypad.h +6 −0
drivers/input/keyboard/matrix_keypad.c+80−28
@@ -37,6 +37,7 @@ struct matrix_keypad { · 36 unmodified lines
37 spinlock_t lock;37 spinlock_t lock;
38 bool scan_pending;38 bool scan_pending;
39 bool stopped;39 bool stopped;
40 bool gpio_all_disabled;
40};41};
41 42
42/*43/*
@@ -87,8 +88,12 @@ static void enable_row_irqs(struct matrix_keypad *keypad) · 44 unmodified lines
87 const struct matrix_keypad_platform_data *pdata = keypad->pdata;88 const struct matrix_keypad_platform_data *pdata = keypad->pdata;
88 int i;89 int i;
89 90
90 for (i = 0; i < pdata->num_row_gpios; i++)91 if (pdata->clustered_irq > 0)
91 enable_irq(gpio_to_irq(pdata->row_gpios[i]));92 enable_irq(pdata->clustered_irq);
93 else {
94 for (i = 0; i < pdata->num_row_gpios; i++)
95 enable_irq(gpio_to_irq(pdata->row_gpios[i]));
96 }
92}97}
93 98
94static void disable_row_irqs(struct matrix_keypad *keypad)99static void disable_row_irqs(struct matrix_keypad *keypad)
@@ -96,8 +101,12 @@ static void disable_row_irqs(struct matrix_keypad *keypad) · 1 unmodified line
96 const struct matrix_keypad_platform_data *pdata = keypad->pdata;101 const struct matrix_keypad_platform_data *pdata = keypad->pdata;
97 int i;102 int i;
98 103
99 for (i = 0; i < pdata->num_row_gpios; i++)104 if (pdata->clustered_irq > 0)
100 disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i]));105 disable_irq_nosync(pdata->clustered_irq);
106 else {
107 for (i = 0; i < pdata->num_row_gpios; i++)
108 disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i]));
109 }
101}110}
102 111
103/*112/*
@@ -216,45 +225,69 @@ static void matrix_keypad_stop(struct input_dev *dev) · 112 unmodified lines
216}225}
217 226
218#ifdef CONFIG_PM227#ifdef CONFIG_PM
219static int matrix_keypad_suspend(struct device *dev)228static void matrix_keypad_enable_wakeup(struct matrix_keypad *keypad)
220{229{
221 struct platform_device *pdev = to_platform_device(dev);
222 struct matrix_keypad *keypad = platform_get_drvdata(pdev);
223 const struct matrix_keypad_platform_data *pdata = keypad->pdata;230 const struct matrix_keypad_platform_data *pdata = keypad->pdata;
231 unsigned int gpio;
224 int i;232 int i;
225 233
226 matrix_keypad_stop(keypad->input_dev);234 if (pdata->clustered_irq > 0) {
235 if (enable_irq_wake(pdata->clustered_irq) == 0)
236 keypad->gpio_all_disabled = true;
237 } else {
227 238
228 if (device_may_wakeup(&pdev->dev)) {
229 for (i = 0; i < pdata->num_row_gpios; i++) {239 for (i = 0; i < pdata->num_row_gpios; i++) {
230 if (!test_bit(i, keypad->disabled_gpios)) {240 if (!test_bit(i, keypad->disabled_gpios)) {
231 unsigned int gpio = pdata->row_gpios[i];241 gpio = pdata->row_gpios[i];
232 242
233 if (enable_irq_wake(gpio_to_irq(gpio)) == 0)243 if (enable_irq_wake(gpio_to_irq(gpio)) == 0)
234 __set_bit(i, keypad->disabled_gpios);244 __set_bit(i, keypad->disabled_gpios);
235 }245 }
236 }246 }
237 }247 }
238
239 return 0;
240}248}
241 249
242static int matrix_keypad_resume(struct device *dev)250static void matrix_keypad_disable_wakeup(struct matrix_keypad *keypad)
243{251{
244 struct platform_device *pdev = to_platform_device(dev);
245 struct matrix_keypad *keypad = platform_get_drvdata(pdev);
246 const struct matrix_keypad_platform_data *pdata = keypad->pdata;252 const struct matrix_keypad_platform_data *pdata = keypad->pdata;
253 unsigned int gpio;
247 int i;254 int i;
248 255
249 if (device_may_wakeup(&pdev->dev)) {256 if (pdata->clustered_irq > 0) {
257 if (keypad->gpio_all_disabled) {
258 disable_irq_wake(pdata->clustered_irq);
259 keypad->gpio_all_disabled = false;
260 }
261 } else {
250 for (i = 0; i < pdata->num_row_gpios; i++) {262 for (i = 0; i < pdata->num_row_gpios; i++) {
251 if (test_and_clear_bit(i, keypad->disabled_gpios)) {263 if (test_and_clear_bit(i, keypad->disabled_gpios)) {
252 unsigned int gpio = pdata->row_gpios[i];264 gpio = pdata->row_gpios[i];
253
254 disable_irq_wake(gpio_to_irq(gpio));265 disable_irq_wake(gpio_to_irq(gpio));
255 }266 }
256 }267 }
257 }268 }
269}
270
271static int matrix_keypad_suspend(struct device *dev)
272{
273 struct platform_device *pdev = to_platform_device(dev);
274 struct matrix_keypad *keypad = platform_get_drvdata(pdev);
275
276 matrix_keypad_stop(keypad->input_dev);
277
278 if (device_may_wakeup(&pdev->dev))
279 matrix_keypad_enable_wakeup(keypad);
280
281 return 0;
282}
283
284static int matrix_keypad_resume(struct device *dev)
285{
286 struct platform_device *pdev = to_platform_device(dev);
287 struct matrix_keypad *keypad = platform_get_drvdata(pdev);
288
289 if (device_may_wakeup(&pdev->dev))
290 matrix_keypad_disable_wakeup(keypad);
258 291
259 matrix_keypad_start(keypad->input_dev);292 matrix_keypad_start(keypad->input_dev);
260 293
@@ -296,17 +329,31 @@ static int __devinit init_matrix_gpio(struct platform_device *pdev, · 35 unmodified lines
296 gpio_direction_input(pdata->row_gpios[i]);329 gpio_direction_input(pdata->row_gpios[i]);
297 }330 }
298 331
299 for (i = 0; i < pdata->num_row_gpios; i++) {332 if (pdata->clustered_irq > 0) {
300 err = request_irq(gpio_to_irq(pdata->row_gpios[i]),333 err = request_irq(pdata->clustered_irq,
301 matrix_keypad_interrupt,334 matrix_keypad_interrupt,
302 IRQF_DISABLED |335 pdata->clustered_irq_flags,
303 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
304 "matrix-keypad", keypad);336 "matrix-keypad", keypad);
305 if (err) {337 if (err) {
306 dev_err(&pdev->dev,338 dev_err(&pdev->dev,
307 "Unable to acquire interrupt for GPIO line %i\n",339 "Unable to acquire clustered interrupt\n");
308 pdata->row_gpios[i]);340 goto err_free_rows;
309 goto err_free_irqs;341 }
342 } else {
343 for (i = 0; i < pdata->num_row_gpios; i++) {
344 err = request_irq(gpio_to_irq(pdata->row_gpios[i]),
345 matrix_keypad_interrupt,
346 IRQF_DISABLED |
347 IRQF_TRIGGER_RISING |
348 IRQF_TRIGGER_FALLING,
349 "matrix-keypad", keypad);
350 if (err) {
351 dev_err(&pdev->dev,
352 "Unable to acquire interrupt "
353 "for GPIO line %i\n",
354 pdata->row_gpios[i]);
355 goto err_free_irqs;
356 }
310 }357 }
311 }358 }
312 359
@@ -418,11 +465,16 @@ static int __devexit matrix_keypad_remove(struct platform_device *pdev) · 105 unmodified lines
418 465
419 device_init_wakeup(&pdev->dev, 0);466 device_init_wakeup(&pdev->dev, 0);
420 467
421 for (i = 0; i < pdata->num_row_gpios; i++) {468 if (pdata->clustered_irq > 0) {
422 free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);469 free_irq(pdata->clustered_irq, keypad);
423 gpio_free(pdata->row_gpios[i]);470 } else {
471 for (i = 0; i < pdata->num_row_gpios; i++)
472 free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
424 }473 }
425 474
475 for (i = 0; i < pdata->num_row_gpios; i++)
476 gpio_free(pdata->row_gpios[i]);
477
426 for (i = 0; i < pdata->num_col_gpios; i++)478 for (i = 0; i < pdata->num_col_gpios; i++)
427 gpio_free(pdata->col_gpios[i]);479 gpio_free(pdata->col_gpios[i]);
428 480
include/linux/input/matrix_keypad.h+6−0
@@ -41,6 +41,9 @@ struct matrix_keymap_data { · 40 unmodified lines
41 * @col_scan_delay_us: delay, measured in microseconds, that is41 * @col_scan_delay_us: delay, measured in microseconds, that is
42 * needed before we can keypad after activating column gpio42 * needed before we can keypad after activating column gpio
43 * @debounce_ms: debounce interval in milliseconds43 * @debounce_ms: debounce interval in milliseconds
44 * @clustered_irq: may be specified if interrupts of all row/column GPIOs
45 * are bundled to one single irq
46 * @clustered_irq_flags: flags that are needed for the clustered irq
44 * @active_low: gpio polarity47 * @active_low: gpio polarity
45 * @wakeup: controls whether the device should be set up as wakeup48 * @wakeup: controls whether the device should be set up as wakeup
46 * source49 * source
@@ -63,6 +66,9 @@ struct matrix_keypad_platform_data { · 16 unmodified lines
63 /* key debounce interval in milli-second */66 /* key debounce interval in milli-second */
64 unsigned int debounce_ms;67 unsigned int debounce_ms;
65 68
69 unsigned int clustered_irq;
70 unsigned int clustered_irq_flags;
71
66 bool active_low;72 bool active_low;
67 bool wakeup;73 bool wakeup;
68 bool no_autorepeat;74 bool no_autorepeat;