2 * Copyright (C) 2012 Invensense, Inc.
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
17 * @brief Hardware drivers.
20 * @file inv_slave_bma250.c
21 * @brief A sysfs device driver for Invensense devices
22 * @details This file is part of invensense mpu driver code
26 #include <linux/module.h>
27 #include <linux/init.h>
28 #include <linux/slab.h>
29 #include <linux/i2c.h>
30 #include <linux/err.h>
31 #include <linux/delay.h>
32 #include <linux/sysfs.h>
33 #include <linux/jiffies.h>
34 #include <linux/irq.h>
35 #include <linux/interrupt.h>
36 #include <linux/kfifo.h>
37 #include <linux/poll.h>
38 #include <linux/miscdevice.h>
39 #include <linux/spinlock.h>
41 #include "inv_mpu_iio.h"
42 #define BMA250_CHIP_ID 3
43 #define BMA250_RANGE_SET 0
44 #define BMA250_BW_SET 4
46 /* range and bandwidth */
47 #define BMA250_RANGE_2G 3
48 #define BMA250_RANGE_4G 5
49 #define BMA250_RANGE_8G 8
50 #define BMA250_RANGE_16G 12
51 #define BMA250_RANGE_MAX 4
52 #define BMA250_RANGE_MASK 0xF0
54 #define BMA250_BW_7_81HZ 0x08
55 #define BMA250_BW_15_63HZ 0x09
56 #define BMA250_BW_31_25HZ 0x0A
57 #define BMA250_BW_62_50HZ 0x0B
58 #define BMA250_BW_125HZ 0x0C
59 #define BMA250_BW_250HZ 0x0D
60 #define BMA250_BW_500HZ 0x0E
61 #define BMA250_BW_1000HZ 0x0F
62 #define BMA250_MAX_BW_SIZE 8
63 #define BMA250_BW_REG_MASK 0xE0
65 /* register definitions */
66 #define BMA250_X_AXIS_LSB_REG 0x02
67 #define BMA250_RANGE_SEL_REG 0x0F
68 #define BMA250_BW_SEL_REG 0x10
69 #define BMA250_MODE_CTRL_REG 0x11
72 #define BMA250_MODE_NORMAL 0
73 #define BMA250_MODE_LOWPOWER 1
74 #define BMA250_MODE_SUSPEND 2
75 #define BMA250_MODE_MAX 3
76 #define BMA250_MODE_MASK 0x3F
77 #define BMA250_BIT_SUSPEND 0x80
78 #define BMA250_BIT_LP 0x40
86 static struct bma_property bma_static_property = {
87 .range = BMA250_RANGE_SET,
88 .bandwidth = BMA250_BW_SET,
89 .mode = BMA250_MODE_SUSPEND
92 static int bma250_set_bandwidth(struct inv_mpu_iio_s *st, u8 bw)
99 bandwidth = BMA250_BW_7_81HZ;
102 bandwidth = BMA250_BW_15_63HZ;
105 bandwidth = BMA250_BW_31_25HZ;
108 bandwidth = BMA250_BW_62_50HZ;
111 bandwidth = BMA250_BW_125HZ;
114 bandwidth = BMA250_BW_250HZ;
117 bandwidth = BMA250_BW_500HZ;
120 bandwidth = BMA250_BW_1000HZ;
125 res = inv_secondary_read(BMA250_BW_SEL_REG, 1, &data);
128 data &= BMA250_BW_REG_MASK;
130 res = inv_secondary_write(st, BMA250_BW_SEL_REG, data);
134 static int bma250_set_range(struct inv_mpu_iio_s *st, u8 range)
140 data = BMA250_RANGE_2G;
143 data = BMA250_RANGE_4G;
146 data = BMA250_RANGE_8G;
149 data = BMA250_RANGE_16G;
154 res = inv_secondary_read(BMA250_RANGE_SEL_REG, 1, &orig);
157 orig &= BMA250_RANGE_MASK;
159 res = inv_secondary_write(st, BMA250_RANGE_SEL_REG, data);
162 bma_static_property.range = range;
167 static int setup_slave_bma250(struct inv_mpu_iio_s *st)
171 result = set_3050_bypass(st, true);
174 /*read secondary i2c ID register */
175 result = inv_secondary_read(0, 1, data);
178 if (BMA250_CHIP_ID != data[0])
180 result = set_3050_bypass(st, false);
183 /*AUX(accel), slave address is set inside set_3050_bypass*/
184 /* bma250 x axis LSB register address is 2 */
185 result = inv_plat_single_write(st, REG_3050_AUX_BST_ADDR,
186 BMA250_X_AXIS_LSB_REG);
191 static int bma250_set_mode(struct inv_mpu_iio_s *st, u8 mode)
196 res = inv_secondary_read(BMA250_MODE_CTRL_REG, 1, &data);
199 data &= BMA250_MODE_MASK;
201 case BMA250_MODE_NORMAL:
203 case BMA250_MODE_LOWPOWER:
204 data |= BMA250_BIT_LP;
206 case BMA250_MODE_SUSPEND:
207 data |= BMA250_BIT_SUSPEND;
212 res = inv_secondary_write(st, BMA250_MODE_CTRL_REG, data);
215 bma_static_property.mode = mode;
220 static int suspend_slave_bma250(struct inv_mpu_iio_s *st)
223 if (bma_static_property.mode == BMA250_MODE_SUSPEND)
225 /*set to bypass mode */
226 result = set_3050_bypass(st, true);
229 bma250_set_mode(st, BMA250_MODE_SUSPEND);
230 /* no need to recover to non-bypass mode because we need it now */
235 static int resume_slave_bma250(struct inv_mpu_iio_s *st)
238 if (bma_static_property.mode == BMA250_MODE_NORMAL)
240 /*set to bypass mode */
241 result = set_3050_bypass(st, true);
244 result = bma250_set_mode(st, BMA250_MODE_NORMAL);
245 /* recover bypass mode */
246 result |= set_3050_bypass(st, false);
248 return result ? (-EINVAL) : 0;
251 static int combine_data_slave_bma250(u8 *in, short *out)
253 out[0] = le16_to_cpup((__le16 *)(&in[0]));
254 out[1] = le16_to_cpup((__le16 *)(&in[2]));
255 out[2] = le16_to_cpup((__le16 *)(&in[4]));
260 static int get_mode_slave_bma250(void)
262 switch (bma_static_property.mode) {
263 case BMA250_MODE_SUSPEND:
264 return INV_MODE_SUSPEND;
265 case BMA250_MODE_NORMAL:
266 return INV_MODE_NORMAL;
273 * set_lpf_bma250() - set lpf value
276 static int set_lpf_bma250(struct inv_mpu_iio_s *st, int rate)
278 const short hz[] = {1000, 500, 250, 125, 62, 31, 15, 7};
279 const int d[] = {7, 6, 5, 4, 3, 2, 1, 0};
280 int i, h, data, result;
283 while ((h < hz[i]) && (i < ARRAY_SIZE(hz) - 1))
287 result = set_3050_bypass(st, true);
290 result = bma250_set_bandwidth(st, (u8) data);
291 result |= set_3050_bypass(st, false);
293 return result ? (-EINVAL) : 0;
296 * set_fs_bma250() - set range value
299 static int set_fs_bma250(struct inv_mpu_iio_s *st, int fs)
302 result = set_3050_bypass(st, true);
305 result = bma250_set_range(st, (u8) fs);
306 result |= set_3050_bypass(st, false);
308 return result ? (-EINVAL) : 0;
311 static struct inv_mpu_slave slave_bma250 = {
312 .suspend = suspend_slave_bma250,
313 .resume = resume_slave_bma250,
314 .setup = setup_slave_bma250,
315 .combine_data = combine_data_slave_bma250,
316 .get_mode = get_mode_slave_bma250,
317 .set_lpf = set_lpf_bma250,
318 .set_fs = set_fs_bma250
321 int inv_register_mpu3050_slave(struct inv_mpu_iio_s *st)
323 st->mpu_slave = &slave_bma250;