staging, iio, mpu: repack mpu driver's communicate interface
[firefly-linux-kernel-4.4.55.git] / drivers / staging / iio / imu / inv_mpu / inv_slave_bma250.c
1 /*
2 * Copyright (C) 2012 Invensense, Inc.
3 *
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.
7 *
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.
12 *
13 */
14
15 /**
16  *  @addtogroup  DRIVERS
17  *  @brief       Hardware drivers.
18  *
19  *  @{
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
23  *
24  */
25
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>
40
41 #include "inv_mpu_iio.h"
42 #define BMA250_CHIP_ID                  3
43 #define BMA250_RANGE_SET                0
44 #define BMA250_BW_SET                   4
45
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
53
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
64
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
70
71 /* mode settings */
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
79
80 struct bma_property {
81         int range;
82         int bandwidth;
83         int mode;
84 };
85
86 static struct bma_property bma_static_property = {
87         .range = BMA250_RANGE_SET,
88         .bandwidth = BMA250_BW_SET,
89         .mode = BMA250_MODE_SUSPEND
90 };
91
92 static int bma250_set_bandwidth(struct inv_mpu_iio_s *st, u8 bw)
93 {
94         int res;
95         u8 data;
96         int bandwidth;
97         switch (bw) {
98         case 0:
99                 bandwidth = BMA250_BW_7_81HZ;
100                 break;
101         case 1:
102                 bandwidth = BMA250_BW_15_63HZ;
103                 break;
104         case 2:
105                 bandwidth = BMA250_BW_31_25HZ;
106                 break;
107         case 3:
108                 bandwidth = BMA250_BW_62_50HZ;
109                 break;
110         case 4:
111                 bandwidth = BMA250_BW_125HZ;
112                 break;
113         case 5:
114                 bandwidth = BMA250_BW_250HZ;
115                 break;
116         case 6:
117                 bandwidth = BMA250_BW_500HZ;
118                 break;
119         case 7:
120                 bandwidth = BMA250_BW_1000HZ;
121                 break;
122         default:
123                 return -EINVAL;
124         }
125         res = inv_secondary_read(BMA250_BW_SEL_REG, 1, &data);
126         if (res)
127                 return res;
128         data &= BMA250_BW_REG_MASK;
129         data |= bandwidth;
130         res = inv_secondary_write(st, BMA250_BW_SEL_REG, data);
131         return res;
132 }
133
134 static int bma250_set_range(struct inv_mpu_iio_s *st, u8 range)
135 {
136         int res;
137         u8 orig, data;
138         switch (range) {
139         case 0:
140                 data  = BMA250_RANGE_2G;
141                 break;
142         case 1:
143                 data  = BMA250_RANGE_4G;
144                 break;
145         case 2:
146                 data  = BMA250_RANGE_8G;
147                 break;
148         case 3:
149                 data  = BMA250_RANGE_16G;
150                 break;
151         default:
152                 return -EINVAL;
153         }
154         res = inv_secondary_read(BMA250_RANGE_SEL_REG, 1, &orig);
155         if (res)
156                 return res;
157         orig &= BMA250_RANGE_MASK;
158         data |= orig;
159         res = inv_secondary_write(st, BMA250_RANGE_SEL_REG, data);
160         if (res)
161                 return res;
162         bma_static_property.range = range;
163
164         return 0;
165 }
166
167 static int setup_slave_bma250(struct inv_mpu_iio_s *st)
168 {
169         int result;
170         u8 data[2];
171         result = set_3050_bypass(st, true);
172         if (result)
173                 return result;
174         /*read secondary i2c ID register */
175         result = inv_secondary_read(0, 1, data);
176         if (result)
177                 return result;
178         if (BMA250_CHIP_ID != data[0])
179                 return -EINVAL;
180         result = set_3050_bypass(st, false);
181         if (result)
182                 return result;
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);
187
188         return result;
189 }
190
191 static int bma250_set_mode(struct inv_mpu_iio_s *st, u8 mode)
192 {
193         int res;
194         u8 data;
195
196         res = inv_secondary_read(BMA250_MODE_CTRL_REG, 1, &data);
197         if (res)
198                 return res;
199         data &= BMA250_MODE_MASK;
200         switch (mode) {
201         case BMA250_MODE_NORMAL:
202                 break;
203         case BMA250_MODE_LOWPOWER:
204                 data |= BMA250_BIT_LP;
205                 break;
206         case BMA250_MODE_SUSPEND:
207                 data |= BMA250_BIT_SUSPEND;
208                 break;
209         default:
210                 return -EINVAL;
211         }
212         res = inv_secondary_write(st, BMA250_MODE_CTRL_REG, data);
213         if (res)
214                 return res;
215         bma_static_property.mode = mode;
216
217         return 0;
218 }
219
220 static int suspend_slave_bma250(struct inv_mpu_iio_s *st)
221 {
222         int result;
223         if (bma_static_property.mode == BMA250_MODE_SUSPEND)
224                 return 0;
225         /*set to bypass mode */
226         result = set_3050_bypass(st, true);
227         if (result)
228                 return result;
229         bma250_set_mode(st, BMA250_MODE_SUSPEND);
230         /* no need to recover to non-bypass mode because we need it now */
231
232         return 0;
233 }
234
235 static int resume_slave_bma250(struct inv_mpu_iio_s *st)
236 {
237         int result;
238         if (bma_static_property.mode == BMA250_MODE_NORMAL)
239                 return 0;
240         /*set to bypass mode */
241         result = set_3050_bypass(st, true);
242         if (result)
243                 return result;
244         result = bma250_set_mode(st, BMA250_MODE_NORMAL);
245         /* recover bypass mode */
246         result |= set_3050_bypass(st, false);
247
248         return result ? (-EINVAL) : 0;
249 }
250
251 static int combine_data_slave_bma250(u8 *in, short *out)
252 {
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]));
256
257         return 0;
258 }
259
260 static int get_mode_slave_bma250(void)
261 {
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;
267         default:
268                 return -EINVAL;
269         }
270 }
271
272 /**
273  *  set_lpf_bma250() - set lpf value
274  */
275
276 static int set_lpf_bma250(struct inv_mpu_iio_s *st, int rate)
277 {
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;
281         h = (rate >> 1);
282         i = 0;
283         while ((h < hz[i]) && (i < ARRAY_SIZE(hz) - 1))
284                 i++;
285         data = d[i];
286
287         result = set_3050_bypass(st, true);
288         if (result)
289                 return result;
290         result = bma250_set_bandwidth(st, (u8) data);
291         result |= set_3050_bypass(st, false);
292
293         return result ? (-EINVAL) : 0;
294 }
295 /**
296  *  set_fs_bma250() - set range value
297  */
298
299 static int set_fs_bma250(struct inv_mpu_iio_s *st, int fs)
300 {
301         int result;
302         result = set_3050_bypass(st, true);
303         if (result)
304                 return result;
305         result = bma250_set_range(st, (u8) fs);
306         result |= set_3050_bypass(st, false);
307
308         return result ? (-EINVAL) : 0;
309 }
310
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
319 };
320
321 int inv_register_mpu3050_slave(struct inv_mpu_iio_s *st)
322 {
323         st->mpu_slave = &slave_bma250;
324
325         return 0;
326 }
327 /**
328  *  @}
329  */
330