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