Commit | Line | Data |
---|---|---|
39325b59 TS |
1 | /* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved. |
2 | * | |
3 | * This program is free software; you can redistribute it and/or modify | |
4 | * it under the terms of the GNU General Public License version 2 and | |
5 | * only version 2 as published by the Free Software Foundation. | |
6 | * | |
7 | * This program is distributed in the hope that it will be useful, | |
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
10 | * GNU General Public License for more details. | |
11 | */ | |
12 | ||
13 | #include <linux/module.h> | |
14 | #include <linux/platform_device.h> | |
15 | #include <linux/kernel.h> | |
16 | #include <linux/interrupt.h> | |
17 | #include <linux/slab.h> | |
18 | #include <linux/input.h> | |
19 | #include <linux/bitops.h> | |
20 | #include <linux/delay.h> | |
21 | #include <linux/mutex.h> | |
a5dde0c7 | 22 | #include <linux/regmap.h> |
86ea5e6b SB |
23 | #include <linux/of.h> |
24 | #include <linux/input/matrix_keypad.h> | |
39325b59 TS |
25 | |
26 | #define PM8XXX_MAX_ROWS 18 | |
27 | #define PM8XXX_MAX_COLS 8 | |
28 | #define PM8XXX_ROW_SHIFT 3 | |
29 | #define PM8XXX_MATRIX_MAX_SIZE (PM8XXX_MAX_ROWS * PM8XXX_MAX_COLS) | |
30 | ||
31 | #define PM8XXX_MIN_ROWS 5 | |
32 | #define PM8XXX_MIN_COLS 5 | |
33 | ||
34 | #define MAX_SCAN_DELAY 128 | |
35 | #define MIN_SCAN_DELAY 1 | |
36 | ||
37 | /* in nanoseconds */ | |
38 | #define MAX_ROW_HOLD_DELAY 122000 | |
39 | #define MIN_ROW_HOLD_DELAY 30500 | |
40 | ||
41 | #define MAX_DEBOUNCE_TIME 20 | |
42 | #define MIN_DEBOUNCE_TIME 5 | |
43 | ||
44 | #define KEYP_CTRL 0x148 | |
45 | ||
46 | #define KEYP_CTRL_EVNTS BIT(0) | |
47 | #define KEYP_CTRL_EVNTS_MASK 0x3 | |
48 | ||
49 | #define KEYP_CTRL_SCAN_COLS_SHIFT 5 | |
50 | #define KEYP_CTRL_SCAN_COLS_MIN 5 | |
51 | #define KEYP_CTRL_SCAN_COLS_BITS 0x3 | |
52 | ||
53 | #define KEYP_CTRL_SCAN_ROWS_SHIFT 2 | |
54 | #define KEYP_CTRL_SCAN_ROWS_MIN 5 | |
55 | #define KEYP_CTRL_SCAN_ROWS_BITS 0x7 | |
56 | ||
57 | #define KEYP_CTRL_KEYP_EN BIT(7) | |
58 | ||
59 | #define KEYP_SCAN 0x149 | |
60 | ||
61 | #define KEYP_SCAN_READ_STATE BIT(0) | |
62 | #define KEYP_SCAN_DBOUNCE_SHIFT 1 | |
63 | #define KEYP_SCAN_PAUSE_SHIFT 3 | |
64 | #define KEYP_SCAN_ROW_HOLD_SHIFT 6 | |
65 | ||
66 | #define KEYP_TEST 0x14A | |
67 | ||
68 | #define KEYP_TEST_CLEAR_RECENT_SCAN BIT(6) | |
69 | #define KEYP_TEST_CLEAR_OLD_SCAN BIT(5) | |
70 | #define KEYP_TEST_READ_RESET BIT(4) | |
71 | #define KEYP_TEST_DTEST_EN BIT(3) | |
72 | #define KEYP_TEST_ABORT_READ BIT(0) | |
73 | ||
74 | #define KEYP_TEST_DBG_SELECT_SHIFT 1 | |
75 | ||
76 | /* bits of these registers represent | |
77 | * '0' for key press | |
78 | * '1' for key release | |
79 | */ | |
80 | #define KEYP_RECENT_DATA 0x14B | |
81 | #define KEYP_OLD_DATA 0x14C | |
82 | ||
83 | #define KEYP_CLOCK_FREQ 32768 | |
84 | ||
85 | /** | |
86 | * struct pmic8xxx_kp - internal keypad data structure | |
86ea5e6b SB |
87 | * @num_cols - number of columns of keypad |
88 | * @num_rows - number of row of keypad | |
39325b59 | 89 | * @input - input device pointer for keypad |
a5dde0c7 | 90 | * @regmap - regmap handle |
39325b59 TS |
91 | * @key_sense_irq - key press/release irq number |
92 | * @key_stuck_irq - key stuck notification irq number | |
93 | * @keycodes - array to hold the key codes | |
94 | * @dev - parent device pointer | |
95 | * @keystate - present key press/release state | |
96 | * @stuckstate - present state when key stuck irq | |
97 | * @ctrl_reg - control register value | |
98 | */ | |
99 | struct pmic8xxx_kp { | |
86ea5e6b SB |
100 | unsigned int num_rows; |
101 | unsigned int num_cols; | |
39325b59 | 102 | struct input_dev *input; |
a5dde0c7 | 103 | struct regmap *regmap; |
39325b59 TS |
104 | int key_sense_irq; |
105 | int key_stuck_irq; | |
106 | ||
107 | unsigned short keycodes[PM8XXX_MATRIX_MAX_SIZE]; | |
108 | ||
109 | struct device *dev; | |
110 | u16 keystate[PM8XXX_MAX_ROWS]; | |
111 | u16 stuckstate[PM8XXX_MAX_ROWS]; | |
112 | ||
113 | u8 ctrl_reg; | |
114 | }; | |
115 | ||
39325b59 TS |
116 | static u8 pmic8xxx_col_state(struct pmic8xxx_kp *kp, u8 col) |
117 | { | |
118 | /* all keys pressed on that particular row? */ | |
119 | if (col == 0x00) | |
86ea5e6b | 120 | return 1 << kp->num_cols; |
39325b59 | 121 | else |
86ea5e6b | 122 | return col & ((1 << kp->num_cols) - 1); |
39325b59 TS |
123 | } |
124 | ||
125 | /* | |
126 | * Synchronous read protocol for RevB0 onwards: | |
127 | * | |
128 | * 1. Write '1' to ReadState bit in KEYP_SCAN register | |
129 | * 2. Wait 2*32KHz clocks, so that HW can successfully enter read mode | |
130 | * synchronously | |
131 | * 3. Read rows in old array first if events are more than one | |
132 | * 4. Read rows in recent array | |
133 | * 5. Wait 4*32KHz clocks | |
134 | * 6. Write '0' to ReadState bit of KEYP_SCAN register so that hw can | |
135 | * synchronously exit read mode. | |
136 | */ | |
137 | static int pmic8xxx_chk_sync_read(struct pmic8xxx_kp *kp) | |
138 | { | |
139 | int rc; | |
a5dde0c7 | 140 | unsigned int scan_val; |
39325b59 | 141 | |
a5dde0c7 | 142 | rc = regmap_read(kp->regmap, KEYP_SCAN, &scan_val); |
39325b59 TS |
143 | if (rc < 0) { |
144 | dev_err(kp->dev, "Error reading KEYP_SCAN reg, rc=%d\n", rc); | |
145 | return rc; | |
146 | } | |
147 | ||
148 | scan_val |= 0x1; | |
149 | ||
a5dde0c7 | 150 | rc = regmap_write(kp->regmap, KEYP_SCAN, scan_val); |
39325b59 TS |
151 | if (rc < 0) { |
152 | dev_err(kp->dev, "Error writing KEYP_SCAN reg, rc=%d\n", rc); | |
153 | return rc; | |
154 | } | |
155 | ||
156 | /* 2 * 32KHz clocks */ | |
157 | udelay((2 * DIV_ROUND_UP(USEC_PER_SEC, KEYP_CLOCK_FREQ)) + 1); | |
158 | ||
159 | return rc; | |
160 | } | |
161 | ||
162 | static int pmic8xxx_kp_read_data(struct pmic8xxx_kp *kp, u16 *state, | |
163 | u16 data_reg, int read_rows) | |
164 | { | |
165 | int rc, row; | |
a5dde0c7 | 166 | unsigned int val; |
39325b59 | 167 | |
a5dde0c7 SB |
168 | for (row = 0; row < read_rows; row++) { |
169 | rc = regmap_read(kp->regmap, data_reg, &val); | |
170 | if (rc) | |
171 | return rc; | |
172 | dev_dbg(kp->dev, "%d = %d\n", row, val); | |
173 | state[row] = pmic8xxx_col_state(kp, val); | |
39325b59 TS |
174 | } |
175 | ||
a5dde0c7 | 176 | return 0; |
39325b59 TS |
177 | } |
178 | ||
179 | static int pmic8xxx_kp_read_matrix(struct pmic8xxx_kp *kp, u16 *new_state, | |
180 | u16 *old_state) | |
181 | { | |
182 | int rc, read_rows; | |
a5dde0c7 | 183 | unsigned int scan_val; |
39325b59 | 184 | |
86ea5e6b | 185 | if (kp->num_rows < PM8XXX_MIN_ROWS) |
39325b59 TS |
186 | read_rows = PM8XXX_MIN_ROWS; |
187 | else | |
86ea5e6b | 188 | read_rows = kp->num_rows; |
39325b59 TS |
189 | |
190 | pmic8xxx_chk_sync_read(kp); | |
191 | ||
192 | if (old_state) { | |
193 | rc = pmic8xxx_kp_read_data(kp, old_state, KEYP_OLD_DATA, | |
194 | read_rows); | |
195 | if (rc < 0) { | |
196 | dev_err(kp->dev, | |
197 | "Error reading KEYP_OLD_DATA, rc=%d\n", rc); | |
198 | return rc; | |
199 | } | |
200 | } | |
201 | ||
202 | rc = pmic8xxx_kp_read_data(kp, new_state, KEYP_RECENT_DATA, | |
203 | read_rows); | |
204 | if (rc < 0) { | |
205 | dev_err(kp->dev, | |
206 | "Error reading KEYP_RECENT_DATA, rc=%d\n", rc); | |
207 | return rc; | |
208 | } | |
209 | ||
210 | /* 4 * 32KHz clocks */ | |
211 | udelay((4 * DIV_ROUND_UP(USEC_PER_SEC, KEYP_CLOCK_FREQ)) + 1); | |
212 | ||
a5dde0c7 | 213 | rc = regmap_read(kp->regmap, KEYP_SCAN, &scan_val); |
39325b59 TS |
214 | if (rc < 0) { |
215 | dev_err(kp->dev, "Error reading KEYP_SCAN reg, rc=%d\n", rc); | |
216 | return rc; | |
217 | } | |
218 | ||
219 | scan_val &= 0xFE; | |
a5dde0c7 | 220 | rc = regmap_write(kp->regmap, KEYP_SCAN, scan_val); |
39325b59 TS |
221 | if (rc < 0) |
222 | dev_err(kp->dev, "Error writing KEYP_SCAN reg, rc=%d\n", rc); | |
223 | ||
224 | return rc; | |
225 | } | |
226 | ||
227 | static void __pmic8xxx_kp_scan_matrix(struct pmic8xxx_kp *kp, u16 *new_state, | |
228 | u16 *old_state) | |
229 | { | |
230 | int row, col, code; | |
231 | ||
86ea5e6b | 232 | for (row = 0; row < kp->num_rows; row++) { |
39325b59 TS |
233 | int bits_changed = new_state[row] ^ old_state[row]; |
234 | ||
235 | if (!bits_changed) | |
236 | continue; | |
237 | ||
86ea5e6b | 238 | for (col = 0; col < kp->num_cols; col++) { |
39325b59 TS |
239 | if (!(bits_changed & (1 << col))) |
240 | continue; | |
241 | ||
242 | dev_dbg(kp->dev, "key [%d:%d] %s\n", row, col, | |
243 | !(new_state[row] & (1 << col)) ? | |
244 | "pressed" : "released"); | |
245 | ||
246 | code = MATRIX_SCAN_CODE(row, col, PM8XXX_ROW_SHIFT); | |
247 | ||
248 | input_event(kp->input, EV_MSC, MSC_SCAN, code); | |
249 | input_report_key(kp->input, | |
250 | kp->keycodes[code], | |
251 | !(new_state[row] & (1 << col))); | |
252 | ||
253 | input_sync(kp->input); | |
254 | } | |
255 | } | |
256 | } | |
257 | ||
258 | static bool pmic8xxx_detect_ghost_keys(struct pmic8xxx_kp *kp, u16 *new_state) | |
259 | { | |
260 | int row, found_first = -1; | |
261 | u16 check, row_state; | |
262 | ||
263 | check = 0; | |
86ea5e6b | 264 | for (row = 0; row < kp->num_rows; row++) { |
39325b59 | 265 | row_state = (~new_state[row]) & |
86ea5e6b | 266 | ((1 << kp->num_cols) - 1); |
39325b59 TS |
267 | |
268 | if (hweight16(row_state) > 1) { | |
269 | if (found_first == -1) | |
270 | found_first = row; | |
271 | if (check & row_state) { | |
272 | dev_dbg(kp->dev, "detected ghost key on row[%d]" | |
273 | " and row[%d]\n", found_first, row); | |
274 | return true; | |
275 | } | |
276 | } | |
277 | check |= row_state; | |
278 | } | |
279 | return false; | |
280 | } | |
281 | ||
282 | static int pmic8xxx_kp_scan_matrix(struct pmic8xxx_kp *kp, unsigned int events) | |
283 | { | |
284 | u16 new_state[PM8XXX_MAX_ROWS]; | |
285 | u16 old_state[PM8XXX_MAX_ROWS]; | |
286 | int rc; | |
287 | ||
288 | switch (events) { | |
289 | case 0x1: | |
290 | rc = pmic8xxx_kp_read_matrix(kp, new_state, NULL); | |
291 | if (rc < 0) | |
292 | return rc; | |
293 | ||
294 | /* detecting ghost key is not an error */ | |
295 | if (pmic8xxx_detect_ghost_keys(kp, new_state)) | |
296 | return 0; | |
297 | __pmic8xxx_kp_scan_matrix(kp, new_state, kp->keystate); | |
298 | memcpy(kp->keystate, new_state, sizeof(new_state)); | |
299 | break; | |
300 | case 0x3: /* two events - eventcounter is gray-coded */ | |
301 | rc = pmic8xxx_kp_read_matrix(kp, new_state, old_state); | |
302 | if (rc < 0) | |
303 | return rc; | |
304 | ||
305 | __pmic8xxx_kp_scan_matrix(kp, old_state, kp->keystate); | |
306 | __pmic8xxx_kp_scan_matrix(kp, new_state, old_state); | |
307 | memcpy(kp->keystate, new_state, sizeof(new_state)); | |
308 | break; | |
309 | case 0x2: | |
310 | dev_dbg(kp->dev, "Some key events were lost\n"); | |
311 | rc = pmic8xxx_kp_read_matrix(kp, new_state, old_state); | |
312 | if (rc < 0) | |
313 | return rc; | |
314 | __pmic8xxx_kp_scan_matrix(kp, old_state, kp->keystate); | |
315 | __pmic8xxx_kp_scan_matrix(kp, new_state, old_state); | |
316 | memcpy(kp->keystate, new_state, sizeof(new_state)); | |
317 | break; | |
318 | default: | |
319 | rc = -EINVAL; | |
320 | } | |
321 | return rc; | |
322 | } | |
323 | ||
324 | /* | |
325 | * NOTE: We are reading recent and old data registers blindly | |
326 | * whenever key-stuck interrupt happens, because events counter doesn't | |
327 | * get updated when this interrupt happens due to key stuck doesn't get | |
328 | * considered as key state change. | |
329 | * | |
330 | * We are not using old data register contents after they are being read | |
331 | * because it might report the key which was pressed before the key being stuck | |
332 | * as stuck key because it's pressed status is stored in the old data | |
333 | * register. | |
334 | */ | |
335 | static irqreturn_t pmic8xxx_kp_stuck_irq(int irq, void *data) | |
336 | { | |
337 | u16 new_state[PM8XXX_MAX_ROWS]; | |
338 | u16 old_state[PM8XXX_MAX_ROWS]; | |
339 | int rc; | |
340 | struct pmic8xxx_kp *kp = data; | |
341 | ||
342 | rc = pmic8xxx_kp_read_matrix(kp, new_state, old_state); | |
343 | if (rc < 0) { | |
344 | dev_err(kp->dev, "failed to read keypad matrix\n"); | |
345 | return IRQ_HANDLED; | |
346 | } | |
347 | ||
348 | __pmic8xxx_kp_scan_matrix(kp, new_state, kp->stuckstate); | |
349 | ||
350 | return IRQ_HANDLED; | |
351 | } | |
352 | ||
353 | static irqreturn_t pmic8xxx_kp_irq(int irq, void *data) | |
354 | { | |
355 | struct pmic8xxx_kp *kp = data; | |
a5dde0c7 | 356 | unsigned int ctrl_val, events; |
39325b59 TS |
357 | int rc; |
358 | ||
a5dde0c7 | 359 | rc = regmap_read(kp->regmap, KEYP_CTRL, &ctrl_val); |
39325b59 TS |
360 | if (rc < 0) { |
361 | dev_err(kp->dev, "failed to read keyp_ctrl register\n"); | |
362 | return IRQ_HANDLED; | |
363 | } | |
364 | ||
365 | events = ctrl_val & KEYP_CTRL_EVNTS_MASK; | |
366 | ||
367 | rc = pmic8xxx_kp_scan_matrix(kp, events); | |
368 | if (rc < 0) | |
369 | dev_err(kp->dev, "failed to scan matrix\n"); | |
370 | ||
371 | return IRQ_HANDLED; | |
372 | } | |
373 | ||
86ea5e6b SB |
374 | static int pmic8xxx_kpd_init(struct pmic8xxx_kp *kp, |
375 | struct platform_device *pdev) | |
39325b59 | 376 | { |
86ea5e6b SB |
377 | const struct device_node *of_node = pdev->dev.of_node; |
378 | unsigned int scan_delay_ms; | |
379 | unsigned int row_hold_ns; | |
380 | unsigned int debounce_ms; | |
39325b59 TS |
381 | int bits, rc, cycles; |
382 | u8 scan_val = 0, ctrl_val = 0; | |
383 | static const u8 row_bits[] = { | |
384 | 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, | |
385 | }; | |
386 | ||
387 | /* Find column bits */ | |
86ea5e6b | 388 | if (kp->num_cols < KEYP_CTRL_SCAN_COLS_MIN) |
39325b59 TS |
389 | bits = 0; |
390 | else | |
86ea5e6b | 391 | bits = kp->num_cols - KEYP_CTRL_SCAN_COLS_MIN; |
39325b59 TS |
392 | ctrl_val = (bits & KEYP_CTRL_SCAN_COLS_BITS) << |
393 | KEYP_CTRL_SCAN_COLS_SHIFT; | |
394 | ||
395 | /* Find row bits */ | |
86ea5e6b | 396 | if (kp->num_rows < KEYP_CTRL_SCAN_ROWS_MIN) |
39325b59 TS |
397 | bits = 0; |
398 | else | |
86ea5e6b | 399 | bits = row_bits[kp->num_rows - KEYP_CTRL_SCAN_ROWS_MIN]; |
39325b59 TS |
400 | |
401 | ctrl_val |= (bits << KEYP_CTRL_SCAN_ROWS_SHIFT); | |
402 | ||
a5dde0c7 | 403 | rc = regmap_write(kp->regmap, KEYP_CTRL, ctrl_val); |
39325b59 TS |
404 | if (rc < 0) { |
405 | dev_err(kp->dev, "Error writing KEYP_CTRL reg, rc=%d\n", rc); | |
406 | return rc; | |
407 | } | |
408 | ||
86ea5e6b SB |
409 | if (of_property_read_u32(of_node, "scan-delay", &scan_delay_ms)) |
410 | scan_delay_ms = MIN_SCAN_DELAY; | |
411 | ||
412 | if (scan_delay_ms > MAX_SCAN_DELAY || scan_delay_ms < MIN_SCAN_DELAY || | |
413 | !is_power_of_2(scan_delay_ms)) { | |
414 | dev_err(&pdev->dev, "invalid keypad scan time supplied\n"); | |
415 | return -EINVAL; | |
416 | } | |
417 | ||
418 | if (of_property_read_u32(of_node, "row-hold", &row_hold_ns)) | |
419 | row_hold_ns = MIN_ROW_HOLD_DELAY; | |
420 | ||
421 | if (row_hold_ns > MAX_ROW_HOLD_DELAY || | |
422 | row_hold_ns < MIN_ROW_HOLD_DELAY || | |
423 | ((row_hold_ns % MIN_ROW_HOLD_DELAY) != 0)) { | |
424 | dev_err(&pdev->dev, "invalid keypad row hold time supplied\n"); | |
425 | return -EINVAL; | |
426 | } | |
427 | ||
428 | if (of_property_read_u32(of_node, "debounce", &debounce_ms)) | |
429 | debounce_ms = MIN_DEBOUNCE_TIME; | |
430 | ||
431 | if (((debounce_ms % 5) != 0) || | |
432 | debounce_ms > MAX_DEBOUNCE_TIME || | |
433 | debounce_ms < MIN_DEBOUNCE_TIME) { | |
434 | dev_err(&pdev->dev, "invalid debounce time supplied\n"); | |
435 | return -EINVAL; | |
436 | } | |
437 | ||
438 | bits = (debounce_ms / 5) - 1; | |
39325b59 TS |
439 | |
440 | scan_val |= (bits << KEYP_SCAN_DBOUNCE_SHIFT); | |
441 | ||
86ea5e6b | 442 | bits = fls(scan_delay_ms) - 1; |
39325b59 TS |
443 | scan_val |= (bits << KEYP_SCAN_PAUSE_SHIFT); |
444 | ||
445 | /* Row hold time is a multiple of 32KHz cycles. */ | |
86ea5e6b | 446 | cycles = (row_hold_ns * KEYP_CLOCK_FREQ) / NSEC_PER_SEC; |
39325b59 TS |
447 | |
448 | scan_val |= (cycles << KEYP_SCAN_ROW_HOLD_SHIFT); | |
449 | ||
a5dde0c7 | 450 | rc = regmap_write(kp->regmap, KEYP_SCAN, scan_val); |
39325b59 TS |
451 | if (rc) |
452 | dev_err(kp->dev, "Error writing KEYP_SCAN reg, rc=%d\n", rc); | |
453 | ||
454 | return rc; | |
455 | ||
456 | } | |
457 | ||
39325b59 TS |
458 | static int pmic8xxx_kp_enable(struct pmic8xxx_kp *kp) |
459 | { | |
460 | int rc; | |
461 | ||
462 | kp->ctrl_reg |= KEYP_CTRL_KEYP_EN; | |
463 | ||
a5dde0c7 | 464 | rc = regmap_write(kp->regmap, KEYP_CTRL, kp->ctrl_reg); |
39325b59 TS |
465 | if (rc < 0) |
466 | dev_err(kp->dev, "Error writing KEYP_CTRL reg, rc=%d\n", rc); | |
467 | ||
468 | return rc; | |
469 | } | |
470 | ||
471 | static int pmic8xxx_kp_disable(struct pmic8xxx_kp *kp) | |
472 | { | |
473 | int rc; | |
474 | ||
475 | kp->ctrl_reg &= ~KEYP_CTRL_KEYP_EN; | |
476 | ||
a5dde0c7 | 477 | rc = regmap_write(kp->regmap, KEYP_CTRL, kp->ctrl_reg); |
39325b59 TS |
478 | if (rc < 0) |
479 | return rc; | |
480 | ||
481 | return rc; | |
482 | } | |
483 | ||
484 | static int pmic8xxx_kp_open(struct input_dev *dev) | |
485 | { | |
486 | struct pmic8xxx_kp *kp = input_get_drvdata(dev); | |
487 | ||
488 | return pmic8xxx_kp_enable(kp); | |
489 | } | |
490 | ||
491 | static void pmic8xxx_kp_close(struct input_dev *dev) | |
492 | { | |
493 | struct pmic8xxx_kp *kp = input_get_drvdata(dev); | |
494 | ||
495 | pmic8xxx_kp_disable(kp); | |
496 | } | |
497 | ||
498 | /* | |
499 | * keypad controller should be initialized in the following sequence | |
500 | * only, otherwise it might get into FSM stuck state. | |
501 | * | |
502 | * - Initialize keypad control parameters, like no. of rows, columns, | |
503 | * timing values etc., | |
504 | * - configure rows and column gpios pull up/down. | |
505 | * - set irq edge type. | |
506 | * - enable the keypad controller. | |
507 | */ | |
5298cc4c | 508 | static int pmic8xxx_kp_probe(struct platform_device *pdev) |
39325b59 | 509 | { |
27469652 | 510 | struct device_node *np = pdev->dev.of_node; |
86ea5e6b SB |
511 | unsigned int rows, cols; |
512 | bool repeat; | |
513 | bool wakeup; | |
39325b59 TS |
514 | struct pmic8xxx_kp *kp; |
515 | int rc; | |
a5dde0c7 | 516 | unsigned int ctrl_val; |
39325b59 | 517 | |
86ea5e6b SB |
518 | rc = matrix_keypad_parse_of_params(&pdev->dev, &rows, &cols); |
519 | if (rc) | |
520 | return rc; | |
39325b59 | 521 | |
86ea5e6b SB |
522 | if (cols > PM8XXX_MAX_COLS || rows > PM8XXX_MAX_ROWS || |
523 | cols < PM8XXX_MIN_COLS) { | |
524 | dev_err(&pdev->dev, "invalid platform data\n"); | |
39325b59 TS |
525 | return -EINVAL; |
526 | } | |
527 | ||
27469652 DT |
528 | repeat = !of_property_read_bool(np, "linux,input-no-autorepeat"); |
529 | ||
530 | wakeup = of_property_read_bool(np, "wakeup-source") || | |
531 | /* legacy name */ | |
532 | of_property_read_bool(np, "linux,keypad-wakeup"); | |
39325b59 | 533 | |
c7f6ee26 | 534 | kp = devm_kzalloc(&pdev->dev, sizeof(*kp), GFP_KERNEL); |
39325b59 TS |
535 | if (!kp) |
536 | return -ENOMEM; | |
537 | ||
a5dde0c7 SB |
538 | kp->regmap = dev_get_regmap(pdev->dev.parent, NULL); |
539 | if (!kp->regmap) | |
540 | return -ENODEV; | |
541 | ||
39325b59 TS |
542 | platform_set_drvdata(pdev, kp); |
543 | ||
86ea5e6b SB |
544 | kp->num_rows = rows; |
545 | kp->num_cols = cols; | |
39325b59 TS |
546 | kp->dev = &pdev->dev; |
547 | ||
c7f6ee26 | 548 | kp->input = devm_input_allocate_device(&pdev->dev); |
39325b59 TS |
549 | if (!kp->input) { |
550 | dev_err(&pdev->dev, "unable to allocate input device\n"); | |
c7f6ee26 | 551 | return -ENOMEM; |
39325b59 TS |
552 | } |
553 | ||
554 | kp->key_sense_irq = platform_get_irq(pdev, 0); | |
555 | if (kp->key_sense_irq < 0) { | |
556 | dev_err(&pdev->dev, "unable to get keypad sense irq\n"); | |
c7f6ee26 | 557 | return kp->key_sense_irq; |
39325b59 TS |
558 | } |
559 | ||
560 | kp->key_stuck_irq = platform_get_irq(pdev, 1); | |
561 | if (kp->key_stuck_irq < 0) { | |
562 | dev_err(&pdev->dev, "unable to get keypad stuck irq\n"); | |
c7f6ee26 | 563 | return kp->key_stuck_irq; |
39325b59 TS |
564 | } |
565 | ||
86ea5e6b SB |
566 | kp->input->name = "PMIC8XXX keypad"; |
567 | kp->input->phys = "pmic8xxx_keypad/input0"; | |
39325b59 | 568 | |
39325b59 TS |
569 | kp->input->id.bustype = BUS_I2C; |
570 | kp->input->id.version = 0x0001; | |
571 | kp->input->id.product = 0x0001; | |
572 | kp->input->id.vendor = 0x0001; | |
573 | ||
39325b59 TS |
574 | kp->input->open = pmic8xxx_kp_open; |
575 | kp->input->close = pmic8xxx_kp_close; | |
576 | ||
86ea5e6b | 577 | rc = matrix_keypad_build_keymap(NULL, NULL, |
1932811f DT |
578 | PM8XXX_MAX_ROWS, PM8XXX_MAX_COLS, |
579 | kp->keycodes, kp->input); | |
580 | if (rc) { | |
581 | dev_err(&pdev->dev, "failed to build keymap\n"); | |
c7f6ee26 | 582 | return rc; |
1932811f | 583 | } |
39325b59 | 584 | |
86ea5e6b | 585 | if (repeat) |
1932811f | 586 | __set_bit(EV_REP, kp->input->evbit); |
39325b59 | 587 | input_set_capability(kp->input, EV_MSC, MSC_SCAN); |
1932811f | 588 | |
39325b59 TS |
589 | input_set_drvdata(kp->input, kp); |
590 | ||
591 | /* initialize keypad state */ | |
592 | memset(kp->keystate, 0xff, sizeof(kp->keystate)); | |
593 | memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate)); | |
594 | ||
86ea5e6b | 595 | rc = pmic8xxx_kpd_init(kp, pdev); |
39325b59 TS |
596 | if (rc < 0) { |
597 | dev_err(&pdev->dev, "unable to initialize keypad controller\n"); | |
c7f6ee26 | 598 | return rc; |
39325b59 TS |
599 | } |
600 | ||
c7f6ee26 SB |
601 | rc = devm_request_any_context_irq(&pdev->dev, kp->key_sense_irq, |
602 | pmic8xxx_kp_irq, IRQF_TRIGGER_RISING, "pmic-keypad", | |
603 | kp); | |
39325b59 TS |
604 | if (rc < 0) { |
605 | dev_err(&pdev->dev, "failed to request keypad sense irq\n"); | |
c7f6ee26 | 606 | return rc; |
39325b59 TS |
607 | } |
608 | ||
c7f6ee26 SB |
609 | rc = devm_request_any_context_irq(&pdev->dev, kp->key_stuck_irq, |
610 | pmic8xxx_kp_stuck_irq, IRQF_TRIGGER_RISING, | |
611 | "pmic-keypad-stuck", kp); | |
39325b59 TS |
612 | if (rc < 0) { |
613 | dev_err(&pdev->dev, "failed to request keypad stuck irq\n"); | |
c7f6ee26 | 614 | return rc; |
39325b59 TS |
615 | } |
616 | ||
a5dde0c7 | 617 | rc = regmap_read(kp->regmap, KEYP_CTRL, &ctrl_val); |
39325b59 TS |
618 | if (rc < 0) { |
619 | dev_err(&pdev->dev, "failed to read KEYP_CTRL register\n"); | |
c7f6ee26 | 620 | return rc; |
39325b59 TS |
621 | } |
622 | ||
623 | kp->ctrl_reg = ctrl_val; | |
624 | ||
625 | rc = input_register_device(kp->input); | |
626 | if (rc < 0) { | |
627 | dev_err(&pdev->dev, "unable to register keypad input device\n"); | |
c7f6ee26 | 628 | return rc; |
39325b59 TS |
629 | } |
630 | ||
86ea5e6b | 631 | device_init_wakeup(&pdev->dev, wakeup); |
39325b59 | 632 | |
39325b59 TS |
633 | return 0; |
634 | } | |
635 | ||
636 | #ifdef CONFIG_PM_SLEEP | |
637 | static int pmic8xxx_kp_suspend(struct device *dev) | |
638 | { | |
639 | struct platform_device *pdev = to_platform_device(dev); | |
640 | struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); | |
641 | struct input_dev *input_dev = kp->input; | |
642 | ||
643 | if (device_may_wakeup(dev)) { | |
644 | enable_irq_wake(kp->key_sense_irq); | |
645 | } else { | |
646 | mutex_lock(&input_dev->mutex); | |
647 | ||
648 | if (input_dev->users) | |
649 | pmic8xxx_kp_disable(kp); | |
650 | ||
651 | mutex_unlock(&input_dev->mutex); | |
652 | } | |
653 | ||
654 | return 0; | |
655 | } | |
656 | ||
657 | static int pmic8xxx_kp_resume(struct device *dev) | |
658 | { | |
659 | struct platform_device *pdev = to_platform_device(dev); | |
660 | struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); | |
661 | struct input_dev *input_dev = kp->input; | |
662 | ||
663 | if (device_may_wakeup(dev)) { | |
664 | disable_irq_wake(kp->key_sense_irq); | |
665 | } else { | |
666 | mutex_lock(&input_dev->mutex); | |
667 | ||
668 | if (input_dev->users) | |
669 | pmic8xxx_kp_enable(kp); | |
670 | ||
671 | mutex_unlock(&input_dev->mutex); | |
672 | } | |
673 | ||
674 | return 0; | |
675 | } | |
676 | #endif | |
677 | ||
678 | static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops, | |
679 | pmic8xxx_kp_suspend, pmic8xxx_kp_resume); | |
680 | ||
86ea5e6b SB |
681 | static const struct of_device_id pm8xxx_match_table[] = { |
682 | { .compatible = "qcom,pm8058-keypad" }, | |
683 | { .compatible = "qcom,pm8921-keypad" }, | |
684 | { } | |
685 | }; | |
686 | MODULE_DEVICE_TABLE(of, pm8xxx_match_table); | |
687 | ||
39325b59 TS |
688 | static struct platform_driver pmic8xxx_kp_driver = { |
689 | .probe = pmic8xxx_kp_probe, | |
39325b59 | 690 | .driver = { |
86ea5e6b | 691 | .name = "pm8xxx-keypad", |
39325b59 | 692 | .pm = &pm8xxx_kp_pm_ops, |
86ea5e6b | 693 | .of_match_table = pm8xxx_match_table, |
39325b59 TS |
694 | }, |
695 | }; | |
5146c84f | 696 | module_platform_driver(pmic8xxx_kp_driver); |
39325b59 TS |
697 | |
698 | MODULE_LICENSE("GPL v2"); | |
699 | MODULE_DESCRIPTION("PMIC8XXX keypad driver"); | |
700 | MODULE_VERSION("1.0"); | |
701 | MODULE_ALIAS("platform:pmic8xxx_keypad"); | |
702 | MODULE_AUTHOR("Trilok Soni <tsoni@codeaurora.org>"); |