Input: spear_keyboard - rename bit definitions to reflect register
[deliverable/linux.git] / drivers / input / keyboard / spear-keyboard.c
CommitLineData
bc95df78
RK
1/*
2 * SPEAr Keyboard Driver
3 * Based on omap-keypad driver
4 *
5 * Copyright (C) 2010 ST Microelectronics
6 * Rajeev Kumar<rajeev-dlh.kumar@st.com>
7 *
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.
11 */
12
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>
18#include <linux/io.h>
19#include <linux/irq.h>
20#include <linux/kernel.h>
21#include <linux/module.h>
829c4f96 22#include <linux/of.h>
bc95df78
RK
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>
28
29/* Keyboard Registers */
f6f2efa3 30#define MODE_CTL_REG 0x00
e99191f0
SH
31#define STATUS_REG 0x0C
32#define DATA_REG 0x10
bc95df78
RK
33#define INTR_MASK 0x54
34
35/* Register Values */
36/*
37 * pclk freq mask = (APB FEQ -1)= 82 MHZ.Programme bit 15-9 in mode
38 * control register as 1010010(82MHZ)
39 */
40#define PCLK_FREQ_MSK 0xA400 /* 82 MHz */
1932811f
DT
41#define NUM_ROWS 16
42#define NUM_COLS 16
43
f6f2efa3
SH
44#define MODE_CTL_KEYBOARD (0x2 << 0)
45#define MODE_CTL_SCAN_RATE_10 (0x0 << 2)
46#define MODE_CTL_SCAN_RATE_20 (0x1 << 2)
47#define MODE_CTL_SCAN_RATE_40 (0x2 << 2)
48#define MODE_CTL_SCAN_RATE_80 (0x3 << 2)
49#define MODE_CTL_KEYNUM_SHIFT 6
50#define MODE_CTL_START_SCAN (0x1 << 8)
51
52#define STATUS_DATA_AVAIL (0x1 << 1)
53
54#define DATA_ROW_MASK 0xF0
55#define DATA_COLUMN_MASK 0x0F
56
57#define ROW_SHIFT 4
bc95df78
RK
58
59struct spear_kbd {
60 struct input_dev *input;
61 struct resource *res;
62 void __iomem *io_base;
63 struct clk *clk;
64 unsigned int irq;
f8354c60 65 unsigned int mode;
bc95df78 66 unsigned short last_key;
1932811f 67 unsigned short keycodes[NUM_ROWS * NUM_COLS];
829c4f96 68 bool rep;
bc95df78
RK
69};
70
71static irqreturn_t spear_kbd_interrupt(int irq, void *dev_id)
72{
73 struct spear_kbd *kbd = dev_id;
74 struct input_dev *input = kbd->input;
75 unsigned int key;
e99191f0 76 u32 sts, val;
bc95df78 77
e99191f0 78 sts = readl_relaxed(kbd->io_base + STATUS_REG);
f6f2efa3 79 if (!(sts & STATUS_DATA_AVAIL))
bc95df78
RK
80 return IRQ_NONE;
81
82 if (kbd->last_key != KEY_RESERVED) {
83 input_report_key(input, kbd->last_key, 0);
84 kbd->last_key = KEY_RESERVED;
85 }
86
87 /* following reads active (row, col) pair */
f6f2efa3
SH
88 val = readl_relaxed(kbd->io_base + DATA_REG) &
89 (DATA_ROW_MASK | DATA_COLUMN_MASK);
bc95df78
RK
90 key = kbd->keycodes[val];
91
92 input_event(input, EV_MSC, MSC_SCAN, val);
93 input_report_key(input, key, 1);
94 input_sync(input);
95
96 kbd->last_key = key;
97
98 /* clear interrupt */
e99191f0 99 writel_relaxed(0, kbd->io_base + STATUS_REG);
bc95df78
RK
100
101 return IRQ_HANDLED;
102}
103
104static int spear_kbd_open(struct input_dev *dev)
105{
106 struct spear_kbd *kbd = input_get_drvdata(dev);
107 int error;
e99191f0 108 u32 val;
bc95df78
RK
109
110 kbd->last_key = KEY_RESERVED;
111
112 error = clk_enable(kbd->clk);
113 if (error)
114 return error;
115
116 /* program keyboard */
f6f2efa3
SH
117 val = MODE_CTL_SCAN_RATE_80 | MODE_CTL_KEYBOARD | PCLK_FREQ_MSK |
118 (kbd->mode << MODE_CTL_KEYNUM_SHIFT);
119 writel_relaxed(val, kbd->io_base + MODE_CTL_REG);
e99191f0 120 writel_relaxed(1, kbd->io_base + STATUS_REG);
bc95df78
RK
121
122 /* start key scan */
f6f2efa3
SH
123 val = readl_relaxed(kbd->io_base + MODE_CTL_REG);
124 val |= MODE_CTL_START_SCAN;
125 writel_relaxed(val, kbd->io_base + MODE_CTL_REG);
bc95df78
RK
126
127 return 0;
128}
129
130static void spear_kbd_close(struct input_dev *dev)
131{
132 struct spear_kbd *kbd = input_get_drvdata(dev);
e99191f0 133 u32 val;
bc95df78
RK
134
135 /* stop key scan */
f6f2efa3
SH
136 val = readl_relaxed(kbd->io_base + MODE_CTL_REG);
137 val &= ~MODE_CTL_START_SCAN;
138 writel_relaxed(val, kbd->io_base + MODE_CTL_REG);
bc95df78
RK
139
140 clk_disable(kbd->clk);
141
142 kbd->last_key = KEY_RESERVED;
143}
144
829c4f96
VK
145#ifdef CONFIG_OF
146static int __devinit spear_kbd_parse_dt(struct platform_device *pdev,
147 struct spear_kbd *kbd)
bc95df78 148{
829c4f96 149 struct device_node *np = pdev->dev.of_node;
bc95df78 150 int error;
829c4f96 151 u32 val;
bc95df78 152
829c4f96
VK
153 if (!np) {
154 dev_err(&pdev->dev, "Missing DT data\n");
bc95df78
RK
155 return -EINVAL;
156 }
157
829c4f96
VK
158 if (of_property_read_bool(np, "autorepeat"))
159 kbd->rep = true;
160
161 error = of_property_read_u32(np, "st,mode", &val);
162 if (error) {
163 dev_err(&pdev->dev, "DT: Invalid or missing mode\n");
164 return error;
bc95df78
RK
165 }
166
829c4f96
VK
167 kbd->mode = val;
168 return 0;
169}
170#else
171static inline int spear_kbd_parse_dt(struct platform_device *pdev,
172 struct spear_kbd *kbd)
173{
174 return -ENOSYS;
175}
176#endif
177
178static int __devinit spear_kbd_probe(struct platform_device *pdev)
179{
180 struct kbd_platform_data *pdata = dev_get_platdata(&pdev->dev);
181 const struct matrix_keymap_data *keymap = pdata ? pdata->keymap : NULL;
182 struct spear_kbd *kbd;
183 struct input_dev *input_dev;
184 struct resource *res;
185 int irq;
186 int error;
187
bc95df78
RK
188 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
189 if (!res) {
190 dev_err(&pdev->dev, "no keyboard resource defined\n");
191 return -EBUSY;
192 }
193
194 irq = platform_get_irq(pdev, 0);
195 if (irq < 0) {
196 dev_err(&pdev->dev, "not able to get irq for the device\n");
197 return irq;
198 }
199
200 kbd = kzalloc(sizeof(*kbd), GFP_KERNEL);
201 input_dev = input_allocate_device();
202 if (!kbd || !input_dev) {
203 dev_err(&pdev->dev, "out of memory\n");
204 error = -ENOMEM;
205 goto err_free_mem;
206 }
207
208 kbd->input = input_dev;
209 kbd->irq = irq;
829c4f96
VK
210
211 if (!pdata) {
212 error = spear_kbd_parse_dt(pdev, kbd);
213 if (error)
214 goto err_free_mem;
215 } else {
216 kbd->mode = pdata->mode;
217 kbd->rep = pdata->rep;
218 }
f8354c60 219
bc95df78
RK
220 kbd->res = request_mem_region(res->start, resource_size(res),
221 pdev->name);
222 if (!kbd->res) {
223 dev_err(&pdev->dev, "keyboard region already claimed\n");
224 error = -EBUSY;
225 goto err_free_mem;
226 }
227
228 kbd->io_base = ioremap(res->start, resource_size(res));
229 if (!kbd->io_base) {
230 dev_err(&pdev->dev, "ioremap failed for kbd_region\n");
231 error = -ENOMEM;
232 goto err_release_mem_region;
233 }
234
235 kbd->clk = clk_get(&pdev->dev, NULL);
236 if (IS_ERR(kbd->clk)) {
237 error = PTR_ERR(kbd->clk);
238 goto err_iounmap;
239 }
240
241 input_dev->name = "Spear Keyboard";
242 input_dev->phys = "keyboard/input0";
243 input_dev->dev.parent = &pdev->dev;
244 input_dev->id.bustype = BUS_HOST;
245 input_dev->id.vendor = 0x0001;
246 input_dev->id.product = 0x0001;
247 input_dev->id.version = 0x0100;
248 input_dev->open = spear_kbd_open;
249 input_dev->close = spear_kbd_close;
250
1932811f
DT
251 error = matrix_keypad_build_keymap(keymap, NULL, NUM_ROWS, NUM_COLS,
252 kbd->keycodes, input_dev);
253 if (error) {
254 dev_err(&pdev->dev, "Failed to build keymap\n");
255 goto err_put_clk;
256 }
257
829c4f96 258 if (kbd->rep)
bc95df78
RK
259 __set_bit(EV_REP, input_dev->evbit);
260 input_set_capability(input_dev, EV_MSC, MSC_SCAN);
261
bc95df78
RK
262 input_set_drvdata(input_dev, kbd);
263
264 error = request_irq(irq, spear_kbd_interrupt, 0, "keyboard", kbd);
265 if (error) {
266 dev_err(&pdev->dev, "request_irq fail\n");
267 goto err_put_clk;
268 }
269
270 error = input_register_device(input_dev);
271 if (error) {
272 dev_err(&pdev->dev, "Unable to register keyboard device\n");
273 goto err_free_irq;
274 }
275
276 device_init_wakeup(&pdev->dev, 1);
277 platform_set_drvdata(pdev, kbd);
278
279 return 0;
280
281err_free_irq:
282 free_irq(kbd->irq, kbd);
283err_put_clk:
284 clk_put(kbd->clk);
285err_iounmap:
286 iounmap(kbd->io_base);
287err_release_mem_region:
288 release_mem_region(res->start, resource_size(res));
289err_free_mem:
290 input_free_device(input_dev);
291 kfree(kbd);
292
293 return error;
294}
295
296static int __devexit spear_kbd_remove(struct platform_device *pdev)
297{
298 struct spear_kbd *kbd = platform_get_drvdata(pdev);
299
300 free_irq(kbd->irq, kbd);
301 input_unregister_device(kbd->input);
302 clk_put(kbd->clk);
303 iounmap(kbd->io_base);
304 release_mem_region(kbd->res->start, resource_size(kbd->res));
305 kfree(kbd);
306
5bdea835 307 device_init_wakeup(&pdev->dev, 0);
bc95df78
RK
308 platform_set_drvdata(pdev, NULL);
309
310 return 0;
311}
312
313#ifdef CONFIG_PM
314static int spear_kbd_suspend(struct device *dev)
315{
316 struct platform_device *pdev = to_platform_device(dev);
317 struct spear_kbd *kbd = platform_get_drvdata(pdev);
318 struct input_dev *input_dev = kbd->input;
319
320 mutex_lock(&input_dev->mutex);
321
322 if (input_dev->users)
323 clk_enable(kbd->clk);
324
325 if (device_may_wakeup(&pdev->dev))
326 enable_irq_wake(kbd->irq);
327
328 mutex_unlock(&input_dev->mutex);
329
330 return 0;
331}
332
333static int spear_kbd_resume(struct device *dev)
334{
335 struct platform_device *pdev = to_platform_device(dev);
336 struct spear_kbd *kbd = platform_get_drvdata(pdev);
337 struct input_dev *input_dev = kbd->input;
338
339 mutex_lock(&input_dev->mutex);
340
341 if (device_may_wakeup(&pdev->dev))
342 disable_irq_wake(kbd->irq);
343
344 if (input_dev->users)
345 clk_enable(kbd->clk);
346
347 mutex_unlock(&input_dev->mutex);
348
349 return 0;
350}
bc95df78
RK
351#endif
352
f79e30a8
VK
353static SIMPLE_DEV_PM_OPS(spear_kbd_pm_ops, spear_kbd_suspend, spear_kbd_resume);
354
829c4f96
VK
355#ifdef CONFIG_OF
356static const struct of_device_id spear_kbd_id_table[] = {
357 { .compatible = "st,spear300-kbd" },
358 {}
359};
360MODULE_DEVICE_TABLE(of, spear_kbd_id_table);
361#endif
362
bc95df78
RK
363static struct platform_driver spear_kbd_driver = {
364 .probe = spear_kbd_probe,
365 .remove = __devexit_p(spear_kbd_remove),
366 .driver = {
367 .name = "keyboard",
368 .owner = THIS_MODULE,
bc95df78 369 .pm = &spear_kbd_pm_ops,
829c4f96 370 .of_match_table = of_match_ptr(spear_kbd_id_table),
bc95df78
RK
371 },
372};
5146c84f 373module_platform_driver(spear_kbd_driver);
bc95df78
RK
374
375MODULE_AUTHOR("Rajeev Kumar");
376MODULE_DESCRIPTION("SPEAr Keyboard Driver");
377MODULE_LICENSE("GPL");
This page took 0.083856 seconds and 5 git commands to generate.