blob: 5b2d8764dd37b712e49549cded3f195817c12b32 [file] [log] [blame]
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -04001/*
Eric Miao0e5f11a2008-01-31 00:56:46 -05002 * linux/drivers/input/keyboard/pxa27x_keypad.c
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -04003 *
4 * Driver for the pxa27x matrix keyboard controller.
5 *
6 * Created: Feb 22, 2007
7 * Author: Rodolfo Giometti <giometti@linux.it>
8 *
9 * Based on a previous implementations by Kevin O'Connor
10 * <kevin_at_koconnor.net> and Alex Osborne <bobofdoom@gmail.com> and
Nicolas Pitre2f82af02009-09-14 03:25:28 -040011 * on some suggestions by Nicolas Pitre <nico@fluxnic.net>.
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -040012 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 */
17
18
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/init.h>
22#include <linux/interrupt.h>
23#include <linux/input.h>
24#include <linux/device.h>
25#include <linux/platform_device.h>
Russell King22d8a732007-08-20 10:19:39 +010026#include <linux/clk.h>
27#include <linux/err.h>
Dmitry Torokhov52ec7752009-07-22 21:51:40 -070028#include <linux/input/matrix_keypad.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090029#include <linux/slab.h>
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -040030
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -040031#include <asm/mach/arch.h>
32#include <asm/mach/map.h>
33
Russell Kinga09e64f2008-08-05 16:14:15 +010034#include <mach/hardware.h>
Arnd Bergmann293b2da2012-08-24 15:16:48 +020035#include <linux/platform_data/keypad-pxa27x.h>
Eric Miao9c60deb2008-01-31 00:59:15 -050036/*
37 * Keypad Controller registers
38 */
39#define KPC 0x0000 /* Keypad Control register */
40#define KPDK 0x0008 /* Keypad Direct Key register */
41#define KPREC 0x0010 /* Keypad Rotary Encoder register */
42#define KPMK 0x0018 /* Keypad Matrix Key register */
43#define KPAS 0x0020 /* Keypad Automatic Scan register */
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -040044
Eric Miao9c60deb2008-01-31 00:59:15 -050045/* Keypad Automatic Scan Multiple Key Presser register 0-3 */
46#define KPASMKP0 0x0028
47#define KPASMKP1 0x0030
48#define KPASMKP2 0x0038
49#define KPASMKP3 0x0040
50#define KPKDI 0x0048
51
52/* bit definitions */
Samuel Ortiz688dad42008-03-20 09:48:14 -040053#define KPC_MKRN(n) ((((n) - 1) & 0x7) << 26) /* matrix key row number */
54#define KPC_MKCN(n) ((((n) - 1) & 0x7) << 23) /* matrix key column number */
55#define KPC_DKN(n) ((((n) - 1) & 0x7) << 6) /* direct key number */
Eric Miaod7416f92008-01-31 00:58:52 -050056
Eric Miao9c60deb2008-01-31 00:59:15 -050057#define KPC_AS (0x1 << 30) /* Automatic Scan bit */
58#define KPC_ASACT (0x1 << 29) /* Automatic Scan on Activity */
59#define KPC_MI (0x1 << 22) /* Matrix interrupt bit */
60#define KPC_IMKP (0x1 << 21) /* Ignore Multiple Key Press */
61
62#define KPC_MS(n) (0x1 << (13 + (n))) /* Matrix scan line 'n' */
63#define KPC_MS_ALL (0xff << 13)
64
65#define KPC_ME (0x1 << 12) /* Matrix Keypad Enable */
66#define KPC_MIE (0x1 << 11) /* Matrix Interrupt Enable */
67#define KPC_DK_DEB_SEL (0x1 << 9) /* Direct Keypad Debounce Select */
68#define KPC_DI (0x1 << 5) /* Direct key interrupt bit */
69#define KPC_RE_ZERO_DEB (0x1 << 4) /* Rotary Encoder Zero Debounce */
70#define KPC_REE1 (0x1 << 3) /* Rotary Encoder1 Enable */
71#define KPC_REE0 (0x1 << 2) /* Rotary Encoder0 Enable */
72#define KPC_DE (0x1 << 1) /* Direct Keypad Enable */
73#define KPC_DIE (0x1 << 0) /* Direct Keypad interrupt Enable */
74
Eric Miao62059d92008-01-31 00:59:03 -050075#define KPDK_DKP (0x1 << 31)
76#define KPDK_DK(n) ((n) & 0xff)
77
Eric Miao9c60deb2008-01-31 00:59:15 -050078#define KPREC_OF1 (0x1 << 31)
79#define kPREC_UF1 (0x1 << 30)
80#define KPREC_OF0 (0x1 << 15)
81#define KPREC_UF0 (0x1 << 14)
82
83#define KPREC_RECOUNT0(n) ((n) & 0xff)
84#define KPREC_RECOUNT1(n) (((n) >> 16) & 0xff)
85
86#define KPMK_MKP (0x1 << 31)
87#define KPAS_SO (0x1 << 31)
88#define KPASMKPx_SO (0x1 << 31)
89
90#define KPAS_MUKP(n) (((n) >> 26) & 0x1f)
91#define KPAS_RP(n) (((n) >> 4) & 0xf)
92#define KPAS_CP(n) ((n) & 0xf)
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -040093
Eric Miao1814db62008-01-31 00:58:37 -050094#define KPASMKP_MKC_MASK (0xff)
95
Eric Miao9c60deb2008-01-31 00:59:15 -050096#define keypad_readl(off) __raw_readl(keypad->mmio_base + (off))
97#define keypad_writel(off, v) __raw_writel((v), keypad->mmio_base + (off))
98
Dmitry Torokhovbd96f372009-09-04 23:46:18 -070099#define MAX_MATRIX_KEY_NUM (MAX_MATRIX_KEY_ROWS * MAX_MATRIX_KEY_COLS)
100#define MAX_KEYPAD_KEYS (MAX_MATRIX_KEY_NUM + MAX_DIRECT_KEY_NUM)
Eric Miao1814db62008-01-31 00:58:37 -0500101
102struct pxa27x_keypad {
103 struct pxa27x_keypad_platform_data *pdata;
104
105 struct clk *clk;
106 struct input_dev *input_dev;
Eric Miao9c60deb2008-01-31 00:59:15 -0500107 void __iomem *mmio_base;
Eric Miao1814db62008-01-31 00:58:37 -0500108
Eric Miao39ab9dd2008-06-02 11:20:55 -0400109 int irq;
110
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700111 unsigned short keycodes[MAX_KEYPAD_KEYS];
112 int rotary_rel_code[2];
Eric Miao1814db62008-01-31 00:58:37 -0500113
114 /* state row bits of each column scan */
115 uint32_t matrix_key_state[MAX_MATRIX_KEY_COLS];
Eric Miao62059d92008-01-31 00:59:03 -0500116 uint32_t direct_key_state;
117
118 unsigned int direct_key_mask;
Eric Miao1814db62008-01-31 00:58:37 -0500119};
120
Chao Xie0a085a92013-05-05 20:24:58 -0700121static int pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad)
Eric Miao1814db62008-01-31 00:58:37 -0500122{
123 struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
124 struct input_dev *input_dev = keypad->input_dev;
Chao Xie0a085a92013-05-05 20:24:58 -0700125 const struct matrix_keymap_data *keymap_data =
126 pdata ? pdata->matrix_keymap_data : NULL;
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700127 unsigned short keycode;
Eric Miao1814db62008-01-31 00:58:37 -0500128 int i;
Chao Xie0a085a92013-05-05 20:24:58 -0700129 int error;
Eric Miao1814db62008-01-31 00:58:37 -0500130
Chao Xie0a085a92013-05-05 20:24:58 -0700131 error = matrix_keypad_build_keymap(keymap_data, NULL,
132 pdata->matrix_key_rows,
133 pdata->matrix_key_cols,
134 keypad->keycodes, input_dev);
135 if (error)
136 return error;
Eric Miao1814db62008-01-31 00:58:37 -0500137
Chao Xie0a085a92013-05-05 20:24:58 -0700138 /*
139 * The keycodes may not only include matrix keys but also the direct
140 * or rotary keys.
141 */
142 input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes);
Eric Miao62059d92008-01-31 00:59:03 -0500143
Chao Xie0a085a92013-05-05 20:24:58 -0700144 /* For direct keys. */
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700145 for (i = 0; i < pdata->direct_key_num; i++) {
146 keycode = pdata->direct_key_map[i];
147 keypad->keycodes[MAX_MATRIX_KEY_NUM + i] = keycode;
148 __set_bit(keycode, input_dev->keybit);
149 }
Eric Miao62059d92008-01-31 00:59:03 -0500150
Antonio Ospite471637a2008-05-28 14:35:52 -0400151 if (pdata->enable_rotary0) {
152 if (pdata->rotary0_up_key && pdata->rotary0_down_key) {
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700153 keycode = pdata->rotary0_up_key;
154 keypad->keycodes[MAX_MATRIX_KEY_NUM + 0] = keycode;
155 __set_bit(keycode, input_dev->keybit);
156
157 keycode = pdata->rotary0_down_key;
158 keypad->keycodes[MAX_MATRIX_KEY_NUM + 1] = keycode;
159 __set_bit(keycode, input_dev->keybit);
160
161 keypad->rotary_rel_code[0] = -1;
162 } else {
163 keypad->rotary_rel_code[0] = pdata->rotary0_rel_code;
Dmitry Torokhov52ec7752009-07-22 21:51:40 -0700164 __set_bit(pdata->rotary0_rel_code, input_dev->relbit);
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700165 }
Antonio Ospite471637a2008-05-28 14:35:52 -0400166 }
Eric Miao62059d92008-01-31 00:59:03 -0500167
Antonio Ospite471637a2008-05-28 14:35:52 -0400168 if (pdata->enable_rotary1) {
169 if (pdata->rotary1_up_key && pdata->rotary1_down_key) {
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700170 keycode = pdata->rotary1_up_key;
171 keypad->keycodes[MAX_MATRIX_KEY_NUM + 2] = keycode;
172 __set_bit(keycode, input_dev->keybit);
Eric Miao1814db62008-01-31 00:58:37 -0500173
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700174 keycode = pdata->rotary1_down_key;
175 keypad->keycodes[MAX_MATRIX_KEY_NUM + 3] = keycode;
176 __set_bit(keycode, input_dev->keybit);
177
178 keypad->rotary_rel_code[1] = -1;
179 } else {
180 keypad->rotary_rel_code[1] = pdata->rotary1_rel_code;
181 __set_bit(pdata->rotary1_rel_code, input_dev->relbit);
182 }
183 }
184
185 __clear_bit(KEY_RESERVED, input_dev->keybit);
Chao Xie0a085a92013-05-05 20:24:58 -0700186
187 return 0;
Eric Miao1814db62008-01-31 00:58:37 -0500188}
189
190static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad)
191{
192 struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700193 struct input_dev *input_dev = keypad->input_dev;
Eric Miao1814db62008-01-31 00:58:37 -0500194 int row, col, num_keys_pressed = 0;
195 uint32_t new_state[MAX_MATRIX_KEY_COLS];
Eric Miao9c60deb2008-01-31 00:59:15 -0500196 uint32_t kpas = keypad_readl(KPAS);
Eric Miao1814db62008-01-31 00:58:37 -0500197
198 num_keys_pressed = KPAS_MUKP(kpas);
199
200 memset(new_state, 0, sizeof(new_state));
201
202 if (num_keys_pressed == 0)
203 goto scan;
204
205 if (num_keys_pressed == 1) {
206 col = KPAS_CP(kpas);
207 row = KPAS_RP(kpas);
208
209 /* if invalid row/col, treat as no key pressed */
210 if (col >= pdata->matrix_key_cols ||
211 row >= pdata->matrix_key_rows)
212 goto scan;
213
214 new_state[col] = (1 << row);
215 goto scan;
216 }
217
218 if (num_keys_pressed > 1) {
Eric Miao9c60deb2008-01-31 00:59:15 -0500219 uint32_t kpasmkp0 = keypad_readl(KPASMKP0);
220 uint32_t kpasmkp1 = keypad_readl(KPASMKP1);
221 uint32_t kpasmkp2 = keypad_readl(KPASMKP2);
222 uint32_t kpasmkp3 = keypad_readl(KPASMKP3);
Eric Miao1814db62008-01-31 00:58:37 -0500223
224 new_state[0] = kpasmkp0 & KPASMKP_MKC_MASK;
225 new_state[1] = (kpasmkp0 >> 16) & KPASMKP_MKC_MASK;
226 new_state[2] = kpasmkp1 & KPASMKP_MKC_MASK;
227 new_state[3] = (kpasmkp1 >> 16) & KPASMKP_MKC_MASK;
228 new_state[4] = kpasmkp2 & KPASMKP_MKC_MASK;
229 new_state[5] = (kpasmkp2 >> 16) & KPASMKP_MKC_MASK;
230 new_state[6] = kpasmkp3 & KPASMKP_MKC_MASK;
231 new_state[7] = (kpasmkp3 >> 16) & KPASMKP_MKC_MASK;
232 }
233scan:
234 for (col = 0; col < pdata->matrix_key_cols; col++) {
235 uint32_t bits_changed;
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700236 int code;
Eric Miao1814db62008-01-31 00:58:37 -0500237
238 bits_changed = keypad->matrix_key_state[col] ^ new_state[col];
239 if (bits_changed == 0)
240 continue;
241
242 for (row = 0; row < pdata->matrix_key_rows; row++) {
243 if ((bits_changed & (1 << row)) == 0)
244 continue;
245
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700246 code = MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT);
247 input_event(input_dev, EV_MSC, MSC_SCAN, code);
248 input_report_key(input_dev, keypad->keycodes[code],
249 new_state[col] & (1 << row));
Eric Miao1814db62008-01-31 00:58:37 -0500250 }
251 }
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700252 input_sync(input_dev);
Eric Miao1814db62008-01-31 00:58:37 -0500253 memcpy(keypad->matrix_key_state, new_state, sizeof(new_state));
254}
Russell King22d8a732007-08-20 10:19:39 +0100255
Eric Miaod7416f92008-01-31 00:58:52 -0500256#define DEFAULT_KPREC (0x007f007f)
257
Eric Miao62059d92008-01-31 00:59:03 -0500258static inline int rotary_delta(uint32_t kprec)
259{
260 if (kprec & KPREC_OF0)
261 return (kprec & 0xff) + 0x7f;
262 else if (kprec & KPREC_UF0)
263 return (kprec & 0xff) - 0x7f - 0xff;
264 else
265 return (kprec & 0xff) - 0x7f;
266}
267
268static void report_rotary_event(struct pxa27x_keypad *keypad, int r, int delta)
269{
270 struct input_dev *dev = keypad->input_dev;
271
272 if (delta == 0)
273 return;
274
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700275 if (keypad->rotary_rel_code[r] == -1) {
276 int code = MAX_MATRIX_KEY_NUM + 2 * r + (delta > 0 ? 0 : 1);
277 unsigned char keycode = keypad->keycodes[code];
Eric Miao62059d92008-01-31 00:59:03 -0500278
279 /* simulate a press-n-release */
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700280 input_event(dev, EV_MSC, MSC_SCAN, code);
Eric Miao62059d92008-01-31 00:59:03 -0500281 input_report_key(dev, keycode, 1);
282 input_sync(dev);
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700283 input_event(dev, EV_MSC, MSC_SCAN, code);
Eric Miao62059d92008-01-31 00:59:03 -0500284 input_report_key(dev, keycode, 0);
285 input_sync(dev);
286 } else {
287 input_report_rel(dev, keypad->rotary_rel_code[r], delta);
288 input_sync(dev);
289 }
290}
291
292static void pxa27x_keypad_scan_rotary(struct pxa27x_keypad *keypad)
293{
294 struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
295 uint32_t kprec;
296
297 /* read and reset to default count value */
Eric Miao9c60deb2008-01-31 00:59:15 -0500298 kprec = keypad_readl(KPREC);
299 keypad_writel(KPREC, DEFAULT_KPREC);
Eric Miao62059d92008-01-31 00:59:03 -0500300
301 if (pdata->enable_rotary0)
302 report_rotary_event(keypad, 0, rotary_delta(kprec));
303
304 if (pdata->enable_rotary1)
305 report_rotary_event(keypad, 1, rotary_delta(kprec >> 16));
306}
307
308static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad)
309{
310 struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700311 struct input_dev *input_dev = keypad->input_dev;
Eric Miao62059d92008-01-31 00:59:03 -0500312 unsigned int new_state;
313 uint32_t kpdk, bits_changed;
314 int i;
315
Eric Miao9c60deb2008-01-31 00:59:15 -0500316 kpdk = keypad_readl(KPDK);
Eric Miao62059d92008-01-31 00:59:03 -0500317
318 if (pdata->enable_rotary0 || pdata->enable_rotary1)
319 pxa27x_keypad_scan_rotary(keypad);
320
Chao Xieee1d8042012-04-01 10:08:03 +0800321 /*
322 * The KPDR_DK only output the key pin level, so it relates to board,
323 * and low level may be active.
324 */
325 if (pdata->direct_key_low_active)
326 new_state = ~KPDK_DK(kpdk) & keypad->direct_key_mask;
327 else
328 new_state = KPDK_DK(kpdk) & keypad->direct_key_mask;
329
Eric Miao62059d92008-01-31 00:59:03 -0500330 bits_changed = keypad->direct_key_state ^ new_state;
331
332 if (bits_changed == 0)
333 return;
334
335 for (i = 0; i < pdata->direct_key_num; i++) {
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700336 if (bits_changed & (1 << i)) {
337 int code = MAX_MATRIX_KEY_NUM + i;
338
339 input_event(input_dev, EV_MSC, MSC_SCAN, code);
340 input_report_key(input_dev, keypad->keycodes[code],
341 new_state & (1 << i));
342 }
Eric Miao62059d92008-01-31 00:59:03 -0500343 }
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700344 input_sync(input_dev);
Eric Miao62059d92008-01-31 00:59:03 -0500345 keypad->direct_key_state = new_state;
346}
347
Mark F. Brown3587c252010-09-03 18:28:09 -0400348static void clear_wakeup_event(struct pxa27x_keypad *keypad)
349{
350 struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
351
352 if (pdata->clear_wakeup_event)
353 (pdata->clear_wakeup_event)();
354}
355
Eric Miao0e5f11a2008-01-31 00:56:46 -0500356static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id)
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400357{
Eric Miao1814db62008-01-31 00:58:37 -0500358 struct pxa27x_keypad *keypad = dev_id;
Eric Miao9c60deb2008-01-31 00:59:15 -0500359 unsigned long kpc = keypad_readl(KPC);
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400360
Mark F. Brown3587c252010-09-03 18:28:09 -0400361 clear_wakeup_event(keypad);
362
Eric Miao62059d92008-01-31 00:59:03 -0500363 if (kpc & KPC_DI)
364 pxa27x_keypad_scan_direct(keypad);
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400365
Eric Miao1814db62008-01-31 00:58:37 -0500366 if (kpc & KPC_MI)
367 pxa27x_keypad_scan_matrix(keypad);
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400368
369 return IRQ_HANDLED;
370}
371
Eric Miaod7416f92008-01-31 00:58:52 -0500372static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
373{
374 struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
Eric Miao62059d92008-01-31 00:59:03 -0500375 unsigned int mask = 0, direct_key_num = 0;
Eric Miaod7416f92008-01-31 00:58:52 -0500376 unsigned long kpc = 0;
377
Vasily Khoruzhick904aded2012-10-29 23:45:09 -0700378 /* clear pending interrupt bit */
379 keypad_readl(KPC);
380
Eric Miaod7416f92008-01-31 00:58:52 -0500381 /* enable matrix keys with automatic scan */
382 if (pdata->matrix_key_rows && pdata->matrix_key_cols) {
383 kpc |= KPC_ASACT | KPC_MIE | KPC_ME | KPC_MS_ALL;
384 kpc |= KPC_MKRN(pdata->matrix_key_rows) |
385 KPC_MKCN(pdata->matrix_key_cols);
386 }
387
Eric Miao62059d92008-01-31 00:59:03 -0500388 /* enable rotary key, debounce interval same as direct keys */
389 if (pdata->enable_rotary0) {
390 mask |= 0x03;
391 direct_key_num = 2;
392 kpc |= KPC_REE0;
393 }
Eric Miaod7416f92008-01-31 00:58:52 -0500394
Eric Miao62059d92008-01-31 00:59:03 -0500395 if (pdata->enable_rotary1) {
396 mask |= 0x0c;
397 direct_key_num = 4;
398 kpc |= KPC_REE1;
399 }
400
401 if (pdata->direct_key_num > direct_key_num)
402 direct_key_num = pdata->direct_key_num;
403
Chao Xiefb054bf2012-04-01 10:08:04 +0800404 /*
405 * Direct keys usage may not start from KP_DKIN0, check the platfrom
406 * mask data to config the specific.
407 */
408 if (pdata->direct_key_mask)
409 keypad->direct_key_mask = pdata->direct_key_mask;
410 else
411 keypad->direct_key_mask = ((1 << direct_key_num) - 1) & ~mask;
Eric Miao62059d92008-01-31 00:59:03 -0500412
413 /* enable direct key */
414 if (direct_key_num)
415 kpc |= KPC_DE | KPC_DIE | KPC_DKN(direct_key_num);
416
Eric Miao9c60deb2008-01-31 00:59:15 -0500417 keypad_writel(KPC, kpc | KPC_RE_ZERO_DEB);
418 keypad_writel(KPREC, DEFAULT_KPREC);
Eric Miao76cb44e2008-01-31 00:59:23 -0500419 keypad_writel(KPKDI, pdata->debounce_interval);
Eric Miaod7416f92008-01-31 00:58:52 -0500420}
421
Eric Miao0e5f11a2008-01-31 00:56:46 -0500422static int pxa27x_keypad_open(struct input_dev *dev)
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400423{
Eric Miao1814db62008-01-31 00:58:37 -0500424 struct pxa27x_keypad *keypad = input_get_drvdata(dev);
425
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400426 /* Enable unit clock */
Chao Xie6ce34a52012-04-01 10:08:01 +0800427 clk_prepare_enable(keypad->clk);
Eric Miaod7416f92008-01-31 00:58:52 -0500428 pxa27x_keypad_config(keypad);
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400429
430 return 0;
431}
432
Eric Miao0e5f11a2008-01-31 00:56:46 -0500433static void pxa27x_keypad_close(struct input_dev *dev)
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400434{
Eric Miao1814db62008-01-31 00:58:37 -0500435 struct pxa27x_keypad *keypad = input_get_drvdata(dev);
436
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400437 /* Disable clock unit */
Chao Xie6ce34a52012-04-01 10:08:01 +0800438 clk_disable_unprepare(keypad->clk);
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400439}
440
441#ifdef CONFIG_PM
Dmitry Torokhovb0010912009-07-24 22:01:43 -0700442static int pxa27x_keypad_suspend(struct device *dev)
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400443{
Dmitry Torokhovb0010912009-07-24 22:01:43 -0700444 struct platform_device *pdev = to_platform_device(dev);
Eric Miao1814db62008-01-31 00:58:37 -0500445 struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400446
Chao Xie6ce34a52012-04-01 10:08:01 +0800447 /*
448 * If the keypad is used a wake up source, clock can not be disabled.
449 * Or it can not detect the key pressing.
450 */
Eric Miao39ab9dd2008-06-02 11:20:55 -0400451 if (device_may_wakeup(&pdev->dev))
452 enable_irq_wake(keypad->irq);
Chao Xie6ce34a52012-04-01 10:08:01 +0800453 else
454 clk_disable_unprepare(keypad->clk);
Eric Miao39ab9dd2008-06-02 11:20:55 -0400455
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400456 return 0;
457}
458
Dmitry Torokhovb0010912009-07-24 22:01:43 -0700459static int pxa27x_keypad_resume(struct device *dev)
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400460{
Dmitry Torokhovb0010912009-07-24 22:01:43 -0700461 struct platform_device *pdev = to_platform_device(dev);
Eric Miao1814db62008-01-31 00:58:37 -0500462 struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
Eric Miao1814db62008-01-31 00:58:37 -0500463 struct input_dev *input_dev = keypad->input_dev;
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400464
Chao Xie6ce34a52012-04-01 10:08:01 +0800465 /*
466 * If the keypad is used as wake up source, the clock is not turned
467 * off. So do not need configure it again.
468 */
469 if (device_may_wakeup(&pdev->dev)) {
Eric Miao39ab9dd2008-06-02 11:20:55 -0400470 disable_irq_wake(keypad->irq);
Chao Xie6ce34a52012-04-01 10:08:01 +0800471 } else {
472 mutex_lock(&input_dev->mutex);
Eric Miao39ab9dd2008-06-02 11:20:55 -0400473
Chao Xie6ce34a52012-04-01 10:08:01 +0800474 if (input_dev->users) {
475 /* Enable unit clock */
476 clk_prepare_enable(keypad->clk);
477 pxa27x_keypad_config(keypad);
478 }
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400479
Chao Xie6ce34a52012-04-01 10:08:01 +0800480 mutex_unlock(&input_dev->mutex);
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400481 }
482
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400483 return 0;
484}
Dmitry Torokhovb0010912009-07-24 22:01:43 -0700485
486static const struct dev_pm_ops pxa27x_keypad_pm_ops = {
487 .suspend = pxa27x_keypad_suspend,
488 .resume = pxa27x_keypad_resume,
489};
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400490#endif
491
Bill Pemberton5298cc42012-11-23 21:38:25 -0800492static int pxa27x_keypad_probe(struct platform_device *pdev)
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400493{
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700494 struct pxa27x_keypad_platform_data *pdata = pdev->dev.platform_data;
Eric Miao1814db62008-01-31 00:58:37 -0500495 struct pxa27x_keypad *keypad;
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400496 struct input_dev *input_dev;
Eric Miao9c60deb2008-01-31 00:59:15 -0500497 struct resource *res;
498 int irq, error;
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400499
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700500 if (pdata == NULL) {
Eric Miao1814db62008-01-31 00:58:37 -0500501 dev_err(&pdev->dev, "no platform data defined\n");
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700502 return -EINVAL;
Eric Miao1814db62008-01-31 00:58:37 -0500503 }
504
Eric Miao9c60deb2008-01-31 00:59:15 -0500505 irq = platform_get_irq(pdev, 0);
506 if (irq < 0) {
507 dev_err(&pdev->dev, "failed to get keypad irq\n");
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700508 return -ENXIO;
Eric Miao9c60deb2008-01-31 00:59:15 -0500509 }
510
511 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
512 if (res == NULL) {
513 dev_err(&pdev->dev, "failed to get I/O memory\n");
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700514 return -ENXIO;
515 }
516
517 keypad = kzalloc(sizeof(struct pxa27x_keypad), GFP_KERNEL);
518 input_dev = input_allocate_device();
519 if (!keypad || !input_dev) {
520 dev_err(&pdev->dev, "failed to allocate memory\n");
521 error = -ENOMEM;
Eric Miao9c60deb2008-01-31 00:59:15 -0500522 goto failed_free;
523 }
524
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700525 keypad->pdata = pdata;
526 keypad->input_dev = input_dev;
527 keypad->irq = irq;
528
Dmitry Torokhov52ec7752009-07-22 21:51:40 -0700529 res = request_mem_region(res->start, resource_size(res), pdev->name);
Eric Miao9c60deb2008-01-31 00:59:15 -0500530 if (res == NULL) {
531 dev_err(&pdev->dev, "failed to request I/O memory\n");
532 error = -EBUSY;
533 goto failed_free;
534 }
535
Dmitry Torokhov52ec7752009-07-22 21:51:40 -0700536 keypad->mmio_base = ioremap(res->start, resource_size(res));
Eric Miao9c60deb2008-01-31 00:59:15 -0500537 if (keypad->mmio_base == NULL) {
538 dev_err(&pdev->dev, "failed to remap I/O memory\n");
539 error = -ENXIO;
540 goto failed_free_mem;
541 }
542
Russell Kinge0d8b132008-11-11 17:52:32 +0000543 keypad->clk = clk_get(&pdev->dev, NULL);
Eric Miao1814db62008-01-31 00:58:37 -0500544 if (IS_ERR(keypad->clk)) {
545 dev_err(&pdev->dev, "failed to get keypad clock\n");
546 error = PTR_ERR(keypad->clk);
Eric Miao9c60deb2008-01-31 00:59:15 -0500547 goto failed_free_io;
Russell King22d8a732007-08-20 10:19:39 +0100548 }
549
Eric Miao9c60deb2008-01-31 00:59:15 -0500550 input_dev->name = pdev->name;
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400551 input_dev->id.bustype = BUS_HOST;
Eric Miao0e5f11a2008-01-31 00:56:46 -0500552 input_dev->open = pxa27x_keypad_open;
553 input_dev->close = pxa27x_keypad_close;
Dmitry Torokhov469ba4d2007-04-12 01:34:58 -0400554 input_dev->dev.parent = &pdev->dev;
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400555
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700556 input_dev->keycode = keypad->keycodes;
557 input_dev->keycodesize = sizeof(keypad->keycodes[0]);
558 input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes);
559
Eric Miao1814db62008-01-31 00:58:37 -0500560 input_set_drvdata(input_dev, keypad);
561
Antonio Ospite471637a2008-05-28 14:35:52 -0400562 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700563 input_set_capability(input_dev, EV_MSC, MSC_SCAN);
Eric Miao1814db62008-01-31 00:58:37 -0500564
Chao Xie0a085a92013-05-05 20:24:58 -0700565 error = pxa27x_keypad_build_keycode(keypad);
566 if (error) {
567 dev_err(&pdev->dev, "failed to build keycode\n");
568 goto failed_put_clk;
569 }
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700570
571 if ((pdata->enable_rotary0 && keypad->rotary_rel_code[0] != -1) ||
572 (pdata->enable_rotary1 && keypad->rotary_rel_code[1] != -1)) {
573 input_dev->evbit[0] |= BIT_MASK(EV_REL);
574 }
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400575
Yong Zhangec4665c2011-09-07 14:04:16 -0700576 error = request_irq(irq, pxa27x_keypad_irq_handler, 0,
Eric Miao9c60deb2008-01-31 00:59:15 -0500577 pdev->name, keypad);
578 if (error) {
579 dev_err(&pdev->dev, "failed to request IRQ\n");
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700580 goto failed_put_clk;
Eric Miao9c60deb2008-01-31 00:59:15 -0500581 }
582
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400583 /* Register the input device */
584 error = input_register_device(input_dev);
Eric Miao9c60deb2008-01-31 00:59:15 -0500585 if (error) {
586 dev_err(&pdev->dev, "failed to register input device\n");
587 goto failed_free_irq;
588 }
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400589
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700590 platform_set_drvdata(pdev, keypad);
Eric Miao39ab9dd2008-06-02 11:20:55 -0400591 device_init_wakeup(&pdev->dev, 1);
592
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400593 return 0;
594
Eric Miao9c60deb2008-01-31 00:59:15 -0500595failed_free_irq:
Lars-Peter Clausen8c7f5f52013-05-23 09:30:04 -0700596 free_irq(irq, keypad);
Eric Miao1814db62008-01-31 00:58:37 -0500597failed_put_clk:
598 clk_put(keypad->clk);
Eric Miao9c60deb2008-01-31 00:59:15 -0500599failed_free_io:
600 iounmap(keypad->mmio_base);
601failed_free_mem:
Dmitry Torokhov52ec7752009-07-22 21:51:40 -0700602 release_mem_region(res->start, resource_size(res));
Eric Miao1814db62008-01-31 00:58:37 -0500603failed_free:
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700604 input_free_device(input_dev);
Eric Miao1814db62008-01-31 00:58:37 -0500605 kfree(keypad);
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400606 return error;
607}
608
Bill Pembertone2619cf2012-11-23 21:50:47 -0800609static int pxa27x_keypad_remove(struct platform_device *pdev)
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400610{
Eric Miao1814db62008-01-31 00:58:37 -0500611 struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
Eric Miao9c60deb2008-01-31 00:59:15 -0500612 struct resource *res;
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400613
Lars-Peter Clausen8c7f5f52013-05-23 09:30:04 -0700614 free_irq(keypad->irq, keypad);
Eric Miao1814db62008-01-31 00:58:37 -0500615 clk_put(keypad->clk);
616
617 input_unregister_device(keypad->input_dev);
Eric Miao9c60deb2008-01-31 00:59:15 -0500618 iounmap(keypad->mmio_base);
619
620 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Dmitry Torokhov52ec7752009-07-22 21:51:40 -0700621 release_mem_region(res->start, resource_size(res));
Eric Miao1814db62008-01-31 00:58:37 -0500622
Eric Miao1814db62008-01-31 00:58:37 -0500623 kfree(keypad);
Dmitry Torokhovbd96f372009-09-04 23:46:18 -0700624
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400625 return 0;
626}
627
Kay Sieversd7b52472008-04-18 00:24:42 -0400628/* work with hotplug and coldplug */
629MODULE_ALIAS("platform:pxa27x-keypad");
630
Eric Miao0e5f11a2008-01-31 00:56:46 -0500631static struct platform_driver pxa27x_keypad_driver = {
632 .probe = pxa27x_keypad_probe,
Bill Pemberton1cb0aa82012-11-23 21:27:39 -0800633 .remove = pxa27x_keypad_remove,
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400634 .driver = {
Eric Miao9c60deb2008-01-31 00:59:15 -0500635 .name = "pxa27x-keypad",
Kay Sieversd7b52472008-04-18 00:24:42 -0400636 .owner = THIS_MODULE,
Dmitry Torokhovb0010912009-07-24 22:01:43 -0700637#ifdef CONFIG_PM
638 .pm = &pxa27x_keypad_pm_ops,
639#endif
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400640 },
641};
JJ Ding5146c842011-11-29 11:08:39 -0800642module_platform_driver(pxa27x_keypad_driver);
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400643
Eric Miao0e5f11a2008-01-31 00:56:46 -0500644MODULE_DESCRIPTION("PXA27x Keypad Controller Driver");
Rodolfo Giometti5a90e5b2007-03-16 00:58:52 -0400645MODULE_LICENSE("GPL");