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