• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/input/keyboard/
1/*
2 * DaVinci Key Scan Driver for TI platforms
3 *
4 * Copyright (C) 2009 Texas Instruments, Inc
5 *
6 * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com>
7 *
8 * Intial Code: Sandeep Paulraj <s-paulraj@ti.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24#include <linux/module.h>
25#include <linux/init.h>
26#include <linux/interrupt.h>
27#include <linux/types.h>
28#include <linux/input.h>
29#include <linux/kernel.h>
30#include <linux/delay.h>
31#include <linux/platform_device.h>
32#include <linux/errno.h>
33#include <linux/slab.h>
34
35#include <asm/irq.h>
36
37#include <mach/hardware.h>
38#include <mach/irqs.h>
39#include <mach/keyscan.h>
40
41/* Key scan registers */
42#define DAVINCI_KEYSCAN_KEYCTRL		0x0000
43#define DAVINCI_KEYSCAN_INTENA		0x0004
44#define DAVINCI_KEYSCAN_INTFLAG		0x0008
45#define DAVINCI_KEYSCAN_INTCLR		0x000c
46#define DAVINCI_KEYSCAN_STRBWIDTH	0x0010
47#define DAVINCI_KEYSCAN_INTERVAL	0x0014
48#define DAVINCI_KEYSCAN_CONTTIME	0x0018
49#define DAVINCI_KEYSCAN_CURRENTST	0x001c
50#define DAVINCI_KEYSCAN_PREVSTATE	0x0020
51#define DAVINCI_KEYSCAN_EMUCTRL		0x0024
52#define DAVINCI_KEYSCAN_IODFTCTRL	0x002c
53
54/* Key Control Register (KEYCTRL) */
55#define DAVINCI_KEYSCAN_KEYEN		0x00000001
56#define DAVINCI_KEYSCAN_PREVMODE	0x00000002
57#define DAVINCI_KEYSCAN_CHATOFF		0x00000004
58#define DAVINCI_KEYSCAN_AUTODET		0x00000008
59#define DAVINCI_KEYSCAN_SCANMODE	0x00000010
60#define DAVINCI_KEYSCAN_OUTTYPE		0x00000020
61
62/* Masks for the interrupts */
63#define DAVINCI_KEYSCAN_INT_CONT	0x00000008
64#define DAVINCI_KEYSCAN_INT_OFF		0x00000004
65#define DAVINCI_KEYSCAN_INT_ON		0x00000002
66#define DAVINCI_KEYSCAN_INT_CHANGE	0x00000001
67#define DAVINCI_KEYSCAN_INT_ALL		0x0000000f
68
69struct davinci_ks {
70	struct input_dev		*input;
71	struct davinci_ks_platform_data	*pdata;
72	int				irq;
73	void __iomem			*base;
74	resource_size_t			pbase;
75	size_t				base_size;
76	unsigned short			keymap[];
77};
78
79/* Initializing the kp Module */
80static int __init davinci_ks_initialize(struct davinci_ks *davinci_ks)
81{
82	struct device *dev = &davinci_ks->input->dev;
83	struct davinci_ks_platform_data *pdata = davinci_ks->pdata;
84	u32 matrix_ctrl;
85
86	/* Enable all interrupts */
87	__raw_writel(DAVINCI_KEYSCAN_INT_ALL,
88		     davinci_ks->base + DAVINCI_KEYSCAN_INTENA);
89
90	/* Clear interrupts if any */
91	__raw_writel(DAVINCI_KEYSCAN_INT_ALL,
92		     davinci_ks->base + DAVINCI_KEYSCAN_INTCLR);
93
94	/* Setup the scan period = strobe + interval */
95	__raw_writel(pdata->strobe,
96		     davinci_ks->base + DAVINCI_KEYSCAN_STRBWIDTH);
97	__raw_writel(pdata->interval,
98		     davinci_ks->base + DAVINCI_KEYSCAN_INTERVAL);
99	__raw_writel(0x01,
100		     davinci_ks->base + DAVINCI_KEYSCAN_CONTTIME);
101
102	/* Define matrix type */
103	switch (pdata->matrix_type) {
104	case DAVINCI_KEYSCAN_MATRIX_4X4:
105		matrix_ctrl = 0;
106		break;
107	case DAVINCI_KEYSCAN_MATRIX_5X3:
108		matrix_ctrl = (1 << 6);
109		break;
110	default:
111		dev_err(dev->parent, "wrong matrix type\n");
112		return -EINVAL;
113	}
114
115	/* Enable key scan module and set matrix type */
116	__raw_writel(DAVINCI_KEYSCAN_AUTODET | DAVINCI_KEYSCAN_KEYEN |
117		     matrix_ctrl, davinci_ks->base + DAVINCI_KEYSCAN_KEYCTRL);
118
119	return 0;
120}
121
122static irqreturn_t davinci_ks_interrupt(int irq, void *dev_id)
123{
124	struct davinci_ks *davinci_ks = dev_id;
125	struct device *dev = &davinci_ks->input->dev;
126	unsigned short *keymap = davinci_ks->keymap;
127	int keymapsize = davinci_ks->pdata->keymapsize;
128	u32 prev_status, new_status, changed;
129	bool release;
130	int keycode = KEY_UNKNOWN;
131	int i;
132
133	/* Disable interrupt */
134	__raw_writel(0x0, davinci_ks->base + DAVINCI_KEYSCAN_INTENA);
135
136	/* Reading previous and new status of the key scan */
137	prev_status = __raw_readl(davinci_ks->base + DAVINCI_KEYSCAN_PREVSTATE);
138	new_status = __raw_readl(davinci_ks->base + DAVINCI_KEYSCAN_CURRENTST);
139
140	changed = prev_status ^ new_status;
141
142	if (changed) {
143		/*
144		 * It goes through all bits in 'changed' to ensure
145		 * that no key changes are being missed
146		 */
147		for (i = 0 ; i < keymapsize; i++) {
148			if ((changed>>i) & 0x1) {
149				keycode = keymap[i];
150				release = (new_status >> i) & 0x1;
151				dev_dbg(dev->parent, "key %d %s\n", keycode,
152					release ? "released" : "pressed");
153				input_report_key(davinci_ks->input, keycode,
154						 !release);
155				input_sync(davinci_ks->input);
156			}
157		}
158		/* Clearing interrupt */
159		__raw_writel(DAVINCI_KEYSCAN_INT_ALL,
160			     davinci_ks->base + DAVINCI_KEYSCAN_INTCLR);
161	}
162
163	/* Enable interrupts */
164	__raw_writel(0x1, davinci_ks->base + DAVINCI_KEYSCAN_INTENA);
165
166	return IRQ_HANDLED;
167}
168
169static int __init davinci_ks_probe(struct platform_device *pdev)
170{
171	struct davinci_ks *davinci_ks;
172	struct input_dev *key_dev;
173	struct resource *res, *mem;
174	struct device *dev = &pdev->dev;
175	struct davinci_ks_platform_data *pdata = pdev->dev.platform_data;
176	int error, i;
177
178	if (pdata->device_enable) {
179		error = pdata->device_enable(dev);
180		if (error < 0) {
181			dev_dbg(dev, "device enable function failed\n");
182			return error;
183		}
184	}
185
186	if (!pdata->keymap) {
187		dev_dbg(dev, "no keymap from pdata\n");
188		return -EINVAL;
189	}
190
191	davinci_ks = kzalloc(sizeof(struct davinci_ks) +
192		sizeof(unsigned short) * pdata->keymapsize, GFP_KERNEL);
193	if (!davinci_ks) {
194		dev_dbg(dev, "could not allocate memory for private data\n");
195		return -ENOMEM;
196	}
197
198	memcpy(davinci_ks->keymap, pdata->keymap,
199		sizeof(unsigned short) * pdata->keymapsize);
200
201	key_dev = input_allocate_device();
202	if (!key_dev) {
203		dev_dbg(dev, "could not allocate input device\n");
204		error = -ENOMEM;
205		goto fail1;
206	}
207
208	davinci_ks->input = key_dev;
209
210	davinci_ks->irq = platform_get_irq(pdev, 0);
211	if (davinci_ks->irq < 0) {
212		dev_err(dev, "no key scan irq\n");
213		error = davinci_ks->irq;
214		goto fail2;
215	}
216
217	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
218	if (!res) {
219		dev_err(dev, "no mem resource\n");
220		error = -EINVAL;
221		goto fail2;
222	}
223
224	davinci_ks->pbase = res->start;
225	davinci_ks->base_size = resource_size(res);
226
227	mem = request_mem_region(davinci_ks->pbase, davinci_ks->base_size,
228				 pdev->name);
229	if (!mem) {
230		dev_err(dev, "key scan registers at %08x are not free\n",
231			davinci_ks->pbase);
232		error = -EBUSY;
233		goto fail2;
234	}
235
236	davinci_ks->base = ioremap(davinci_ks->pbase, davinci_ks->base_size);
237	if (!davinci_ks->base) {
238		dev_err(dev, "can't ioremap MEM resource.\n");
239		error = -ENOMEM;
240		goto fail3;
241	}
242
243	/* Enable auto repeat feature of Linux input subsystem */
244	if (pdata->rep)
245		__set_bit(EV_REP, key_dev->evbit);
246
247	/* Setup input device */
248	__set_bit(EV_KEY, key_dev->evbit);
249
250	/* Setup the platform data */
251	davinci_ks->pdata = pdata;
252
253	for (i = 0; i < davinci_ks->pdata->keymapsize; i++)
254		__set_bit(davinci_ks->pdata->keymap[i], key_dev->keybit);
255
256	key_dev->name = "davinci_keyscan";
257	key_dev->phys = "davinci_keyscan/input0";
258	key_dev->dev.parent = &pdev->dev;
259	key_dev->id.bustype = BUS_HOST;
260	key_dev->id.vendor = 0x0001;
261	key_dev->id.product = 0x0001;
262	key_dev->id.version = 0x0001;
263	key_dev->keycode = davinci_ks->keymap;
264	key_dev->keycodesize = sizeof(davinci_ks->keymap[0]);
265	key_dev->keycodemax = davinci_ks->pdata->keymapsize;
266
267	error = input_register_device(davinci_ks->input);
268	if (error < 0) {
269		dev_err(dev, "unable to register davinci key scan device\n");
270		goto fail4;
271	}
272
273	error = request_irq(davinci_ks->irq, davinci_ks_interrupt,
274			  IRQF_DISABLED, pdev->name, davinci_ks);
275	if (error < 0) {
276		dev_err(dev, "unable to register davinci key scan interrupt\n");
277		goto fail5;
278	}
279
280	error = davinci_ks_initialize(davinci_ks);
281	if (error < 0) {
282		dev_err(dev, "unable to initialize davinci key scan device\n");
283		goto fail6;
284	}
285
286	platform_set_drvdata(pdev, davinci_ks);
287	return 0;
288
289fail6:
290	free_irq(davinci_ks->irq, davinci_ks);
291fail5:
292	input_unregister_device(davinci_ks->input);
293	key_dev = NULL;
294fail4:
295	iounmap(davinci_ks->base);
296fail3:
297	release_mem_region(davinci_ks->pbase, davinci_ks->base_size);
298fail2:
299	input_free_device(key_dev);
300fail1:
301	kfree(davinci_ks);
302
303	return error;
304}
305
306static int __devexit davinci_ks_remove(struct platform_device *pdev)
307{
308	struct davinci_ks *davinci_ks = platform_get_drvdata(pdev);
309
310	free_irq(davinci_ks->irq, davinci_ks);
311
312	input_unregister_device(davinci_ks->input);
313
314	iounmap(davinci_ks->base);
315	release_mem_region(davinci_ks->pbase, davinci_ks->base_size);
316
317	platform_set_drvdata(pdev, NULL);
318
319	kfree(davinci_ks);
320
321	return 0;
322}
323
324static struct platform_driver davinci_ks_driver = {
325	.driver	= {
326		.name = "davinci_keyscan",
327		.owner = THIS_MODULE,
328	},
329	.remove	= __devexit_p(davinci_ks_remove),
330};
331
332static int __init davinci_ks_init(void)
333{
334	return platform_driver_probe(&davinci_ks_driver, davinci_ks_probe);
335}
336module_init(davinci_ks_init);
337
338static void __exit davinci_ks_exit(void)
339{
340	platform_driver_unregister(&davinci_ks_driver);
341}
342module_exit(davinci_ks_exit);
343
344MODULE_AUTHOR("Miguel Aguilar");
345MODULE_DESCRIPTION("Texas Instruments DaVinci Key Scan Driver");
346MODULE_LICENSE("GPL");
347