xref: /openbmc/linux/drivers/input/misc/bma150.c (revision f63bb4f4)
1c17ca3f5SEric Andersson /*
2c17ca3f5SEric Andersson  * Copyright (c) 2011 Bosch Sensortec GmbH
3c17ca3f5SEric Andersson  * Copyright (c) 2011 Unixphere
4c17ca3f5SEric Andersson  *
5c17ca3f5SEric Andersson  * This driver adds support for Bosch Sensortec's digital acceleration
6c17ca3f5SEric Andersson  * sensors BMA150 and SMB380.
7c17ca3f5SEric Andersson  * The SMB380 is fully compatible with BMA150 and only differs in packaging.
8c17ca3f5SEric Andersson  *
9c17ca3f5SEric Andersson  * The datasheet for the BMA150 chip can be found here:
10c17ca3f5SEric Andersson  * http://www.bosch-sensortec.com/content/language1/downloads/BST-BMA150-DS000-07.pdf
11c17ca3f5SEric Andersson  *
12c17ca3f5SEric Andersson  * This program is free software; you can redistribute it and/or modify
13c17ca3f5SEric Andersson  * it under the terms of the GNU General Public License as published by
14c17ca3f5SEric Andersson  * the Free Software Foundation; either version 2 of the License, or
15c17ca3f5SEric Andersson  * (at your option) any later version.
16c17ca3f5SEric Andersson  *
17c17ca3f5SEric Andersson  * This program is distributed in the hope that it will be useful,
18c17ca3f5SEric Andersson  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19c17ca3f5SEric Andersson  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20c17ca3f5SEric Andersson  * GNU General Public License for more details.
21c17ca3f5SEric Andersson  *
22c17ca3f5SEric Andersson  * You should have received a copy of the GNU General Public License
23c17ca3f5SEric Andersson  * along with this program; if not, write to the Free Software
24c17ca3f5SEric Andersson  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25c17ca3f5SEric Andersson  */
26c17ca3f5SEric Andersson #include <linux/kernel.h>
27c17ca3f5SEric Andersson #include <linux/module.h>
28c17ca3f5SEric Andersson #include <linux/i2c.h>
29c17ca3f5SEric Andersson #include <linux/input.h>
30c17ca3f5SEric Andersson #include <linux/input-polldev.h>
31c17ca3f5SEric Andersson #include <linux/interrupt.h>
32c17ca3f5SEric Andersson #include <linux/delay.h>
33c17ca3f5SEric Andersson #include <linux/slab.h>
34c17ca3f5SEric Andersson #include <linux/pm.h>
35c17ca3f5SEric Andersson #include <linux/pm_runtime.h>
36c17ca3f5SEric Andersson #include <linux/bma150.h>
37c17ca3f5SEric Andersson 
38c17ca3f5SEric Andersson #define ABSMAX_ACC_VAL		0x01FF
39c17ca3f5SEric Andersson #define ABSMIN_ACC_VAL		-(ABSMAX_ACC_VAL)
40c17ca3f5SEric Andersson 
41c17ca3f5SEric Andersson /* Each axis is represented by a 2-byte data word */
42c17ca3f5SEric Andersson #define BMA150_XYZ_DATA_SIZE	6
43c17ca3f5SEric Andersson 
44c17ca3f5SEric Andersson /* Input poll interval in milliseconds */
45c17ca3f5SEric Andersson #define BMA150_POLL_INTERVAL	10
46c17ca3f5SEric Andersson #define BMA150_POLL_MAX		200
47c17ca3f5SEric Andersson #define BMA150_POLL_MIN		0
48c17ca3f5SEric Andersson 
49c17ca3f5SEric Andersson #define BMA150_MODE_NORMAL	0
50c17ca3f5SEric Andersson #define BMA150_MODE_SLEEP	2
51c17ca3f5SEric Andersson #define BMA150_MODE_WAKE_UP	3
52c17ca3f5SEric Andersson 
53c17ca3f5SEric Andersson /* Data register addresses */
54c17ca3f5SEric Andersson #define BMA150_DATA_0_REG	0x00
55c17ca3f5SEric Andersson #define BMA150_DATA_1_REG	0x01
56c17ca3f5SEric Andersson #define BMA150_DATA_2_REG	0x02
57c17ca3f5SEric Andersson 
58c17ca3f5SEric Andersson /* Control register addresses */
59c17ca3f5SEric Andersson #define BMA150_CTRL_0_REG	0x0A
60c17ca3f5SEric Andersson #define BMA150_CTRL_1_REG	0x0B
61c17ca3f5SEric Andersson #define BMA150_CTRL_2_REG	0x14
62c17ca3f5SEric Andersson #define BMA150_CTRL_3_REG	0x15
63c17ca3f5SEric Andersson 
64c17ca3f5SEric Andersson /* Configuration/Setting register addresses */
65c17ca3f5SEric Andersson #define BMA150_CFG_0_REG	0x0C
66c17ca3f5SEric Andersson #define BMA150_CFG_1_REG	0x0D
67c17ca3f5SEric Andersson #define BMA150_CFG_2_REG	0x0E
68c17ca3f5SEric Andersson #define BMA150_CFG_3_REG	0x0F
69c17ca3f5SEric Andersson #define BMA150_CFG_4_REG	0x10
70c17ca3f5SEric Andersson #define BMA150_CFG_5_REG	0x11
71c17ca3f5SEric Andersson 
72c17ca3f5SEric Andersson #define BMA150_CHIP_ID		2
73ef3714fdSDr. H. Nikolaus Schaller #define BMA180_CHIP_ID		3
74c17ca3f5SEric Andersson #define BMA150_CHIP_ID_REG	BMA150_DATA_0_REG
75c17ca3f5SEric Andersson 
76c17ca3f5SEric Andersson #define BMA150_ACC_X_LSB_REG	BMA150_DATA_2_REG
77c17ca3f5SEric Andersson 
78c17ca3f5SEric Andersson #define BMA150_SLEEP_POS	0
79c17ca3f5SEric Andersson #define BMA150_SLEEP_MSK	0x01
80c17ca3f5SEric Andersson #define BMA150_SLEEP_REG	BMA150_CTRL_0_REG
81c17ca3f5SEric Andersson 
82c17ca3f5SEric Andersson #define BMA150_BANDWIDTH_POS	0
83c17ca3f5SEric Andersson #define BMA150_BANDWIDTH_MSK	0x07
84c17ca3f5SEric Andersson #define BMA150_BANDWIDTH_REG	BMA150_CTRL_2_REG
85c17ca3f5SEric Andersson 
86c17ca3f5SEric Andersson #define BMA150_RANGE_POS	3
87c17ca3f5SEric Andersson #define BMA150_RANGE_MSK	0x18
88c17ca3f5SEric Andersson #define BMA150_RANGE_REG	BMA150_CTRL_2_REG
89c17ca3f5SEric Andersson 
90c17ca3f5SEric Andersson #define BMA150_WAKE_UP_POS	0
91c17ca3f5SEric Andersson #define BMA150_WAKE_UP_MSK	0x01
92c17ca3f5SEric Andersson #define BMA150_WAKE_UP_REG	BMA150_CTRL_3_REG
93c17ca3f5SEric Andersson 
94c17ca3f5SEric Andersson #define BMA150_SW_RES_POS	1
95c17ca3f5SEric Andersson #define BMA150_SW_RES_MSK	0x02
96c17ca3f5SEric Andersson #define BMA150_SW_RES_REG	BMA150_CTRL_0_REG
97c17ca3f5SEric Andersson 
98c17ca3f5SEric Andersson /* Any-motion interrupt register fields */
99c17ca3f5SEric Andersson #define BMA150_ANY_MOTION_EN_POS	6
100c17ca3f5SEric Andersson #define BMA150_ANY_MOTION_EN_MSK	0x40
101c17ca3f5SEric Andersson #define BMA150_ANY_MOTION_EN_REG	BMA150_CTRL_1_REG
102c17ca3f5SEric Andersson 
103c17ca3f5SEric Andersson #define BMA150_ANY_MOTION_DUR_POS	6
104c17ca3f5SEric Andersson #define BMA150_ANY_MOTION_DUR_MSK	0xC0
105c17ca3f5SEric Andersson #define BMA150_ANY_MOTION_DUR_REG	BMA150_CFG_5_REG
106c17ca3f5SEric Andersson 
107c17ca3f5SEric Andersson #define BMA150_ANY_MOTION_THRES_REG	BMA150_CFG_4_REG
108c17ca3f5SEric Andersson 
109c17ca3f5SEric Andersson /* Advanced interrupt register fields */
110c17ca3f5SEric Andersson #define BMA150_ADV_INT_EN_POS		6
111c17ca3f5SEric Andersson #define BMA150_ADV_INT_EN_MSK		0x40
112c17ca3f5SEric Andersson #define BMA150_ADV_INT_EN_REG		BMA150_CTRL_3_REG
113c17ca3f5SEric Andersson 
114c17ca3f5SEric Andersson /* High-G interrupt register fields */
115c17ca3f5SEric Andersson #define BMA150_HIGH_G_EN_POS		1
116c17ca3f5SEric Andersson #define BMA150_HIGH_G_EN_MSK		0x02
117c17ca3f5SEric Andersson #define BMA150_HIGH_G_EN_REG		BMA150_CTRL_1_REG
118c17ca3f5SEric Andersson 
119c17ca3f5SEric Andersson #define BMA150_HIGH_G_HYST_POS		3
120c17ca3f5SEric Andersson #define BMA150_HIGH_G_HYST_MSK		0x38
121c17ca3f5SEric Andersson #define BMA150_HIGH_G_HYST_REG		BMA150_CFG_5_REG
122c17ca3f5SEric Andersson 
123c17ca3f5SEric Andersson #define BMA150_HIGH_G_DUR_REG		BMA150_CFG_3_REG
124c17ca3f5SEric Andersson #define BMA150_HIGH_G_THRES_REG		BMA150_CFG_2_REG
125c17ca3f5SEric Andersson 
126c17ca3f5SEric Andersson /* Low-G interrupt register fields */
127c17ca3f5SEric Andersson #define BMA150_LOW_G_EN_POS		0
128c17ca3f5SEric Andersson #define BMA150_LOW_G_EN_MSK		0x01
129c17ca3f5SEric Andersson #define BMA150_LOW_G_EN_REG		BMA150_CTRL_1_REG
130c17ca3f5SEric Andersson 
131c17ca3f5SEric Andersson #define BMA150_LOW_G_HYST_POS		0
132c17ca3f5SEric Andersson #define BMA150_LOW_G_HYST_MSK		0x07
133c17ca3f5SEric Andersson #define BMA150_LOW_G_HYST_REG		BMA150_CFG_5_REG
134c17ca3f5SEric Andersson 
135c17ca3f5SEric Andersson #define BMA150_LOW_G_DUR_REG		BMA150_CFG_1_REG
136c17ca3f5SEric Andersson #define BMA150_LOW_G_THRES_REG		BMA150_CFG_0_REG
137c17ca3f5SEric Andersson 
138c17ca3f5SEric Andersson struct bma150_data {
139c17ca3f5SEric Andersson 	struct i2c_client *client;
140c17ca3f5SEric Andersson 	struct input_polled_dev *input_polled;
141c17ca3f5SEric Andersson 	struct input_dev *input;
142c17ca3f5SEric Andersson 	u8 mode;
143c17ca3f5SEric Andersson };
144c17ca3f5SEric Andersson 
145c17ca3f5SEric Andersson /*
146c17ca3f5SEric Andersson  * The settings for the given range, bandwidth and interrupt features
147c17ca3f5SEric Andersson  * are stated and verified by Bosch Sensortec where they are configured
148c17ca3f5SEric Andersson  * to provide a generic sensitivity performance.
149c17ca3f5SEric Andersson  */
1507ed5ff82SJulia Lawall static const struct bma150_cfg default_cfg = {
151c17ca3f5SEric Andersson 	.any_motion_int = 1,
152c17ca3f5SEric Andersson 	.hg_int = 1,
153c17ca3f5SEric Andersson 	.lg_int = 1,
154c17ca3f5SEric Andersson 	.any_motion_dur = 0,
155c17ca3f5SEric Andersson 	.any_motion_thres = 0,
156c17ca3f5SEric Andersson 	.hg_hyst = 0,
157c17ca3f5SEric Andersson 	.hg_dur = 150,
158c17ca3f5SEric Andersson 	.hg_thres = 160,
159c17ca3f5SEric Andersson 	.lg_hyst = 0,
160c17ca3f5SEric Andersson 	.lg_dur = 150,
161c17ca3f5SEric Andersson 	.lg_thres = 20,
162c17ca3f5SEric Andersson 	.range = BMA150_RANGE_2G,
163c17ca3f5SEric Andersson 	.bandwidth = BMA150_BW_50HZ
164c17ca3f5SEric Andersson };
165c17ca3f5SEric Andersson 
166c17ca3f5SEric Andersson static int bma150_write_byte(struct i2c_client *client, u8 reg, u8 val)
167c17ca3f5SEric Andersson {
168c17ca3f5SEric Andersson 	s32 ret;
169c17ca3f5SEric Andersson 
170c17ca3f5SEric Andersson 	/* As per specification, disable irq in between register writes */
171c17ca3f5SEric Andersson 	if (client->irq)
172c17ca3f5SEric Andersson 		disable_irq_nosync(client->irq);
173c17ca3f5SEric Andersson 
174c17ca3f5SEric Andersson 	ret = i2c_smbus_write_byte_data(client, reg, val);
175c17ca3f5SEric Andersson 
176c17ca3f5SEric Andersson 	if (client->irq)
177c17ca3f5SEric Andersson 		enable_irq(client->irq);
178c17ca3f5SEric Andersson 
179c17ca3f5SEric Andersson 	return ret;
180c17ca3f5SEric Andersson }
181c17ca3f5SEric Andersson 
182c17ca3f5SEric Andersson static int bma150_set_reg_bits(struct i2c_client *client,
183c17ca3f5SEric Andersson 					int val, int shift, u8 mask, u8 reg)
184c17ca3f5SEric Andersson {
185c17ca3f5SEric Andersson 	int data;
186c17ca3f5SEric Andersson 
187c17ca3f5SEric Andersson 	data = i2c_smbus_read_byte_data(client, reg);
188c17ca3f5SEric Andersson 	if (data < 0)
189c17ca3f5SEric Andersson 		return data;
190c17ca3f5SEric Andersson 
191c17ca3f5SEric Andersson 	data = (data & ~mask) | ((val << shift) & mask);
192c17ca3f5SEric Andersson 	return bma150_write_byte(client, reg, data);
193c17ca3f5SEric Andersson }
194c17ca3f5SEric Andersson 
195c17ca3f5SEric Andersson static int bma150_set_mode(struct bma150_data *bma150, u8 mode)
196c17ca3f5SEric Andersson {
197c17ca3f5SEric Andersson 	int error;
198c17ca3f5SEric Andersson 
199c17ca3f5SEric Andersson 	error = bma150_set_reg_bits(bma150->client, mode, BMA150_WAKE_UP_POS,
200c17ca3f5SEric Andersson 				BMA150_WAKE_UP_MSK, BMA150_WAKE_UP_REG);
201c17ca3f5SEric Andersson 	if (error)
202c17ca3f5SEric Andersson 		return error;
203c17ca3f5SEric Andersson 
204c17ca3f5SEric Andersson 	error = bma150_set_reg_bits(bma150->client, mode, BMA150_SLEEP_POS,
205c17ca3f5SEric Andersson 				BMA150_SLEEP_MSK, BMA150_SLEEP_REG);
206c17ca3f5SEric Andersson 	if (error)
207c17ca3f5SEric Andersson 		return error;
208c17ca3f5SEric Andersson 
209c17ca3f5SEric Andersson 	if (mode == BMA150_MODE_NORMAL)
210f63bb4f4SAniroop Mathur 		usleep_range(2000, 2100);
211c17ca3f5SEric Andersson 
212c17ca3f5SEric Andersson 	bma150->mode = mode;
213c17ca3f5SEric Andersson 	return 0;
214c17ca3f5SEric Andersson }
215c17ca3f5SEric Andersson 
2165298cc4cSBill Pemberton static int bma150_soft_reset(struct bma150_data *bma150)
217c17ca3f5SEric Andersson {
218c17ca3f5SEric Andersson 	int error;
219c17ca3f5SEric Andersson 
220c17ca3f5SEric Andersson 	error = bma150_set_reg_bits(bma150->client, 1, BMA150_SW_RES_POS,
221c17ca3f5SEric Andersson 				BMA150_SW_RES_MSK, BMA150_SW_RES_REG);
222c17ca3f5SEric Andersson 	if (error)
223c17ca3f5SEric Andersson 		return error;
224c17ca3f5SEric Andersson 
225f63bb4f4SAniroop Mathur 	usleep_range(2000, 2100);
226c17ca3f5SEric Andersson 	return 0;
227c17ca3f5SEric Andersson }
228c17ca3f5SEric Andersson 
2295298cc4cSBill Pemberton static int bma150_set_range(struct bma150_data *bma150, u8 range)
230c17ca3f5SEric Andersson {
231c17ca3f5SEric Andersson 	return bma150_set_reg_bits(bma150->client, range, BMA150_RANGE_POS,
232c17ca3f5SEric Andersson 				BMA150_RANGE_MSK, BMA150_RANGE_REG);
233c17ca3f5SEric Andersson }
234c17ca3f5SEric Andersson 
2355298cc4cSBill Pemberton static int bma150_set_bandwidth(struct bma150_data *bma150, u8 bw)
236c17ca3f5SEric Andersson {
237c17ca3f5SEric Andersson 	return bma150_set_reg_bits(bma150->client, bw, BMA150_BANDWIDTH_POS,
238c17ca3f5SEric Andersson 				BMA150_BANDWIDTH_MSK, BMA150_BANDWIDTH_REG);
239c17ca3f5SEric Andersson }
240c17ca3f5SEric Andersson 
2415298cc4cSBill Pemberton static int bma150_set_low_g_interrupt(struct bma150_data *bma150,
242c17ca3f5SEric Andersson 					u8 enable, u8 hyst, u8 dur, u8 thres)
243c17ca3f5SEric Andersson {
244c17ca3f5SEric Andersson 	int error;
245c17ca3f5SEric Andersson 
246c17ca3f5SEric Andersson 	error = bma150_set_reg_bits(bma150->client, hyst,
247c17ca3f5SEric Andersson 				BMA150_LOW_G_HYST_POS, BMA150_LOW_G_HYST_MSK,
248c17ca3f5SEric Andersson 				BMA150_LOW_G_HYST_REG);
249c17ca3f5SEric Andersson 	if (error)
250c17ca3f5SEric Andersson 		return error;
251c17ca3f5SEric Andersson 
252c17ca3f5SEric Andersson 	error = bma150_write_byte(bma150->client, BMA150_LOW_G_DUR_REG, dur);
253c17ca3f5SEric Andersson 	if (error)
254c17ca3f5SEric Andersson 		return error;
255c17ca3f5SEric Andersson 
256c17ca3f5SEric Andersson 	error = bma150_write_byte(bma150->client, BMA150_LOW_G_THRES_REG, thres);
257c17ca3f5SEric Andersson 	if (error)
258c17ca3f5SEric Andersson 		return error;
259c17ca3f5SEric Andersson 
260c17ca3f5SEric Andersson 	return bma150_set_reg_bits(bma150->client, !!enable,
261c17ca3f5SEric Andersson 				BMA150_LOW_G_EN_POS, BMA150_LOW_G_EN_MSK,
262c17ca3f5SEric Andersson 				BMA150_LOW_G_EN_REG);
263c17ca3f5SEric Andersson }
264c17ca3f5SEric Andersson 
2655298cc4cSBill Pemberton static int bma150_set_high_g_interrupt(struct bma150_data *bma150,
266c17ca3f5SEric Andersson 					u8 enable, u8 hyst, u8 dur, u8 thres)
267c17ca3f5SEric Andersson {
268c17ca3f5SEric Andersson 	int error;
269c17ca3f5SEric Andersson 
270c17ca3f5SEric Andersson 	error = bma150_set_reg_bits(bma150->client, hyst,
271c17ca3f5SEric Andersson 				BMA150_HIGH_G_HYST_POS, BMA150_HIGH_G_HYST_MSK,
272c17ca3f5SEric Andersson 				BMA150_HIGH_G_HYST_REG);
273c17ca3f5SEric Andersson 	if (error)
274c17ca3f5SEric Andersson 		return error;
275c17ca3f5SEric Andersson 
276c17ca3f5SEric Andersson 	error = bma150_write_byte(bma150->client,
277c17ca3f5SEric Andersson 				BMA150_HIGH_G_DUR_REG, dur);
278c17ca3f5SEric Andersson 	if (error)
279c17ca3f5SEric Andersson 		return error;
280c17ca3f5SEric Andersson 
281c17ca3f5SEric Andersson 	error = bma150_write_byte(bma150->client,
282c17ca3f5SEric Andersson 				BMA150_HIGH_G_THRES_REG, thres);
283c17ca3f5SEric Andersson 	if (error)
284c17ca3f5SEric Andersson 		return error;
285c17ca3f5SEric Andersson 
286c17ca3f5SEric Andersson 	return bma150_set_reg_bits(bma150->client, !!enable,
287c17ca3f5SEric Andersson 				BMA150_HIGH_G_EN_POS, BMA150_HIGH_G_EN_MSK,
288c17ca3f5SEric Andersson 				BMA150_HIGH_G_EN_REG);
289c17ca3f5SEric Andersson }
290c17ca3f5SEric Andersson 
291c17ca3f5SEric Andersson 
2925298cc4cSBill Pemberton static int bma150_set_any_motion_interrupt(struct bma150_data *bma150,
293c17ca3f5SEric Andersson 						u8 enable, u8 dur, u8 thres)
294c17ca3f5SEric Andersson {
295c17ca3f5SEric Andersson 	int error;
296c17ca3f5SEric Andersson 
297c17ca3f5SEric Andersson 	error = bma150_set_reg_bits(bma150->client, dur,
298c17ca3f5SEric Andersson 				BMA150_ANY_MOTION_DUR_POS,
299c17ca3f5SEric Andersson 				BMA150_ANY_MOTION_DUR_MSK,
300c17ca3f5SEric Andersson 				BMA150_ANY_MOTION_DUR_REG);
301c17ca3f5SEric Andersson 	if (error)
302c17ca3f5SEric Andersson 		return error;
303c17ca3f5SEric Andersson 
304c17ca3f5SEric Andersson 	error = bma150_write_byte(bma150->client,
305c17ca3f5SEric Andersson 				BMA150_ANY_MOTION_THRES_REG, thres);
306c17ca3f5SEric Andersson 	if (error)
307c17ca3f5SEric Andersson 		return error;
308c17ca3f5SEric Andersson 
309c17ca3f5SEric Andersson 	error = bma150_set_reg_bits(bma150->client, !!enable,
310c17ca3f5SEric Andersson 				BMA150_ADV_INT_EN_POS, BMA150_ADV_INT_EN_MSK,
311c17ca3f5SEric Andersson 				BMA150_ADV_INT_EN_REG);
312c17ca3f5SEric Andersson 	if (error)
313c17ca3f5SEric Andersson 		return error;
314c17ca3f5SEric Andersson 
315c17ca3f5SEric Andersson 	return bma150_set_reg_bits(bma150->client, !!enable,
316c17ca3f5SEric Andersson 				BMA150_ANY_MOTION_EN_POS,
317c17ca3f5SEric Andersson 				BMA150_ANY_MOTION_EN_MSK,
318c17ca3f5SEric Andersson 				BMA150_ANY_MOTION_EN_REG);
319c17ca3f5SEric Andersson }
320c17ca3f5SEric Andersson 
321c17ca3f5SEric Andersson static void bma150_report_xyz(struct bma150_data *bma150)
322c17ca3f5SEric Andersson {
323c17ca3f5SEric Andersson 	u8 data[BMA150_XYZ_DATA_SIZE];
324c17ca3f5SEric Andersson 	s16 x, y, z;
325c17ca3f5SEric Andersson 	s32 ret;
326c17ca3f5SEric Andersson 
327c17ca3f5SEric Andersson 	ret = i2c_smbus_read_i2c_block_data(bma150->client,
328c17ca3f5SEric Andersson 			BMA150_ACC_X_LSB_REG, BMA150_XYZ_DATA_SIZE, data);
329c17ca3f5SEric Andersson 	if (ret != BMA150_XYZ_DATA_SIZE)
330c17ca3f5SEric Andersson 		return;
331c17ca3f5SEric Andersson 
332c17ca3f5SEric Andersson 	x = ((0xc0 & data[0]) >> 6) | (data[1] << 2);
333c17ca3f5SEric Andersson 	y = ((0xc0 & data[2]) >> 6) | (data[3] << 2);
334c17ca3f5SEric Andersson 	z = ((0xc0 & data[4]) >> 6) | (data[5] << 2);
335c17ca3f5SEric Andersson 
336b7e79329SMartin Kepplinger 	x = sign_extend32(x, 9);
337b7e79329SMartin Kepplinger 	y = sign_extend32(y, 9);
338b7e79329SMartin Kepplinger 	z = sign_extend32(z, 9);
339c17ca3f5SEric Andersson 
340c17ca3f5SEric Andersson 	input_report_abs(bma150->input, ABS_X, x);
341c17ca3f5SEric Andersson 	input_report_abs(bma150->input, ABS_Y, y);
342c17ca3f5SEric Andersson 	input_report_abs(bma150->input, ABS_Z, z);
343c17ca3f5SEric Andersson 	input_sync(bma150->input);
344c17ca3f5SEric Andersson }
345c17ca3f5SEric Andersson 
346c17ca3f5SEric Andersson static irqreturn_t bma150_irq_thread(int irq, void *dev)
347c17ca3f5SEric Andersson {
348c17ca3f5SEric Andersson 	bma150_report_xyz(dev);
349c17ca3f5SEric Andersson 
350c17ca3f5SEric Andersson 	return IRQ_HANDLED;
351c17ca3f5SEric Andersson }
352c17ca3f5SEric Andersson 
353c17ca3f5SEric Andersson static void bma150_poll(struct input_polled_dev *dev)
354c17ca3f5SEric Andersson {
355c17ca3f5SEric Andersson 	bma150_report_xyz(dev->private);
356c17ca3f5SEric Andersson }
357c17ca3f5SEric Andersson 
358c17ca3f5SEric Andersson static int bma150_open(struct bma150_data *bma150)
359c17ca3f5SEric Andersson {
360c17ca3f5SEric Andersson 	int error;
361c17ca3f5SEric Andersson 
362c17ca3f5SEric Andersson 	error = pm_runtime_get_sync(&bma150->client->dev);
36379f34d19SMichael Trimarchi 	if (error < 0 && error != -ENOSYS)
364c17ca3f5SEric Andersson 		return error;
365c17ca3f5SEric Andersson 
366c17ca3f5SEric Andersson 	/*
367c17ca3f5SEric Andersson 	 * See if runtime PM woke up the device. If runtime PM
368c17ca3f5SEric Andersson 	 * is disabled we need to do it ourselves.
369c17ca3f5SEric Andersson 	 */
370c17ca3f5SEric Andersson 	if (bma150->mode != BMA150_MODE_NORMAL) {
371c17ca3f5SEric Andersson 		error = bma150_set_mode(bma150, BMA150_MODE_NORMAL);
372c17ca3f5SEric Andersson 		if (error)
373c17ca3f5SEric Andersson 			return error;
374c17ca3f5SEric Andersson 	}
375c17ca3f5SEric Andersson 
376c17ca3f5SEric Andersson 	return 0;
377c17ca3f5SEric Andersson }
378c17ca3f5SEric Andersson 
379c17ca3f5SEric Andersson static void bma150_close(struct bma150_data *bma150)
380c17ca3f5SEric Andersson {
381c17ca3f5SEric Andersson 	pm_runtime_put_sync(&bma150->client->dev);
382c17ca3f5SEric Andersson 
383c17ca3f5SEric Andersson 	if (bma150->mode != BMA150_MODE_SLEEP)
384c17ca3f5SEric Andersson 		bma150_set_mode(bma150, BMA150_MODE_SLEEP);
385c17ca3f5SEric Andersson }
386c17ca3f5SEric Andersson 
387c17ca3f5SEric Andersson static int bma150_irq_open(struct input_dev *input)
388c17ca3f5SEric Andersson {
389c17ca3f5SEric Andersson 	struct bma150_data *bma150 = input_get_drvdata(input);
390c17ca3f5SEric Andersson 
391c17ca3f5SEric Andersson 	return bma150_open(bma150);
392c17ca3f5SEric Andersson }
393c17ca3f5SEric Andersson 
394c17ca3f5SEric Andersson static void bma150_irq_close(struct input_dev *input)
395c17ca3f5SEric Andersson {
396c17ca3f5SEric Andersson 	struct bma150_data *bma150 = input_get_drvdata(input);
397c17ca3f5SEric Andersson 
398c17ca3f5SEric Andersson 	bma150_close(bma150);
399c17ca3f5SEric Andersson }
400c17ca3f5SEric Andersson 
401c17ca3f5SEric Andersson static void bma150_poll_open(struct input_polled_dev *ipoll_dev)
402c17ca3f5SEric Andersson {
403c17ca3f5SEric Andersson 	struct bma150_data *bma150 = ipoll_dev->private;
404c17ca3f5SEric Andersson 
405c17ca3f5SEric Andersson 	bma150_open(bma150);
406c17ca3f5SEric Andersson }
407c17ca3f5SEric Andersson 
408c17ca3f5SEric Andersson static void bma150_poll_close(struct input_polled_dev *ipoll_dev)
409c17ca3f5SEric Andersson {
410c17ca3f5SEric Andersson 	struct bma150_data *bma150 = ipoll_dev->private;
411c17ca3f5SEric Andersson 
412c17ca3f5SEric Andersson 	bma150_close(bma150);
413c17ca3f5SEric Andersson }
414c17ca3f5SEric Andersson 
4155298cc4cSBill Pemberton static int bma150_initialize(struct bma150_data *bma150,
416c17ca3f5SEric Andersson 				       const struct bma150_cfg *cfg)
417c17ca3f5SEric Andersson {
418c17ca3f5SEric Andersson 	int error;
419c17ca3f5SEric Andersson 
420c17ca3f5SEric Andersson 	error = bma150_soft_reset(bma150);
421c17ca3f5SEric Andersson 	if (error)
422c17ca3f5SEric Andersson 		return error;
423c17ca3f5SEric Andersson 
424c17ca3f5SEric Andersson 	error = bma150_set_bandwidth(bma150, cfg->bandwidth);
425c17ca3f5SEric Andersson 	if (error)
426c17ca3f5SEric Andersson 		return error;
427c17ca3f5SEric Andersson 
428c17ca3f5SEric Andersson 	error = bma150_set_range(bma150, cfg->range);
429c17ca3f5SEric Andersson 	if (error)
430c17ca3f5SEric Andersson 		return error;
431c17ca3f5SEric Andersson 
432c17ca3f5SEric Andersson 	if (bma150->client->irq) {
433c17ca3f5SEric Andersson 		error = bma150_set_any_motion_interrupt(bma150,
434c17ca3f5SEric Andersson 					cfg->any_motion_int,
435c17ca3f5SEric Andersson 					cfg->any_motion_dur,
436c17ca3f5SEric Andersson 					cfg->any_motion_thres);
437c17ca3f5SEric Andersson 		if (error)
438c17ca3f5SEric Andersson 			return error;
439c17ca3f5SEric Andersson 
440c17ca3f5SEric Andersson 		error = bma150_set_high_g_interrupt(bma150,
441c17ca3f5SEric Andersson 					cfg->hg_int, cfg->hg_hyst,
442c17ca3f5SEric Andersson 					cfg->hg_dur, cfg->hg_thres);
443c17ca3f5SEric Andersson 		if (error)
444c17ca3f5SEric Andersson 			return error;
445c17ca3f5SEric Andersson 
446c17ca3f5SEric Andersson 		error = bma150_set_low_g_interrupt(bma150,
447c17ca3f5SEric Andersson 					cfg->lg_int, cfg->lg_hyst,
448c17ca3f5SEric Andersson 					cfg->lg_dur, cfg->lg_thres);
449c17ca3f5SEric Andersson 		if (error)
450c17ca3f5SEric Andersson 			return error;
451c17ca3f5SEric Andersson 	}
452c17ca3f5SEric Andersson 
453c17ca3f5SEric Andersson 	return bma150_set_mode(bma150, BMA150_MODE_SLEEP);
454c17ca3f5SEric Andersson }
455c17ca3f5SEric Andersson 
4565298cc4cSBill Pemberton static void bma150_init_input_device(struct bma150_data *bma150,
457c17ca3f5SEric Andersson 						struct input_dev *idev)
458c17ca3f5SEric Andersson {
459c17ca3f5SEric Andersson 	idev->name = BMA150_DRIVER;
460c17ca3f5SEric Andersson 	idev->phys = BMA150_DRIVER "/input0";
461c17ca3f5SEric Andersson 	idev->id.bustype = BUS_I2C;
462c17ca3f5SEric Andersson 	idev->dev.parent = &bma150->client->dev;
463c17ca3f5SEric Andersson 
464c17ca3f5SEric Andersson 	idev->evbit[0] = BIT_MASK(EV_ABS);
465c17ca3f5SEric Andersson 	input_set_abs_params(idev, ABS_X, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
466c17ca3f5SEric Andersson 	input_set_abs_params(idev, ABS_Y, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
467c17ca3f5SEric Andersson 	input_set_abs_params(idev, ABS_Z, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
468c17ca3f5SEric Andersson }
469c17ca3f5SEric Andersson 
4705298cc4cSBill Pemberton static int bma150_register_input_device(struct bma150_data *bma150)
471c17ca3f5SEric Andersson {
472c17ca3f5SEric Andersson 	struct input_dev *idev;
473c17ca3f5SEric Andersson 	int error;
474c17ca3f5SEric Andersson 
475c17ca3f5SEric Andersson 	idev = input_allocate_device();
476c17ca3f5SEric Andersson 	if (!idev)
477c17ca3f5SEric Andersson 		return -ENOMEM;
478c17ca3f5SEric Andersson 
479c17ca3f5SEric Andersson 	bma150_init_input_device(bma150, idev);
480c17ca3f5SEric Andersson 
481c17ca3f5SEric Andersson 	idev->open = bma150_irq_open;
482c17ca3f5SEric Andersson 	idev->close = bma150_irq_close;
483c17ca3f5SEric Andersson 	input_set_drvdata(idev, bma150);
484c17ca3f5SEric Andersson 
485c17ca3f5SEric Andersson 	error = input_register_device(idev);
486c17ca3f5SEric Andersson 	if (error) {
487c17ca3f5SEric Andersson 		input_free_device(idev);
488c17ca3f5SEric Andersson 		return error;
489c17ca3f5SEric Andersson 	}
490c17ca3f5SEric Andersson 
491c17ca3f5SEric Andersson 	bma150->input = idev;
492c17ca3f5SEric Andersson 	return 0;
493c17ca3f5SEric Andersson }
494c17ca3f5SEric Andersson 
4955298cc4cSBill Pemberton static int bma150_register_polled_device(struct bma150_data *bma150)
496c17ca3f5SEric Andersson {
497c17ca3f5SEric Andersson 	struct input_polled_dev *ipoll_dev;
498c17ca3f5SEric Andersson 	int error;
499c17ca3f5SEric Andersson 
500c17ca3f5SEric Andersson 	ipoll_dev = input_allocate_polled_device();
501c17ca3f5SEric Andersson 	if (!ipoll_dev)
502c17ca3f5SEric Andersson 		return -ENOMEM;
503c17ca3f5SEric Andersson 
504c17ca3f5SEric Andersson 	ipoll_dev->private = bma150;
505c17ca3f5SEric Andersson 	ipoll_dev->open = bma150_poll_open;
506c17ca3f5SEric Andersson 	ipoll_dev->close = bma150_poll_close;
507c17ca3f5SEric Andersson 	ipoll_dev->poll = bma150_poll;
508c17ca3f5SEric Andersson 	ipoll_dev->poll_interval = BMA150_POLL_INTERVAL;
509c17ca3f5SEric Andersson 	ipoll_dev->poll_interval_min = BMA150_POLL_MIN;
510c17ca3f5SEric Andersson 	ipoll_dev->poll_interval_max = BMA150_POLL_MAX;
511c17ca3f5SEric Andersson 
512c17ca3f5SEric Andersson 	bma150_init_input_device(bma150, ipoll_dev->input);
513c17ca3f5SEric Andersson 
514c17ca3f5SEric Andersson 	error = input_register_polled_device(ipoll_dev);
515c17ca3f5SEric Andersson 	if (error) {
516c17ca3f5SEric Andersson 		input_free_polled_device(ipoll_dev);
517c17ca3f5SEric Andersson 		return error;
518c17ca3f5SEric Andersson 	}
519c17ca3f5SEric Andersson 
520c17ca3f5SEric Andersson 	bma150->input_polled = ipoll_dev;
521c17ca3f5SEric Andersson 	bma150->input = ipoll_dev->input;
522c17ca3f5SEric Andersson 
523c17ca3f5SEric Andersson 	return 0;
524c17ca3f5SEric Andersson }
525c17ca3f5SEric Andersson 
5265298cc4cSBill Pemberton static int bma150_probe(struct i2c_client *client,
527c17ca3f5SEric Andersson 				  const struct i2c_device_id *id)
528c17ca3f5SEric Andersson {
529c838cb3dSJingoo Han 	const struct bma150_platform_data *pdata =
530c838cb3dSJingoo Han 			dev_get_platdata(&client->dev);
531c17ca3f5SEric Andersson 	const struct bma150_cfg *cfg;
532c17ca3f5SEric Andersson 	struct bma150_data *bma150;
533c17ca3f5SEric Andersson 	int chip_id;
534c17ca3f5SEric Andersson 	int error;
535c17ca3f5SEric Andersson 
536c17ca3f5SEric Andersson 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
537c17ca3f5SEric Andersson 		dev_err(&client->dev, "i2c_check_functionality error\n");
538c17ca3f5SEric Andersson 		return -EIO;
539c17ca3f5SEric Andersson 	}
540c17ca3f5SEric Andersson 
541baf28d91SHans de Goede 	/*
542baf28d91SHans de Goede 	 * Note if the IIO CONFIG_BMA180 driver is enabled we want to fail
543baf28d91SHans de Goede 	 * the probe for the bma180 as the iio driver is preferred.
544baf28d91SHans de Goede 	 */
545c17ca3f5SEric Andersson 	chip_id = i2c_smbus_read_byte_data(client, BMA150_CHIP_ID_REG);
546baf28d91SHans de Goede 	if (chip_id != BMA150_CHIP_ID &&
547baf28d91SHans de Goede 	    (IS_ENABLED(CONFIG_BMA180) || chip_id != BMA180_CHIP_ID)) {
548c17ca3f5SEric Andersson 		dev_err(&client->dev, "BMA150 chip id error: %d\n", chip_id);
549c17ca3f5SEric Andersson 		return -EINVAL;
550c17ca3f5SEric Andersson 	}
551c17ca3f5SEric Andersson 
552c17ca3f5SEric Andersson 	bma150 = kzalloc(sizeof(struct bma150_data), GFP_KERNEL);
553c17ca3f5SEric Andersson 	if (!bma150)
554c17ca3f5SEric Andersson 		return -ENOMEM;
555c17ca3f5SEric Andersson 
556c17ca3f5SEric Andersson 	bma150->client = client;
557c17ca3f5SEric Andersson 
558c17ca3f5SEric Andersson 	if (pdata) {
559c17ca3f5SEric Andersson 		if (pdata->irq_gpio_cfg) {
560c17ca3f5SEric Andersson 			error = pdata->irq_gpio_cfg();
561c17ca3f5SEric Andersson 			if (error) {
562c17ca3f5SEric Andersson 				dev_err(&client->dev,
563c17ca3f5SEric Andersson 					"IRQ GPIO conf. error %d, error %d\n",
564c17ca3f5SEric Andersson 					client->irq, error);
565c17ca3f5SEric Andersson 				goto err_free_mem;
566c17ca3f5SEric Andersson 			}
567c17ca3f5SEric Andersson 		}
568c17ca3f5SEric Andersson 		cfg = &pdata->cfg;
569c17ca3f5SEric Andersson 	} else {
570c17ca3f5SEric Andersson 		cfg = &default_cfg;
571c17ca3f5SEric Andersson 	}
572c17ca3f5SEric Andersson 
573c17ca3f5SEric Andersson 	error = bma150_initialize(bma150, cfg);
574c17ca3f5SEric Andersson 	if (error)
575c17ca3f5SEric Andersson 		goto err_free_mem;
576c17ca3f5SEric Andersson 
577c17ca3f5SEric Andersson 	if (client->irq > 0) {
578c17ca3f5SEric Andersson 		error = bma150_register_input_device(bma150);
579c17ca3f5SEric Andersson 		if (error)
580c17ca3f5SEric Andersson 			goto err_free_mem;
581c17ca3f5SEric Andersson 
582c17ca3f5SEric Andersson 		error = request_threaded_irq(client->irq,
583c17ca3f5SEric Andersson 					NULL, bma150_irq_thread,
584c17ca3f5SEric Andersson 					IRQF_TRIGGER_RISING | IRQF_ONESHOT,
585c17ca3f5SEric Andersson 					BMA150_DRIVER, bma150);
586c17ca3f5SEric Andersson 		if (error) {
587c17ca3f5SEric Andersson 			dev_err(&client->dev,
588c17ca3f5SEric Andersson 				"irq request failed %d, error %d\n",
589c17ca3f5SEric Andersson 				client->irq, error);
590c17ca3f5SEric Andersson 			input_unregister_device(bma150->input);
591c17ca3f5SEric Andersson 			goto err_free_mem;
592c17ca3f5SEric Andersson 		}
593c17ca3f5SEric Andersson 	} else {
594c17ca3f5SEric Andersson 		error = bma150_register_polled_device(bma150);
595c17ca3f5SEric Andersson 		if (error)
596c17ca3f5SEric Andersson 			goto err_free_mem;
597c17ca3f5SEric Andersson 	}
598c17ca3f5SEric Andersson 
599c17ca3f5SEric Andersson 	i2c_set_clientdata(client, bma150);
600c17ca3f5SEric Andersson 
601c17ca3f5SEric Andersson 	pm_runtime_enable(&client->dev);
602c17ca3f5SEric Andersson 
603c17ca3f5SEric Andersson 	return 0;
604c17ca3f5SEric Andersson 
605c17ca3f5SEric Andersson err_free_mem:
606c17ca3f5SEric Andersson 	kfree(bma150);
607c17ca3f5SEric Andersson 	return error;
608c17ca3f5SEric Andersson }
609c17ca3f5SEric Andersson 
610e2619cf7SBill Pemberton static int bma150_remove(struct i2c_client *client)
611c17ca3f5SEric Andersson {
612c17ca3f5SEric Andersson 	struct bma150_data *bma150 = i2c_get_clientdata(client);
613c17ca3f5SEric Andersson 
614c17ca3f5SEric Andersson 	pm_runtime_disable(&client->dev);
615c17ca3f5SEric Andersson 
616c17ca3f5SEric Andersson 	if (client->irq > 0) {
617c17ca3f5SEric Andersson 		free_irq(client->irq, bma150);
618c17ca3f5SEric Andersson 		input_unregister_device(bma150->input);
619c17ca3f5SEric Andersson 	} else {
620c17ca3f5SEric Andersson 		input_unregister_polled_device(bma150->input_polled);
621c17ca3f5SEric Andersson 		input_free_polled_device(bma150->input_polled);
622c17ca3f5SEric Andersson 	}
623c17ca3f5SEric Andersson 
624c17ca3f5SEric Andersson 	kfree(bma150);
625c17ca3f5SEric Andersson 
626c17ca3f5SEric Andersson 	return 0;
627c17ca3f5SEric Andersson }
628c17ca3f5SEric Andersson 
629c17ca3f5SEric Andersson #ifdef CONFIG_PM
630c17ca3f5SEric Andersson static int bma150_suspend(struct device *dev)
631c17ca3f5SEric Andersson {
632c17ca3f5SEric Andersson 	struct i2c_client *client = to_i2c_client(dev);
633c17ca3f5SEric Andersson 	struct bma150_data *bma150 = i2c_get_clientdata(client);
634c17ca3f5SEric Andersson 
635c17ca3f5SEric Andersson 	return bma150_set_mode(bma150, BMA150_MODE_SLEEP);
636c17ca3f5SEric Andersson }
637c17ca3f5SEric Andersson 
638c17ca3f5SEric Andersson static int bma150_resume(struct device *dev)
639c17ca3f5SEric Andersson {
640c17ca3f5SEric Andersson 	struct i2c_client *client = to_i2c_client(dev);
641c17ca3f5SEric Andersson 	struct bma150_data *bma150 = i2c_get_clientdata(client);
642c17ca3f5SEric Andersson 
643c17ca3f5SEric Andersson 	return bma150_set_mode(bma150, BMA150_MODE_NORMAL);
644c17ca3f5SEric Andersson }
645c17ca3f5SEric Andersson #endif
646c17ca3f5SEric Andersson 
647c17ca3f5SEric Andersson static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL);
648c17ca3f5SEric Andersson 
649c17ca3f5SEric Andersson static const struct i2c_device_id bma150_id[] = {
650c17ca3f5SEric Andersson 	{ "bma150", 0 },
651baf28d91SHans de Goede #if !IS_ENABLED(CONFIG_BMA180)
652ef3714fdSDr. H. Nikolaus Schaller 	{ "bma180", 0 },
653baf28d91SHans de Goede #endif
654c17ca3f5SEric Andersson 	{ "smb380", 0 },
655c17ca3f5SEric Andersson 	{ "bma023", 0 },
656c17ca3f5SEric Andersson 	{ }
657c17ca3f5SEric Andersson };
658c17ca3f5SEric Andersson 
659c17ca3f5SEric Andersson MODULE_DEVICE_TABLE(i2c, bma150_id);
660c17ca3f5SEric Andersson 
661c17ca3f5SEric Andersson static struct i2c_driver bma150_driver = {
662c17ca3f5SEric Andersson 	.driver = {
663c17ca3f5SEric Andersson 		.name	= BMA150_DRIVER,
664c17ca3f5SEric Andersson 		.pm	= &bma150_pm,
665c17ca3f5SEric Andersson 	},
666c17ca3f5SEric Andersson 	.class		= I2C_CLASS_HWMON,
667c17ca3f5SEric Andersson 	.id_table	= bma150_id,
668c17ca3f5SEric Andersson 	.probe		= bma150_probe,
6691cb0aa88SBill Pemberton 	.remove		= bma150_remove,
670c17ca3f5SEric Andersson };
671c17ca3f5SEric Andersson 
6721b92c1cfSAxel Lin module_i2c_driver(bma150_driver);
673c17ca3f5SEric Andersson 
674c17ca3f5SEric Andersson MODULE_AUTHOR("Albert Zhang <xu.zhang@bosch-sensortec.com>");
675c17ca3f5SEric Andersson MODULE_DESCRIPTION("BMA150 driver");
676c17ca3f5SEric Andersson MODULE_LICENSE("GPL");
677