xref: /openbmc/linux/drivers/input/misc/cma3000_d0x.c (revision d2d8442d)
1b029ffafSHemanth V /*
2b029ffafSHemanth V  * VTI CMA3000_D0x Accelerometer driver
3b029ffafSHemanth V  *
4b029ffafSHemanth V  * Copyright (C) 2010 Texas Instruments
5b029ffafSHemanth V  * Author: Hemanth V <hemanthv@ti.com>
6b029ffafSHemanth V  *
7b029ffafSHemanth V  * This program is free software; you can redistribute it and/or modify it
8b029ffafSHemanth V  * under the terms of the GNU General Public License version 2 as published by
9b029ffafSHemanth V  * the Free Software Foundation.
10b029ffafSHemanth V  *
11b029ffafSHemanth V  * This program is distributed in the hope that it will be useful, but WITHOUT
12b029ffafSHemanth V  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13b029ffafSHemanth V  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14b029ffafSHemanth V  * more details.
15b029ffafSHemanth V  *
16b029ffafSHemanth V  * You should have received a copy of the GNU General Public License along with
17b029ffafSHemanth V  * this program.  If not, see <http://www.gnu.org/licenses/>.
18b029ffafSHemanth V  */
19b029ffafSHemanth V 
20b029ffafSHemanth V #include <linux/types.h>
21b029ffafSHemanth V #include <linux/interrupt.h>
22b029ffafSHemanth V #include <linux/delay.h>
23b029ffafSHemanth V #include <linux/slab.h>
24b029ffafSHemanth V #include <linux/input.h>
25b029ffafSHemanth V #include <linux/input/cma3000.h>
26d2d8442dSPaul Gortmaker #include <linux/module.h>
27b029ffafSHemanth V 
28b029ffafSHemanth V #include "cma3000_d0x.h"
29b029ffafSHemanth V 
30b029ffafSHemanth V #define CMA3000_WHOAMI      0x00
31b029ffafSHemanth V #define CMA3000_REVID       0x01
32b029ffafSHemanth V #define CMA3000_CTRL        0x02
33b029ffafSHemanth V #define CMA3000_STATUS      0x03
34b029ffafSHemanth V #define CMA3000_RSTR        0x04
35b029ffafSHemanth V #define CMA3000_INTSTATUS   0x05
36b029ffafSHemanth V #define CMA3000_DOUTX       0x06
37b029ffafSHemanth V #define CMA3000_DOUTY       0x07
38b029ffafSHemanth V #define CMA3000_DOUTZ       0x08
39b029ffafSHemanth V #define CMA3000_MDTHR       0x09
40b029ffafSHemanth V #define CMA3000_MDFFTMR     0x0A
41b029ffafSHemanth V #define CMA3000_FFTHR       0x0B
42b029ffafSHemanth V 
43b029ffafSHemanth V #define CMA3000_RANGE2G    (1 << 7)
44b029ffafSHemanth V #define CMA3000_RANGE8G    (0 << 7)
45b029ffafSHemanth V #define CMA3000_BUSI2C     (0 << 4)
46b029ffafSHemanth V #define CMA3000_MODEMASK   (7 << 1)
47b029ffafSHemanth V #define CMA3000_GRANGEMASK (1 << 7)
48b029ffafSHemanth V 
49b029ffafSHemanth V #define CMA3000_STATUS_PERR    1
50b029ffafSHemanth V #define CMA3000_INTSTATUS_FFDET (1 << 2)
51b029ffafSHemanth V 
52b029ffafSHemanth V /* Settling time delay in ms */
53b029ffafSHemanth V #define CMA3000_SETDELAY    30
54b029ffafSHemanth V 
55b029ffafSHemanth V /* Delay for clearing interrupt in us */
56b029ffafSHemanth V #define CMA3000_INTDELAY    44
57b029ffafSHemanth V 
58b029ffafSHemanth V 
59b029ffafSHemanth V /*
60b029ffafSHemanth V  * Bit weights in mg for bit 0, other bits need
61b029ffafSHemanth V  * multipy factor 2^n. Eight bit is the sign bit.
62b029ffafSHemanth V  */
63b029ffafSHemanth V #define BIT_TO_2G  18
64b029ffafSHemanth V #define BIT_TO_8G  71
65b029ffafSHemanth V 
66b029ffafSHemanth V struct cma3000_accl_data {
67b029ffafSHemanth V 	const struct cma3000_bus_ops *bus_ops;
68b029ffafSHemanth V 	const struct cma3000_platform_data *pdata;
69b029ffafSHemanth V 
70b029ffafSHemanth V 	struct device *dev;
71b029ffafSHemanth V 	struct input_dev *input_dev;
72b029ffafSHemanth V 
73b029ffafSHemanth V 	int bit_to_mg;
74b029ffafSHemanth V 	int irq;
75b029ffafSHemanth V 
76b029ffafSHemanth V 	int g_range;
77b029ffafSHemanth V 	u8 mode;
78b029ffafSHemanth V 
79b029ffafSHemanth V 	struct mutex mutex;
80b029ffafSHemanth V 	bool opened;
81b029ffafSHemanth V 	bool suspended;
82b029ffafSHemanth V };
83b029ffafSHemanth V 
84b029ffafSHemanth V #define CMA3000_READ(data, reg, msg) \
85b029ffafSHemanth V 	(data->bus_ops->read(data->dev, reg, msg))
86b029ffafSHemanth V #define CMA3000_SET(data, reg, val, msg) \
87b029ffafSHemanth V 	((data)->bus_ops->write(data->dev, reg, val, msg))
88b029ffafSHemanth V 
89b029ffafSHemanth V /*
90b029ffafSHemanth V  * Conversion for each of the eight modes to g, depending
91b029ffafSHemanth V  * on G range i.e 2G or 8G. Some modes always operate in
92b029ffafSHemanth V  * 8G.
93b029ffafSHemanth V  */
94b029ffafSHemanth V 
95b029ffafSHemanth V static int mode_to_mg[8][2] = {
96b029ffafSHemanth V 	{ 0, 0 },
97b029ffafSHemanth V 	{ BIT_TO_8G, BIT_TO_2G },
98b029ffafSHemanth V 	{ BIT_TO_8G, BIT_TO_2G },
99b029ffafSHemanth V 	{ BIT_TO_8G, BIT_TO_8G },
100b029ffafSHemanth V 	{ BIT_TO_8G, BIT_TO_8G },
101b029ffafSHemanth V 	{ BIT_TO_8G, BIT_TO_2G },
102b029ffafSHemanth V 	{ BIT_TO_8G, BIT_TO_2G },
103b029ffafSHemanth V 	{ 0, 0},
104b029ffafSHemanth V };
105b029ffafSHemanth V 
106b029ffafSHemanth V static void decode_mg(struct cma3000_accl_data *data, int *datax,
107b029ffafSHemanth V 				int *datay, int *dataz)
108b029ffafSHemanth V {
109b029ffafSHemanth V 	/* Data in 2's complement, convert to mg */
110b029ffafSHemanth V 	*datax = ((s8)*datax) * data->bit_to_mg;
111b029ffafSHemanth V 	*datay = ((s8)*datay) * data->bit_to_mg;
112b029ffafSHemanth V 	*dataz = ((s8)*dataz) * data->bit_to_mg;
113b029ffafSHemanth V }
114b029ffafSHemanth V 
115b029ffafSHemanth V static irqreturn_t cma3000_thread_irq(int irq, void *dev_id)
116b029ffafSHemanth V {
117b029ffafSHemanth V 	struct cma3000_accl_data *data = dev_id;
118b029ffafSHemanth V 	int datax, datay, dataz;
119b029ffafSHemanth V 	u8 ctrl, mode, range, intr_status;
120b029ffafSHemanth V 
121b029ffafSHemanth V 	intr_status = CMA3000_READ(data, CMA3000_INTSTATUS, "interrupt status");
122b029ffafSHemanth V 	if (intr_status < 0)
123b029ffafSHemanth V 		return IRQ_NONE;
124b029ffafSHemanth V 
125b029ffafSHemanth V 	/* Check if free fall is detected, report immediately */
126b029ffafSHemanth V 	if (intr_status & CMA3000_INTSTATUS_FFDET) {
127b029ffafSHemanth V 		input_report_abs(data->input_dev, ABS_MISC, 1);
128b029ffafSHemanth V 		input_sync(data->input_dev);
129b029ffafSHemanth V 	} else {
130b029ffafSHemanth V 		input_report_abs(data->input_dev, ABS_MISC, 0);
131b029ffafSHemanth V 	}
132b029ffafSHemanth V 
133b029ffafSHemanth V 	datax = CMA3000_READ(data, CMA3000_DOUTX, "X");
134b029ffafSHemanth V 	datay = CMA3000_READ(data, CMA3000_DOUTY, "Y");
135b029ffafSHemanth V 	dataz = CMA3000_READ(data, CMA3000_DOUTZ, "Z");
136b029ffafSHemanth V 
137b029ffafSHemanth V 	ctrl = CMA3000_READ(data, CMA3000_CTRL, "ctrl");
138b029ffafSHemanth V 	mode = (ctrl & CMA3000_MODEMASK) >> 1;
139b029ffafSHemanth V 	range = (ctrl & CMA3000_GRANGEMASK) >> 7;
140b029ffafSHemanth V 
141b029ffafSHemanth V 	data->bit_to_mg = mode_to_mg[mode][range];
142b029ffafSHemanth V 
143b029ffafSHemanth V 	/* Interrupt not for this device */
144b029ffafSHemanth V 	if (data->bit_to_mg == 0)
145b029ffafSHemanth V 		return IRQ_NONE;
146b029ffafSHemanth V 
147b029ffafSHemanth V 	/* Decode register values to milli g */
148b029ffafSHemanth V 	decode_mg(data, &datax, &datay, &dataz);
149b029ffafSHemanth V 
150b029ffafSHemanth V 	input_report_abs(data->input_dev, ABS_X, datax);
151b029ffafSHemanth V 	input_report_abs(data->input_dev, ABS_Y, datay);
152b029ffafSHemanth V 	input_report_abs(data->input_dev, ABS_Z, dataz);
153b029ffafSHemanth V 	input_sync(data->input_dev);
154b029ffafSHemanth V 
155b029ffafSHemanth V 	return IRQ_HANDLED;
156b029ffafSHemanth V }
157b029ffafSHemanth V 
158b029ffafSHemanth V static int cma3000_reset(struct cma3000_accl_data *data)
159b029ffafSHemanth V {
160b029ffafSHemanth V 	int val;
161b029ffafSHemanth V 
162b029ffafSHemanth V 	/* Reset sequence */
163b029ffafSHemanth V 	CMA3000_SET(data, CMA3000_RSTR, 0x02, "Reset");
164b029ffafSHemanth V 	CMA3000_SET(data, CMA3000_RSTR, 0x0A, "Reset");
165b029ffafSHemanth V 	CMA3000_SET(data, CMA3000_RSTR, 0x04, "Reset");
166b029ffafSHemanth V 
167b029ffafSHemanth V 	/* Settling time delay */
168b029ffafSHemanth V 	mdelay(10);
169b029ffafSHemanth V 
170b029ffafSHemanth V 	val = CMA3000_READ(data, CMA3000_STATUS, "Status");
171b029ffafSHemanth V 	if (val < 0) {
172b029ffafSHemanth V 		dev_err(data->dev, "Reset failed\n");
173b029ffafSHemanth V 		return val;
174b029ffafSHemanth V 	}
175b029ffafSHemanth V 
176b029ffafSHemanth V 	if (val & CMA3000_STATUS_PERR) {
177b029ffafSHemanth V 		dev_err(data->dev, "Parity Error\n");
178b029ffafSHemanth V 		return -EIO;
179b029ffafSHemanth V 	}
180b029ffafSHemanth V 
181b029ffafSHemanth V 	return 0;
182b029ffafSHemanth V }
183b029ffafSHemanth V 
184b029ffafSHemanth V static int cma3000_poweron(struct cma3000_accl_data *data)
185b029ffafSHemanth V {
186b029ffafSHemanth V 	const struct cma3000_platform_data *pdata = data->pdata;
187b029ffafSHemanth V 	u8 ctrl = 0;
188b029ffafSHemanth V 	int ret;
189b029ffafSHemanth V 
190b029ffafSHemanth V 	if (data->g_range == CMARANGE_2G) {
191b029ffafSHemanth V 		ctrl = (data->mode << 1) | CMA3000_RANGE2G;
192b029ffafSHemanth V 	} else if (data->g_range == CMARANGE_8G) {
193b029ffafSHemanth V 		ctrl = (data->mode << 1) | CMA3000_RANGE8G;
194b029ffafSHemanth V 	} else {
195b029ffafSHemanth V 		dev_info(data->dev,
196b029ffafSHemanth V 			 "Invalid G range specified, assuming 8G\n");
197b029ffafSHemanth V 		ctrl = (data->mode << 1) | CMA3000_RANGE8G;
198b029ffafSHemanth V 	}
199b029ffafSHemanth V 
200b029ffafSHemanth V 	ctrl |= data->bus_ops->ctrl_mod;
201b029ffafSHemanth V 
202b029ffafSHemanth V 	CMA3000_SET(data, CMA3000_MDTHR, pdata->mdthr,
203b029ffafSHemanth V 		    "Motion Detect Threshold");
204b029ffafSHemanth V 	CMA3000_SET(data, CMA3000_MDFFTMR, pdata->mdfftmr,
205b029ffafSHemanth V 		    "Time register");
206b029ffafSHemanth V 	CMA3000_SET(data, CMA3000_FFTHR, pdata->ffthr,
207b029ffafSHemanth V 		    "Free fall threshold");
208b029ffafSHemanth V 	ret = CMA3000_SET(data, CMA3000_CTRL, ctrl, "Mode setting");
209b029ffafSHemanth V 	if (ret < 0)
210b029ffafSHemanth V 		return -EIO;
211b029ffafSHemanth V 
212b029ffafSHemanth V 	msleep(CMA3000_SETDELAY);
213b029ffafSHemanth V 
214b029ffafSHemanth V 	return 0;
215b029ffafSHemanth V }
216b029ffafSHemanth V 
217b029ffafSHemanth V static int cma3000_poweroff(struct cma3000_accl_data *data)
218b029ffafSHemanth V {
219b029ffafSHemanth V 	int ret;
220b029ffafSHemanth V 
221b029ffafSHemanth V 	ret = CMA3000_SET(data, CMA3000_CTRL, CMAMODE_POFF, "Mode setting");
222b029ffafSHemanth V 	msleep(CMA3000_SETDELAY);
223b029ffafSHemanth V 
224b029ffafSHemanth V 	return ret;
225b029ffafSHemanth V }
226b029ffafSHemanth V 
227b029ffafSHemanth V static int cma3000_open(struct input_dev *input_dev)
228b029ffafSHemanth V {
229b029ffafSHemanth V 	struct cma3000_accl_data *data = input_get_drvdata(input_dev);
230b029ffafSHemanth V 
231b029ffafSHemanth V 	mutex_lock(&data->mutex);
232b029ffafSHemanth V 
233b029ffafSHemanth V 	if (!data->suspended)
234b029ffafSHemanth V 		cma3000_poweron(data);
235b029ffafSHemanth V 
236b029ffafSHemanth V 	data->opened = true;
237b029ffafSHemanth V 
238b029ffafSHemanth V 	mutex_unlock(&data->mutex);
239b029ffafSHemanth V 
240b029ffafSHemanth V 	return 0;
241b029ffafSHemanth V }
242b029ffafSHemanth V 
243b029ffafSHemanth V static void cma3000_close(struct input_dev *input_dev)
244b029ffafSHemanth V {
245b029ffafSHemanth V 	struct cma3000_accl_data *data = input_get_drvdata(input_dev);
246b029ffafSHemanth V 
247b029ffafSHemanth V 	mutex_lock(&data->mutex);
248b029ffafSHemanth V 
249b029ffafSHemanth V 	if (!data->suspended)
250b029ffafSHemanth V 		cma3000_poweroff(data);
251b029ffafSHemanth V 
252b029ffafSHemanth V 	data->opened = false;
253b029ffafSHemanth V 
254b029ffafSHemanth V 	mutex_unlock(&data->mutex);
255b029ffafSHemanth V }
256b029ffafSHemanth V 
257b029ffafSHemanth V void cma3000_suspend(struct cma3000_accl_data *data)
258b029ffafSHemanth V {
259b029ffafSHemanth V 	mutex_lock(&data->mutex);
260b029ffafSHemanth V 
261b029ffafSHemanth V 	if (!data->suspended && data->opened)
262b029ffafSHemanth V 		cma3000_poweroff(data);
263b029ffafSHemanth V 
264b029ffafSHemanth V 	data->suspended = true;
265b029ffafSHemanth V 
266b029ffafSHemanth V 	mutex_unlock(&data->mutex);
267b029ffafSHemanth V }
268b029ffafSHemanth V EXPORT_SYMBOL(cma3000_suspend);
269b029ffafSHemanth V 
270b029ffafSHemanth V 
271b029ffafSHemanth V void cma3000_resume(struct cma3000_accl_data *data)
272b029ffafSHemanth V {
273b029ffafSHemanth V 	mutex_lock(&data->mutex);
274b029ffafSHemanth V 
275b029ffafSHemanth V 	if (data->suspended && data->opened)
276b029ffafSHemanth V 		cma3000_poweron(data);
277b029ffafSHemanth V 
278b029ffafSHemanth V 	data->suspended = false;
279b029ffafSHemanth V 
280b029ffafSHemanth V 	mutex_unlock(&data->mutex);
281b029ffafSHemanth V }
282b029ffafSHemanth V EXPORT_SYMBOL(cma3000_resume);
283b029ffafSHemanth V 
284b029ffafSHemanth V struct cma3000_accl_data *cma3000_init(struct device *dev, int irq,
285b029ffafSHemanth V 				       const struct cma3000_bus_ops *bops)
286b029ffafSHemanth V {
287b029ffafSHemanth V 	const struct cma3000_platform_data *pdata = dev->platform_data;
288b029ffafSHemanth V 	struct cma3000_accl_data *data;
289b029ffafSHemanth V 	struct input_dev *input_dev;
290b029ffafSHemanth V 	int rev;
291b029ffafSHemanth V 	int error;
292b029ffafSHemanth V 
293b029ffafSHemanth V 	if (!pdata) {
294b029ffafSHemanth V 		dev_err(dev, "platform data not found\n");
295b029ffafSHemanth V 		error = -EINVAL;
296b029ffafSHemanth V 		goto err_out;
297b029ffafSHemanth V 	}
298b029ffafSHemanth V 
299b029ffafSHemanth V 
300b029ffafSHemanth V 	/* if no IRQ return error */
301b029ffafSHemanth V 	if (irq == 0) {
302b029ffafSHemanth V 		error = -EINVAL;
303b029ffafSHemanth V 		goto err_out;
304b029ffafSHemanth V 	}
305b029ffafSHemanth V 
306b029ffafSHemanth V 	data = kzalloc(sizeof(struct cma3000_accl_data), GFP_KERNEL);
307b029ffafSHemanth V 	input_dev = input_allocate_device();
308b029ffafSHemanth V 	if (!data || !input_dev) {
309b029ffafSHemanth V 		error = -ENOMEM;
310b029ffafSHemanth V 		goto err_free_mem;
311b029ffafSHemanth V 	}
312b029ffafSHemanth V 
313b029ffafSHemanth V 	data->dev = dev;
314b029ffafSHemanth V 	data->input_dev = input_dev;
315b029ffafSHemanth V 	data->bus_ops = bops;
316b029ffafSHemanth V 	data->pdata = pdata;
317b029ffafSHemanth V 	data->irq = irq;
318b029ffafSHemanth V 	mutex_init(&data->mutex);
319b029ffafSHemanth V 
320b029ffafSHemanth V 	data->mode = pdata->mode;
321b029ffafSHemanth V 	if (data->mode < CMAMODE_DEFAULT || data->mode > CMAMODE_POFF) {
322b029ffafSHemanth V 		data->mode = CMAMODE_MOTDET;
323b029ffafSHemanth V 		dev_warn(dev,
324b029ffafSHemanth V 			 "Invalid mode specified, assuming Motion Detect\n");
325b029ffafSHemanth V 	}
326b029ffafSHemanth V 
327b029ffafSHemanth V 	data->g_range = pdata->g_range;
328b029ffafSHemanth V 	if (data->g_range != CMARANGE_2G && data->g_range != CMARANGE_8G) {
329b029ffafSHemanth V 		dev_info(dev,
330b029ffafSHemanth V 			 "Invalid G range specified, assuming 8G\n");
331b029ffafSHemanth V 		data->g_range = CMARANGE_8G;
332b029ffafSHemanth V 	}
333b029ffafSHemanth V 
334b029ffafSHemanth V 	input_dev->name = "cma3000-accelerometer";
335b029ffafSHemanth V 	input_dev->id.bustype = bops->bustype;
336b029ffafSHemanth V 	input_dev->open = cma3000_open;
337b029ffafSHemanth V 	input_dev->close = cma3000_close;
338b029ffafSHemanth V 
339b029ffafSHemanth V 	 __set_bit(EV_ABS, input_dev->evbit);
340b029ffafSHemanth V 
341b029ffafSHemanth V 	input_set_abs_params(input_dev, ABS_X,
342b029ffafSHemanth V 			-data->g_range, data->g_range, pdata->fuzz_x, 0);
343b029ffafSHemanth V 	input_set_abs_params(input_dev, ABS_Y,
344b029ffafSHemanth V 			-data->g_range, data->g_range, pdata->fuzz_y, 0);
345b029ffafSHemanth V 	input_set_abs_params(input_dev, ABS_Z,
346b029ffafSHemanth V 			-data->g_range, data->g_range, pdata->fuzz_z, 0);
347b029ffafSHemanth V 	input_set_abs_params(input_dev, ABS_MISC, 0, 1, 0, 0);
348b029ffafSHemanth V 
349b029ffafSHemanth V 	input_set_drvdata(input_dev, data);
350b029ffafSHemanth V 
351b029ffafSHemanth V 	error = cma3000_reset(data);
352b029ffafSHemanth V 	if (error)
353b029ffafSHemanth V 		goto err_free_mem;
354b029ffafSHemanth V 
355b029ffafSHemanth V 	rev = CMA3000_READ(data, CMA3000_REVID, "Revid");
356b029ffafSHemanth V 	if (rev < 0) {
357b029ffafSHemanth V 		error = rev;
358b029ffafSHemanth V 		goto err_free_mem;
359b029ffafSHemanth V 	}
360b029ffafSHemanth V 
361b029ffafSHemanth V 	pr_info("CMA3000 Accelerometer: Revision %x\n", rev);
362b029ffafSHemanth V 
363b029ffafSHemanth V 	error = request_threaded_irq(irq, NULL, cma3000_thread_irq,
364b029ffafSHemanth V 				     pdata->irqflags | IRQF_ONESHOT,
365b029ffafSHemanth V 				     "cma3000_d0x", data);
366b029ffafSHemanth V 	if (error) {
367b029ffafSHemanth V 		dev_err(dev, "request_threaded_irq failed\n");
368b029ffafSHemanth V 		goto err_free_mem;
369b029ffafSHemanth V 	}
370b029ffafSHemanth V 
371b029ffafSHemanth V 	error = input_register_device(data->input_dev);
372b029ffafSHemanth V 	if (error) {
373b029ffafSHemanth V 		dev_err(dev, "Unable to register input device\n");
374b029ffafSHemanth V 		goto err_free_irq;
375b029ffafSHemanth V 	}
376b029ffafSHemanth V 
377b029ffafSHemanth V 	return data;
378b029ffafSHemanth V 
379b029ffafSHemanth V err_free_irq:
380b029ffafSHemanth V 	free_irq(irq, data);
381b029ffafSHemanth V err_free_mem:
382b029ffafSHemanth V 	input_free_device(input_dev);
383b029ffafSHemanth V 	kfree(data);
384b029ffafSHemanth V err_out:
385b029ffafSHemanth V 	return ERR_PTR(error);
386b029ffafSHemanth V }
387b029ffafSHemanth V EXPORT_SYMBOL(cma3000_init);
388b029ffafSHemanth V 
389b029ffafSHemanth V void cma3000_exit(struct cma3000_accl_data *data)
390b029ffafSHemanth V {
391b029ffafSHemanth V 	free_irq(data->irq, data);
392b029ffafSHemanth V 	input_unregister_device(data->input_dev);
393b029ffafSHemanth V 	kfree(data);
394b029ffafSHemanth V }
395b029ffafSHemanth V EXPORT_SYMBOL(cma3000_exit);
396b029ffafSHemanth V 
397b029ffafSHemanth V MODULE_DESCRIPTION("CMA3000-D0x Accelerometer Driver");
398b029ffafSHemanth V MODULE_LICENSE("GPL");
399b029ffafSHemanth V MODULE_AUTHOR("Hemanth V <hemanthv@ti.com>");
400