1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * GPIO driven matrix keyboard driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (c) 2008 Marek Vasut <marek.vasut@gmail.com>
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Based on corgikbd.c
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/types.h>
11*4882a593Smuzhiyun #include <linux/delay.h>
12*4882a593Smuzhiyun #include <linux/platform_device.h>
13*4882a593Smuzhiyun #include <linux/input.h>
14*4882a593Smuzhiyun #include <linux/irq.h>
15*4882a593Smuzhiyun #include <linux/interrupt.h>
16*4882a593Smuzhiyun #include <linux/jiffies.h>
17*4882a593Smuzhiyun #include <linux/module.h>
18*4882a593Smuzhiyun #include <linux/gpio.h>
19*4882a593Smuzhiyun #include <linux/input/matrix_keypad.h>
20*4882a593Smuzhiyun #include <linux/slab.h>
21*4882a593Smuzhiyun #include <linux/of.h>
22*4882a593Smuzhiyun #include <linux/of_gpio.h>
23*4882a593Smuzhiyun #include <linux/of_platform.h>
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun struct matrix_keypad {
26*4882a593Smuzhiyun const struct matrix_keypad_platform_data *pdata;
27*4882a593Smuzhiyun struct input_dev *input_dev;
28*4882a593Smuzhiyun unsigned int row_shift;
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun DECLARE_BITMAP(disabled_gpios, MATRIX_MAX_ROWS);
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun uint32_t last_key_state[MATRIX_MAX_COLS];
33*4882a593Smuzhiyun struct delayed_work work;
34*4882a593Smuzhiyun spinlock_t lock;
35*4882a593Smuzhiyun bool scan_pending;
36*4882a593Smuzhiyun bool stopped;
37*4882a593Smuzhiyun bool gpio_all_disabled;
38*4882a593Smuzhiyun };
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun /*
41*4882a593Smuzhiyun * NOTE: If drive_inactive_cols is false, then the GPIO has to be put into
42*4882a593Smuzhiyun * HiZ when de-activated to cause minmal side effect when scanning other
43*4882a593Smuzhiyun * columns. In that case it is configured here to be input, otherwise it is
44*4882a593Smuzhiyun * driven with the inactive value.
45*4882a593Smuzhiyun */
__activate_col(const struct matrix_keypad_platform_data * pdata,int col,bool on)46*4882a593Smuzhiyun static void __activate_col(const struct matrix_keypad_platform_data *pdata,
47*4882a593Smuzhiyun int col, bool on)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun bool level_on = !pdata->active_low;
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun if (on) {
52*4882a593Smuzhiyun gpio_direction_output(pdata->col_gpios[col], level_on);
53*4882a593Smuzhiyun } else {
54*4882a593Smuzhiyun gpio_set_value_cansleep(pdata->col_gpios[col], !level_on);
55*4882a593Smuzhiyun if (!pdata->drive_inactive_cols)
56*4882a593Smuzhiyun gpio_direction_input(pdata->col_gpios[col]);
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun
activate_col(const struct matrix_keypad_platform_data * pdata,int col,bool on)60*4882a593Smuzhiyun static void activate_col(const struct matrix_keypad_platform_data *pdata,
61*4882a593Smuzhiyun int col, bool on)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun __activate_col(pdata, col, on);
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun if (on && pdata->col_scan_delay_us)
66*4882a593Smuzhiyun udelay(pdata->col_scan_delay_us);
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun
activate_all_cols(const struct matrix_keypad_platform_data * pdata,bool on)69*4882a593Smuzhiyun static void activate_all_cols(const struct matrix_keypad_platform_data *pdata,
70*4882a593Smuzhiyun bool on)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun int col;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun for (col = 0; col < pdata->num_col_gpios; col++)
75*4882a593Smuzhiyun __activate_col(pdata, col, on);
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun
row_asserted(const struct matrix_keypad_platform_data * pdata,int row)78*4882a593Smuzhiyun static bool row_asserted(const struct matrix_keypad_platform_data *pdata,
79*4882a593Smuzhiyun int row)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun return gpio_get_value_cansleep(pdata->row_gpios[row]) ?
82*4882a593Smuzhiyun !pdata->active_low : pdata->active_low;
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun
enable_row_irqs(struct matrix_keypad * keypad)85*4882a593Smuzhiyun static void enable_row_irqs(struct matrix_keypad *keypad)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun const struct matrix_keypad_platform_data *pdata = keypad->pdata;
88*4882a593Smuzhiyun int i;
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun if (pdata->clustered_irq > 0)
91*4882a593Smuzhiyun enable_irq(pdata->clustered_irq);
92*4882a593Smuzhiyun else {
93*4882a593Smuzhiyun for (i = 0; i < pdata->num_row_gpios; i++)
94*4882a593Smuzhiyun enable_irq(gpio_to_irq(pdata->row_gpios[i]));
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun
disable_row_irqs(struct matrix_keypad * keypad)98*4882a593Smuzhiyun static void disable_row_irqs(struct matrix_keypad *keypad)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun const struct matrix_keypad_platform_data *pdata = keypad->pdata;
101*4882a593Smuzhiyun int i;
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun if (pdata->clustered_irq > 0)
104*4882a593Smuzhiyun disable_irq_nosync(pdata->clustered_irq);
105*4882a593Smuzhiyun else {
106*4882a593Smuzhiyun for (i = 0; i < pdata->num_row_gpios; i++)
107*4882a593Smuzhiyun disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i]));
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun /*
112*4882a593Smuzhiyun * This gets the keys from keyboard and reports it to input subsystem
113*4882a593Smuzhiyun */
matrix_keypad_scan(struct work_struct * work)114*4882a593Smuzhiyun static void matrix_keypad_scan(struct work_struct *work)
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun struct matrix_keypad *keypad =
117*4882a593Smuzhiyun container_of(work, struct matrix_keypad, work.work);
118*4882a593Smuzhiyun struct input_dev *input_dev = keypad->input_dev;
119*4882a593Smuzhiyun const unsigned short *keycodes = input_dev->keycode;
120*4882a593Smuzhiyun const struct matrix_keypad_platform_data *pdata = keypad->pdata;
121*4882a593Smuzhiyun uint32_t new_state[MATRIX_MAX_COLS];
122*4882a593Smuzhiyun int row, col, code;
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun /* de-activate all columns for scanning */
125*4882a593Smuzhiyun activate_all_cols(pdata, false);
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun memset(new_state, 0, sizeof(new_state));
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun /* assert each column and read the row status out */
130*4882a593Smuzhiyun for (col = 0; col < pdata->num_col_gpios; col++) {
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun activate_col(pdata, col, true);
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun for (row = 0; row < pdata->num_row_gpios; row++)
135*4882a593Smuzhiyun new_state[col] |=
136*4882a593Smuzhiyun row_asserted(pdata, row) ? (1 << row) : 0;
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun activate_col(pdata, col, false);
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun for (col = 0; col < pdata->num_col_gpios; col++) {
142*4882a593Smuzhiyun uint32_t bits_changed;
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun bits_changed = keypad->last_key_state[col] ^ new_state[col];
145*4882a593Smuzhiyun if (bits_changed == 0)
146*4882a593Smuzhiyun continue;
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun for (row = 0; row < pdata->num_row_gpios; row++) {
149*4882a593Smuzhiyun if ((bits_changed & (1 << row)) == 0)
150*4882a593Smuzhiyun continue;
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun code = MATRIX_SCAN_CODE(row, col, keypad->row_shift);
153*4882a593Smuzhiyun input_event(input_dev, EV_MSC, MSC_SCAN, code);
154*4882a593Smuzhiyun input_report_key(input_dev,
155*4882a593Smuzhiyun keycodes[code],
156*4882a593Smuzhiyun new_state[col] & (1 << row));
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun input_sync(input_dev);
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun memcpy(keypad->last_key_state, new_state, sizeof(new_state));
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun activate_all_cols(pdata, true);
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun /* Enable IRQs again */
166*4882a593Smuzhiyun spin_lock_irq(&keypad->lock);
167*4882a593Smuzhiyun keypad->scan_pending = false;
168*4882a593Smuzhiyun enable_row_irqs(keypad);
169*4882a593Smuzhiyun spin_unlock_irq(&keypad->lock);
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun
matrix_keypad_interrupt(int irq,void * id)172*4882a593Smuzhiyun static irqreturn_t matrix_keypad_interrupt(int irq, void *id)
173*4882a593Smuzhiyun {
174*4882a593Smuzhiyun struct matrix_keypad *keypad = id;
175*4882a593Smuzhiyun unsigned long flags;
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun spin_lock_irqsave(&keypad->lock, flags);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun /*
180*4882a593Smuzhiyun * See if another IRQ beaten us to it and scheduled the
181*4882a593Smuzhiyun * scan already. In that case we should not try to
182*4882a593Smuzhiyun * disable IRQs again.
183*4882a593Smuzhiyun */
184*4882a593Smuzhiyun if (unlikely(keypad->scan_pending || keypad->stopped))
185*4882a593Smuzhiyun goto out;
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun disable_row_irqs(keypad);
188*4882a593Smuzhiyun keypad->scan_pending = true;
189*4882a593Smuzhiyun schedule_delayed_work(&keypad->work,
190*4882a593Smuzhiyun msecs_to_jiffies(keypad->pdata->debounce_ms));
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun out:
193*4882a593Smuzhiyun spin_unlock_irqrestore(&keypad->lock, flags);
194*4882a593Smuzhiyun return IRQ_HANDLED;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
matrix_keypad_start(struct input_dev * dev)197*4882a593Smuzhiyun static int matrix_keypad_start(struct input_dev *dev)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun struct matrix_keypad *keypad = input_get_drvdata(dev);
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun keypad->stopped = false;
202*4882a593Smuzhiyun mb();
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun /*
205*4882a593Smuzhiyun * Schedule an immediate key scan to capture current key state;
206*4882a593Smuzhiyun * columns will be activated and IRQs be enabled after the scan.
207*4882a593Smuzhiyun */
208*4882a593Smuzhiyun schedule_delayed_work(&keypad->work, 0);
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun return 0;
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun
matrix_keypad_stop(struct input_dev * dev)213*4882a593Smuzhiyun static void matrix_keypad_stop(struct input_dev *dev)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun struct matrix_keypad *keypad = input_get_drvdata(dev);
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun spin_lock_irq(&keypad->lock);
218*4882a593Smuzhiyun keypad->stopped = true;
219*4882a593Smuzhiyun spin_unlock_irq(&keypad->lock);
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun flush_delayed_work(&keypad->work);
222*4882a593Smuzhiyun /*
223*4882a593Smuzhiyun * matrix_keypad_scan() will leave IRQs enabled;
224*4882a593Smuzhiyun * we should disable them now.
225*4882a593Smuzhiyun */
226*4882a593Smuzhiyun disable_row_irqs(keypad);
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
matrix_keypad_enable_wakeup(struct matrix_keypad * keypad)230*4882a593Smuzhiyun static void matrix_keypad_enable_wakeup(struct matrix_keypad *keypad)
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun const struct matrix_keypad_platform_data *pdata = keypad->pdata;
233*4882a593Smuzhiyun unsigned int gpio;
234*4882a593Smuzhiyun int i;
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun if (pdata->clustered_irq > 0) {
237*4882a593Smuzhiyun if (enable_irq_wake(pdata->clustered_irq) == 0)
238*4882a593Smuzhiyun keypad->gpio_all_disabled = true;
239*4882a593Smuzhiyun } else {
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun for (i = 0; i < pdata->num_row_gpios; i++) {
242*4882a593Smuzhiyun if (!test_bit(i, keypad->disabled_gpios)) {
243*4882a593Smuzhiyun gpio = pdata->row_gpios[i];
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun if (enable_irq_wake(gpio_to_irq(gpio)) == 0)
246*4882a593Smuzhiyun __set_bit(i, keypad->disabled_gpios);
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun
matrix_keypad_disable_wakeup(struct matrix_keypad * keypad)252*4882a593Smuzhiyun static void matrix_keypad_disable_wakeup(struct matrix_keypad *keypad)
253*4882a593Smuzhiyun {
254*4882a593Smuzhiyun const struct matrix_keypad_platform_data *pdata = keypad->pdata;
255*4882a593Smuzhiyun unsigned int gpio;
256*4882a593Smuzhiyun int i;
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun if (pdata->clustered_irq > 0) {
259*4882a593Smuzhiyun if (keypad->gpio_all_disabled) {
260*4882a593Smuzhiyun disable_irq_wake(pdata->clustered_irq);
261*4882a593Smuzhiyun keypad->gpio_all_disabled = false;
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun } else {
264*4882a593Smuzhiyun for (i = 0; i < pdata->num_row_gpios; i++) {
265*4882a593Smuzhiyun if (test_and_clear_bit(i, keypad->disabled_gpios)) {
266*4882a593Smuzhiyun gpio = pdata->row_gpios[i];
267*4882a593Smuzhiyun disable_irq_wake(gpio_to_irq(gpio));
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun
matrix_keypad_suspend(struct device * dev)273*4882a593Smuzhiyun static int matrix_keypad_suspend(struct device *dev)
274*4882a593Smuzhiyun {
275*4882a593Smuzhiyun struct platform_device *pdev = to_platform_device(dev);
276*4882a593Smuzhiyun struct matrix_keypad *keypad = platform_get_drvdata(pdev);
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun matrix_keypad_stop(keypad->input_dev);
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun if (device_may_wakeup(&pdev->dev))
281*4882a593Smuzhiyun matrix_keypad_enable_wakeup(keypad);
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun return 0;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun
matrix_keypad_resume(struct device * dev)286*4882a593Smuzhiyun static int matrix_keypad_resume(struct device *dev)
287*4882a593Smuzhiyun {
288*4882a593Smuzhiyun struct platform_device *pdev = to_platform_device(dev);
289*4882a593Smuzhiyun struct matrix_keypad *keypad = platform_get_drvdata(pdev);
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun if (device_may_wakeup(&pdev->dev))
292*4882a593Smuzhiyun matrix_keypad_disable_wakeup(keypad);
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun matrix_keypad_start(keypad->input_dev);
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun return 0;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun #endif
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun static SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops,
301*4882a593Smuzhiyun matrix_keypad_suspend, matrix_keypad_resume);
302*4882a593Smuzhiyun
matrix_keypad_init_gpio(struct platform_device * pdev,struct matrix_keypad * keypad)303*4882a593Smuzhiyun static int matrix_keypad_init_gpio(struct platform_device *pdev,
304*4882a593Smuzhiyun struct matrix_keypad *keypad)
305*4882a593Smuzhiyun {
306*4882a593Smuzhiyun const struct matrix_keypad_platform_data *pdata = keypad->pdata;
307*4882a593Smuzhiyun int i, err;
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun /* initialized strobe lines as outputs, activated */
310*4882a593Smuzhiyun for (i = 0; i < pdata->num_col_gpios; i++) {
311*4882a593Smuzhiyun err = gpio_request(pdata->col_gpios[i], "matrix_kbd_col");
312*4882a593Smuzhiyun if (err) {
313*4882a593Smuzhiyun dev_err(&pdev->dev,
314*4882a593Smuzhiyun "failed to request GPIO%d for COL%d\n",
315*4882a593Smuzhiyun pdata->col_gpios[i], i);
316*4882a593Smuzhiyun goto err_free_cols;
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun gpio_direction_output(pdata->col_gpios[i], !pdata->active_low);
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun for (i = 0; i < pdata->num_row_gpios; i++) {
323*4882a593Smuzhiyun err = gpio_request(pdata->row_gpios[i], "matrix_kbd_row");
324*4882a593Smuzhiyun if (err) {
325*4882a593Smuzhiyun dev_err(&pdev->dev,
326*4882a593Smuzhiyun "failed to request GPIO%d for ROW%d\n",
327*4882a593Smuzhiyun pdata->row_gpios[i], i);
328*4882a593Smuzhiyun goto err_free_rows;
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun gpio_direction_input(pdata->row_gpios[i]);
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun if (pdata->clustered_irq > 0) {
335*4882a593Smuzhiyun err = request_any_context_irq(pdata->clustered_irq,
336*4882a593Smuzhiyun matrix_keypad_interrupt,
337*4882a593Smuzhiyun pdata->clustered_irq_flags,
338*4882a593Smuzhiyun "matrix-keypad", keypad);
339*4882a593Smuzhiyun if (err < 0) {
340*4882a593Smuzhiyun dev_err(&pdev->dev,
341*4882a593Smuzhiyun "Unable to acquire clustered interrupt\n");
342*4882a593Smuzhiyun goto err_free_rows;
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun } else {
345*4882a593Smuzhiyun for (i = 0; i < pdata->num_row_gpios; i++) {
346*4882a593Smuzhiyun err = request_any_context_irq(
347*4882a593Smuzhiyun gpio_to_irq(pdata->row_gpios[i]),
348*4882a593Smuzhiyun matrix_keypad_interrupt,
349*4882a593Smuzhiyun IRQF_TRIGGER_RISING |
350*4882a593Smuzhiyun IRQF_TRIGGER_FALLING,
351*4882a593Smuzhiyun "matrix-keypad", keypad);
352*4882a593Smuzhiyun if (err < 0) {
353*4882a593Smuzhiyun dev_err(&pdev->dev,
354*4882a593Smuzhiyun "Unable to acquire interrupt for GPIO line %i\n",
355*4882a593Smuzhiyun pdata->row_gpios[i]);
356*4882a593Smuzhiyun goto err_free_irqs;
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun }
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun /* initialized as disabled - enabled by input->open */
362*4882a593Smuzhiyun disable_row_irqs(keypad);
363*4882a593Smuzhiyun return 0;
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun err_free_irqs:
366*4882a593Smuzhiyun while (--i >= 0)
367*4882a593Smuzhiyun free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
368*4882a593Smuzhiyun i = pdata->num_row_gpios;
369*4882a593Smuzhiyun err_free_rows:
370*4882a593Smuzhiyun while (--i >= 0)
371*4882a593Smuzhiyun gpio_free(pdata->row_gpios[i]);
372*4882a593Smuzhiyun i = pdata->num_col_gpios;
373*4882a593Smuzhiyun err_free_cols:
374*4882a593Smuzhiyun while (--i >= 0)
375*4882a593Smuzhiyun gpio_free(pdata->col_gpios[i]);
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun return err;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun
matrix_keypad_free_gpio(struct matrix_keypad * keypad)380*4882a593Smuzhiyun static void matrix_keypad_free_gpio(struct matrix_keypad *keypad)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun const struct matrix_keypad_platform_data *pdata = keypad->pdata;
383*4882a593Smuzhiyun int i;
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun if (pdata->clustered_irq > 0) {
386*4882a593Smuzhiyun free_irq(pdata->clustered_irq, keypad);
387*4882a593Smuzhiyun } else {
388*4882a593Smuzhiyun for (i = 0; i < pdata->num_row_gpios; i++)
389*4882a593Smuzhiyun free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun for (i = 0; i < pdata->num_row_gpios; i++)
393*4882a593Smuzhiyun gpio_free(pdata->row_gpios[i]);
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun for (i = 0; i < pdata->num_col_gpios; i++)
396*4882a593Smuzhiyun gpio_free(pdata->col_gpios[i]);
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun #ifdef CONFIG_OF
400*4882a593Smuzhiyun static struct matrix_keypad_platform_data *
matrix_keypad_parse_dt(struct device * dev)401*4882a593Smuzhiyun matrix_keypad_parse_dt(struct device *dev)
402*4882a593Smuzhiyun {
403*4882a593Smuzhiyun struct matrix_keypad_platform_data *pdata;
404*4882a593Smuzhiyun struct device_node *np = dev->of_node;
405*4882a593Smuzhiyun unsigned int *gpios;
406*4882a593Smuzhiyun int ret, i, nrow, ncol;
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun if (!np) {
409*4882a593Smuzhiyun dev_err(dev, "device lacks DT data\n");
410*4882a593Smuzhiyun return ERR_PTR(-ENODEV);
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
414*4882a593Smuzhiyun if (!pdata) {
415*4882a593Smuzhiyun dev_err(dev, "could not allocate memory for platform data\n");
416*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun pdata->num_row_gpios = nrow = of_gpio_named_count(np, "row-gpios");
420*4882a593Smuzhiyun pdata->num_col_gpios = ncol = of_gpio_named_count(np, "col-gpios");
421*4882a593Smuzhiyun if (nrow <= 0 || ncol <= 0) {
422*4882a593Smuzhiyun dev_err(dev, "number of keypad rows/columns not specified\n");
423*4882a593Smuzhiyun return ERR_PTR(-EINVAL);
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun if (of_get_property(np, "linux,no-autorepeat", NULL))
427*4882a593Smuzhiyun pdata->no_autorepeat = true;
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun pdata->wakeup = of_property_read_bool(np, "wakeup-source") ||
430*4882a593Smuzhiyun of_property_read_bool(np, "linux,wakeup"); /* legacy */
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun if (of_get_property(np, "gpio-activelow", NULL))
433*4882a593Smuzhiyun pdata->active_low = true;
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun pdata->drive_inactive_cols =
436*4882a593Smuzhiyun of_property_read_bool(np, "drive-inactive-cols");
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun of_property_read_u32(np, "debounce-delay-ms", &pdata->debounce_ms);
439*4882a593Smuzhiyun of_property_read_u32(np, "col-scan-delay-us",
440*4882a593Smuzhiyun &pdata->col_scan_delay_us);
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun gpios = devm_kcalloc(dev,
443*4882a593Smuzhiyun pdata->num_row_gpios + pdata->num_col_gpios,
444*4882a593Smuzhiyun sizeof(unsigned int),
445*4882a593Smuzhiyun GFP_KERNEL);
446*4882a593Smuzhiyun if (!gpios) {
447*4882a593Smuzhiyun dev_err(dev, "could not allocate memory for gpios\n");
448*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun for (i = 0; i < nrow; i++) {
452*4882a593Smuzhiyun ret = of_get_named_gpio(np, "row-gpios", i);
453*4882a593Smuzhiyun if (ret < 0)
454*4882a593Smuzhiyun return ERR_PTR(ret);
455*4882a593Smuzhiyun gpios[i] = ret;
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun for (i = 0; i < ncol; i++) {
459*4882a593Smuzhiyun ret = of_get_named_gpio(np, "col-gpios", i);
460*4882a593Smuzhiyun if (ret < 0)
461*4882a593Smuzhiyun return ERR_PTR(ret);
462*4882a593Smuzhiyun gpios[nrow + i] = ret;
463*4882a593Smuzhiyun }
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun pdata->row_gpios = gpios;
466*4882a593Smuzhiyun pdata->col_gpios = &gpios[pdata->num_row_gpios];
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun return pdata;
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun #else
471*4882a593Smuzhiyun static inline struct matrix_keypad_platform_data *
matrix_keypad_parse_dt(struct device * dev)472*4882a593Smuzhiyun matrix_keypad_parse_dt(struct device *dev)
473*4882a593Smuzhiyun {
474*4882a593Smuzhiyun dev_err(dev, "no platform data defined\n");
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun return ERR_PTR(-EINVAL);
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun #endif
479*4882a593Smuzhiyun
matrix_keypad_probe(struct platform_device * pdev)480*4882a593Smuzhiyun static int matrix_keypad_probe(struct platform_device *pdev)
481*4882a593Smuzhiyun {
482*4882a593Smuzhiyun const struct matrix_keypad_platform_data *pdata;
483*4882a593Smuzhiyun struct matrix_keypad *keypad;
484*4882a593Smuzhiyun struct input_dev *input_dev;
485*4882a593Smuzhiyun int err;
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun pdata = dev_get_platdata(&pdev->dev);
488*4882a593Smuzhiyun if (!pdata) {
489*4882a593Smuzhiyun pdata = matrix_keypad_parse_dt(&pdev->dev);
490*4882a593Smuzhiyun if (IS_ERR(pdata))
491*4882a593Smuzhiyun return PTR_ERR(pdata);
492*4882a593Smuzhiyun } else if (!pdata->keymap_data) {
493*4882a593Smuzhiyun dev_err(&pdev->dev, "no keymap data defined\n");
494*4882a593Smuzhiyun return -EINVAL;
495*4882a593Smuzhiyun }
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL);
498*4882a593Smuzhiyun input_dev = input_allocate_device();
499*4882a593Smuzhiyun if (!keypad || !input_dev) {
500*4882a593Smuzhiyun err = -ENOMEM;
501*4882a593Smuzhiyun goto err_free_mem;
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun keypad->input_dev = input_dev;
505*4882a593Smuzhiyun keypad->pdata = pdata;
506*4882a593Smuzhiyun keypad->row_shift = get_count_order(pdata->num_col_gpios);
507*4882a593Smuzhiyun keypad->stopped = true;
508*4882a593Smuzhiyun INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan);
509*4882a593Smuzhiyun spin_lock_init(&keypad->lock);
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun input_dev->name = pdev->name;
512*4882a593Smuzhiyun input_dev->id.bustype = BUS_HOST;
513*4882a593Smuzhiyun input_dev->dev.parent = &pdev->dev;
514*4882a593Smuzhiyun input_dev->open = matrix_keypad_start;
515*4882a593Smuzhiyun input_dev->close = matrix_keypad_stop;
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun err = matrix_keypad_build_keymap(pdata->keymap_data, NULL,
518*4882a593Smuzhiyun pdata->num_row_gpios,
519*4882a593Smuzhiyun pdata->num_col_gpios,
520*4882a593Smuzhiyun NULL, input_dev);
521*4882a593Smuzhiyun if (err) {
522*4882a593Smuzhiyun dev_err(&pdev->dev, "failed to build keymap\n");
523*4882a593Smuzhiyun goto err_free_mem;
524*4882a593Smuzhiyun }
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun if (!pdata->no_autorepeat)
527*4882a593Smuzhiyun __set_bit(EV_REP, input_dev->evbit);
528*4882a593Smuzhiyun input_set_capability(input_dev, EV_MSC, MSC_SCAN);
529*4882a593Smuzhiyun input_set_drvdata(input_dev, keypad);
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun err = matrix_keypad_init_gpio(pdev, keypad);
532*4882a593Smuzhiyun if (err)
533*4882a593Smuzhiyun goto err_free_mem;
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun err = input_register_device(keypad->input_dev);
536*4882a593Smuzhiyun if (err)
537*4882a593Smuzhiyun goto err_free_gpio;
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun device_init_wakeup(&pdev->dev, pdata->wakeup);
540*4882a593Smuzhiyun platform_set_drvdata(pdev, keypad);
541*4882a593Smuzhiyun
542*4882a593Smuzhiyun return 0;
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun err_free_gpio:
545*4882a593Smuzhiyun matrix_keypad_free_gpio(keypad);
546*4882a593Smuzhiyun err_free_mem:
547*4882a593Smuzhiyun input_free_device(input_dev);
548*4882a593Smuzhiyun kfree(keypad);
549*4882a593Smuzhiyun return err;
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun
matrix_keypad_remove(struct platform_device * pdev)552*4882a593Smuzhiyun static int matrix_keypad_remove(struct platform_device *pdev)
553*4882a593Smuzhiyun {
554*4882a593Smuzhiyun struct matrix_keypad *keypad = platform_get_drvdata(pdev);
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun matrix_keypad_free_gpio(keypad);
557*4882a593Smuzhiyun input_unregister_device(keypad->input_dev);
558*4882a593Smuzhiyun kfree(keypad);
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun return 0;
561*4882a593Smuzhiyun }
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun #ifdef CONFIG_OF
564*4882a593Smuzhiyun static const struct of_device_id matrix_keypad_dt_match[] = {
565*4882a593Smuzhiyun { .compatible = "gpio-matrix-keypad" },
566*4882a593Smuzhiyun { }
567*4882a593Smuzhiyun };
568*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, matrix_keypad_dt_match);
569*4882a593Smuzhiyun #endif
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun static struct platform_driver matrix_keypad_driver = {
572*4882a593Smuzhiyun .probe = matrix_keypad_probe,
573*4882a593Smuzhiyun .remove = matrix_keypad_remove,
574*4882a593Smuzhiyun .driver = {
575*4882a593Smuzhiyun .name = "matrix-keypad",
576*4882a593Smuzhiyun .pm = &matrix_keypad_pm_ops,
577*4882a593Smuzhiyun .of_match_table = of_match_ptr(matrix_keypad_dt_match),
578*4882a593Smuzhiyun },
579*4882a593Smuzhiyun };
580*4882a593Smuzhiyun module_platform_driver(matrix_keypad_driver);
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
583*4882a593Smuzhiyun MODULE_DESCRIPTION("GPIO Driven Matrix Keypad Driver");
584*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
585*4882a593Smuzhiyun MODULE_ALIAS("platform:matrix-keypad");
586