Linux Audio

Check our new training course

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