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
3737 spinlock_t lock;
3838 bool scan_pending;
3939 bool stopped;
40+ bool gpio_all_disabled;
4041 };
4142
4243 /*
@@ -87,8 +88,12 @@ static void enable_row_irqs(struct matrix_keypad *keypad) · 44 unmodified lines
8788 const struct matrix_keypad_platform_data *pdata = keypad->pdata;
8889 int i;
8990
90− for (i = 0; i < pdata->num_row_gpios; i++)
91− enable_irq(gpio_to_irq(pdata->row_gpios[i]));
91+ if (pdata->clustered_irq > 0)
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+ }
9297 }
9398
9499 static void disable_row_irqs(struct matrix_keypad *keypad)
@@ -96,8 +101,12 @@ static void disable_row_irqs(struct matrix_keypad *keypad) · 1 unmodified line
96101 const struct matrix_keypad_platform_data *pdata = keypad->pdata;
97102 int i;
98103
99− for (i = 0; i < pdata->num_row_gpios; i++)
100− disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i]));
104+ if (pdata->clustered_irq > 0)
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+ }
101110 }
102111
103112 /*
@@ -216,45 +225,69 @@ static void matrix_keypad_stop(struct input_dev *dev) · 112 unmodified lines
216225 }
217226
218227 #ifdef CONFIG_PM
219−static int matrix_keypad_suspend(struct device *dev)
228+static void matrix_keypad_enable_wakeup(struct matrix_keypad *keypad)
220229 {
221− struct platform_device *pdev = to_platform_device(dev);
222− struct matrix_keypad *keypad = platform_get_drvdata(pdev);
223230 const struct matrix_keypad_platform_data *pdata = keypad->pdata;
231+ unsigned int gpio;
224232 int i;
225233
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 {
227238
228− if (device_may_wakeup(&pdev->dev)) {
229239 for (i = 0; i < pdata->num_row_gpios; i++) {
230240 if (!test_bit(i, keypad->disabled_gpios)) {
231− unsigned int gpio = pdata->row_gpios[i];
241+ gpio = pdata->row_gpios[i];
232242
233243 if (enable_irq_wake(gpio_to_irq(gpio)) == 0)
234244 __set_bit(i, keypad->disabled_gpios);
235245 }
236246 }
237247 }
238−
239− return 0;
240248 }
241249
242−static int matrix_keypad_resume(struct device *dev)
250+static void matrix_keypad_disable_wakeup(struct matrix_keypad *keypad)
243251 {
244− struct platform_device *pdev = to_platform_device(dev);
245− struct matrix_keypad *keypad = platform_get_drvdata(pdev);
246252 const struct matrix_keypad_platform_data *pdata = keypad->pdata;
253+ unsigned int gpio;
247254 int i;
248255
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 {
250262 for (i = 0; i < pdata->num_row_gpios; i++) {
251263 if (test_and_clear_bit(i, keypad->disabled_gpios)) {
252− unsigned int gpio = pdata->row_gpios[i];
253−
264+ gpio = pdata->row_gpios[i];
254265 disable_irq_wake(gpio_to_irq(gpio));
255266 }
256267 }
257268 }
269+}
270+
271+static 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+
284+static 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);
258291
259292 matrix_keypad_start(keypad->input_dev);
260293
@@ -296,17 +329,31 @@ static int __devinit init_matrix_gpio(struct platform_device *pdev, · 35 unmodified lines
296329 gpio_direction_input(pdata->row_gpios[i]);
297330 }
298331
299− for (i = 0; i < pdata->num_row_gpios; i++) {
300− err = request_irq(gpio_to_irq(pdata->row_gpios[i]),
332+ if (pdata->clustered_irq > 0) {
333+ err = request_irq(pdata->clustered_irq,
301334 matrix_keypad_interrupt,
302− IRQF_DISABLED |
303− IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
335+ pdata->clustered_irq_flags,
304336 "matrix-keypad", keypad);
305337 if (err) {
306338 dev_err(&pdev->dev,
307− "Unable to acquire interrupt for GPIO line %i\n",
308− pdata->row_gpios[i]);
309− goto err_free_irqs;
339+ "Unable to acquire clustered interrupt\n");
340+ goto err_free_rows;
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+ }
310357 }
311358 }
312359
@@ -418,11 +465,16 @@ static int __devexit matrix_keypad_remove(struct platform_device *pdev) · 105 unmodified lines
418465
419466 device_init_wakeup(&pdev->dev, 0);
420467
421− for (i = 0; i < pdata->num_row_gpios; i++) {
422− free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
423− gpio_free(pdata->row_gpios[i]);
468+ if (pdata->clustered_irq > 0) {
469+ free_irq(pdata->clustered_irq, keypad);
470+ } else {
471+ for (i = 0; i < pdata->num_row_gpios; i++)
472+ free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
424473 }
425474
475+ for (i = 0; i < pdata->num_row_gpios; i++)
476+ gpio_free(pdata->row_gpios[i]);
477+
426478 for (i = 0; i < pdata->num_col_gpios; i++)
427479 gpio_free(pdata->col_gpios[i]);
428480
include/linux/input/matrix_keypad.h+6−0
@@ -41,6 +41,9 @@ struct matrix_keymap_data { · 40 unmodified lines
4141 * @col_scan_delay_us: delay, measured in microseconds, that is
4242 * needed before we can keypad after activating column gpio
4343 * @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
4447 * @active_low: gpio polarity
4548 * @wakeup: controls whether the device should be set up as wakeup
4649 * source
@@ -63,6 +66,9 @@ struct matrix_keypad_platform_data { · 16 unmodified lines
6366 /* key debounce interval in milli-second */
6467 unsigned int debounce_ms;
6568
69+ unsigned int clustered_irq;
70+ unsigned int clustered_irq_flags;
71+
6672 bool active_low;
6773 bool wakeup;
6874 bool no_autorepeat;