2 * SPEAr Keyboard Driver
3 * Based on omap-keypad driver
5 * Copyright (C) 2010 ST Microelectronics
6 * Rajeev Kumar<rajeev-dlh.kumar@st.com>
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
13 #include <linux/clk.h>
14 #include <linux/errno.h>
15 #include <linux/init.h>
16 #include <linux/interrupt.h>
17 #include <linux/input.h>
19 #include <linux/irq.h>
20 #include <linux/kernel.h>
21 #include <linux/module.h>
23 #include <linux/platform_device.h>
24 #include <linux/pm_wakeup.h>
25 #include <linux/slab.h>
26 #include <linux/types.h>
27 #include <plat/keyboard.h>
29 /* Keyboard Registers */
30 #define MODE_REG 0x00 /* 16 bit reg */
31 #define STATUS_REG 0x0C /* 2 bit reg */
32 #define DATA_REG 0x10 /* 8 bit reg */
33 #define INTR_MASK 0x54
37 * pclk freq mask = (APB FEQ -1)= 82 MHZ.Programme bit 15-9 in mode
38 * control register as 1010010(82MHZ)
40 #define PCLK_FREQ_MSK 0xA400 /* 82 MHz */
41 #define START_SCAN 0x0100
42 #define SCAN_RATE_10 0x0000
43 #define SCAN_RATE_20 0x0004
44 #define SCAN_RATE_40 0x0008
45 #define SCAN_RATE_80 0x000C
46 #define MODE_KEYBOARD 0x0002
47 #define DATA_AVAIL 0x2
49 #define KEY_MASK 0xFF000000
50 #define KEY_VALUE 0x00FFFFFF
52 #define COLUMN_MASK 0x0F
56 #define KEY_MATRIX_SHIFT 6
59 struct input_dev
*input
;
61 void __iomem
*io_base
;
65 unsigned short last_key
;
66 unsigned short keycodes
[NUM_ROWS
* NUM_COLS
];
70 static irqreturn_t
spear_kbd_interrupt(int irq
, void *dev_id
)
72 struct spear_kbd
*kbd
= dev_id
;
73 struct input_dev
*input
= kbd
->input
;
77 sts
= readb(kbd
->io_base
+ STATUS_REG
);
78 if (!(sts
& DATA_AVAIL
))
81 if (kbd
->last_key
!= KEY_RESERVED
) {
82 input_report_key(input
, kbd
->last_key
, 0);
83 kbd
->last_key
= KEY_RESERVED
;
86 /* following reads active (row, col) pair */
87 val
= readb(kbd
->io_base
+ DATA_REG
);
88 key
= kbd
->keycodes
[val
];
90 input_event(input
, EV_MSC
, MSC_SCAN
, val
);
91 input_report_key(input
, key
, 1);
97 writeb(0, kbd
->io_base
+ STATUS_REG
);
102 static int spear_kbd_open(struct input_dev
*dev
)
104 struct spear_kbd
*kbd
= input_get_drvdata(dev
);
108 kbd
->last_key
= KEY_RESERVED
;
110 error
= clk_enable(kbd
->clk
);
114 /* program keyboard */
115 val
= SCAN_RATE_80
| MODE_KEYBOARD
| PCLK_FREQ_MSK
|
116 (kbd
->mode
<< KEY_MATRIX_SHIFT
);
117 writew(val
, kbd
->io_base
+ MODE_REG
);
118 writeb(1, kbd
->io_base
+ STATUS_REG
);
121 val
= readw(kbd
->io_base
+ MODE_REG
);
123 writew(val
, kbd
->io_base
+ MODE_REG
);
128 static void spear_kbd_close(struct input_dev
*dev
)
130 struct spear_kbd
*kbd
= input_get_drvdata(dev
);
134 val
= readw(kbd
->io_base
+ MODE_REG
);
136 writew(val
, kbd
->io_base
+ MODE_REG
);
138 clk_disable(kbd
->clk
);
140 kbd
->last_key
= KEY_RESERVED
;
144 static int __devinit
spear_kbd_parse_dt(struct platform_device
*pdev
,
145 struct spear_kbd
*kbd
)
147 struct device_node
*np
= pdev
->dev
.of_node
;
152 dev_err(&pdev
->dev
, "Missing DT data\n");
156 if (of_property_read_bool(np
, "autorepeat"))
159 error
= of_property_read_u32(np
, "st,mode", &val
);
161 dev_err(&pdev
->dev
, "DT: Invalid or missing mode\n");
169 static inline int spear_kbd_parse_dt(struct platform_device
*pdev
,
170 struct spear_kbd
*kbd
)
176 static int __devinit
spear_kbd_probe(struct platform_device
*pdev
)
178 struct kbd_platform_data
*pdata
= dev_get_platdata(&pdev
->dev
);
179 const struct matrix_keymap_data
*keymap
= pdata
? pdata
->keymap
: NULL
;
180 struct spear_kbd
*kbd
;
181 struct input_dev
*input_dev
;
182 struct resource
*res
;
186 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
188 dev_err(&pdev
->dev
, "no keyboard resource defined\n");
192 irq
= platform_get_irq(pdev
, 0);
194 dev_err(&pdev
->dev
, "not able to get irq for the device\n");
198 kbd
= kzalloc(sizeof(*kbd
), GFP_KERNEL
);
199 input_dev
= input_allocate_device();
200 if (!kbd
|| !input_dev
) {
201 dev_err(&pdev
->dev
, "out of memory\n");
206 kbd
->input
= input_dev
;
210 error
= spear_kbd_parse_dt(pdev
, kbd
);
214 kbd
->mode
= pdata
->mode
;
215 kbd
->rep
= pdata
->rep
;
218 kbd
->res
= request_mem_region(res
->start
, resource_size(res
),
221 dev_err(&pdev
->dev
, "keyboard region already claimed\n");
226 kbd
->io_base
= ioremap(res
->start
, resource_size(res
));
228 dev_err(&pdev
->dev
, "ioremap failed for kbd_region\n");
230 goto err_release_mem_region
;
233 kbd
->clk
= clk_get(&pdev
->dev
, NULL
);
234 if (IS_ERR(kbd
->clk
)) {
235 error
= PTR_ERR(kbd
->clk
);
239 input_dev
->name
= "Spear Keyboard";
240 input_dev
->phys
= "keyboard/input0";
241 input_dev
->dev
.parent
= &pdev
->dev
;
242 input_dev
->id
.bustype
= BUS_HOST
;
243 input_dev
->id
.vendor
= 0x0001;
244 input_dev
->id
.product
= 0x0001;
245 input_dev
->id
.version
= 0x0100;
246 input_dev
->open
= spear_kbd_open
;
247 input_dev
->close
= spear_kbd_close
;
249 error
= matrix_keypad_build_keymap(keymap
, NULL
, NUM_ROWS
, NUM_COLS
,
250 kbd
->keycodes
, input_dev
);
252 dev_err(&pdev
->dev
, "Failed to build keymap\n");
257 __set_bit(EV_REP
, input_dev
->evbit
);
258 input_set_capability(input_dev
, EV_MSC
, MSC_SCAN
);
260 input_set_drvdata(input_dev
, kbd
);
262 error
= request_irq(irq
, spear_kbd_interrupt
, 0, "keyboard", kbd
);
264 dev_err(&pdev
->dev
, "request_irq fail\n");
268 error
= input_register_device(input_dev
);
270 dev_err(&pdev
->dev
, "Unable to register keyboard device\n");
274 device_init_wakeup(&pdev
->dev
, 1);
275 platform_set_drvdata(pdev
, kbd
);
280 free_irq(kbd
->irq
, kbd
);
284 iounmap(kbd
->io_base
);
285 err_release_mem_region
:
286 release_mem_region(res
->start
, resource_size(res
));
288 input_free_device(input_dev
);
294 static int __devexit
spear_kbd_remove(struct platform_device
*pdev
)
296 struct spear_kbd
*kbd
= platform_get_drvdata(pdev
);
298 free_irq(kbd
->irq
, kbd
);
299 input_unregister_device(kbd
->input
);
301 iounmap(kbd
->io_base
);
302 release_mem_region(kbd
->res
->start
, resource_size(kbd
->res
));
305 device_init_wakeup(&pdev
->dev
, 1);
306 platform_set_drvdata(pdev
, NULL
);
312 static int spear_kbd_suspend(struct device
*dev
)
314 struct platform_device
*pdev
= to_platform_device(dev
);
315 struct spear_kbd
*kbd
= platform_get_drvdata(pdev
);
316 struct input_dev
*input_dev
= kbd
->input
;
318 mutex_lock(&input_dev
->mutex
);
320 if (input_dev
->users
)
321 clk_enable(kbd
->clk
);
323 if (device_may_wakeup(&pdev
->dev
))
324 enable_irq_wake(kbd
->irq
);
326 mutex_unlock(&input_dev
->mutex
);
331 static int spear_kbd_resume(struct device
*dev
)
333 struct platform_device
*pdev
= to_platform_device(dev
);
334 struct spear_kbd
*kbd
= platform_get_drvdata(pdev
);
335 struct input_dev
*input_dev
= kbd
->input
;
337 mutex_lock(&input_dev
->mutex
);
339 if (device_may_wakeup(&pdev
->dev
))
340 disable_irq_wake(kbd
->irq
);
342 if (input_dev
->users
)
343 clk_enable(kbd
->clk
);
345 mutex_unlock(&input_dev
->mutex
);
351 static SIMPLE_DEV_PM_OPS(spear_kbd_pm_ops
, spear_kbd_suspend
, spear_kbd_resume
);
354 static const struct of_device_id spear_kbd_id_table
[] = {
355 { .compatible
= "st,spear300-kbd" },
358 MODULE_DEVICE_TABLE(of
, spear_kbd_id_table
);
361 static struct platform_driver spear_kbd_driver
= {
362 .probe
= spear_kbd_probe
,
363 .remove
= __devexit_p(spear_kbd_remove
),
366 .owner
= THIS_MODULE
,
367 .pm
= &spear_kbd_pm_ops
,
368 .of_match_table
= of_match_ptr(spear_kbd_id_table
),
371 module_platform_driver(spear_kbd_driver
);
373 MODULE_AUTHOR("Rajeev Kumar");
374 MODULE_DESCRIPTION("SPEAr Keyboard Driver");
375 MODULE_LICENSE("GPL");