Merge tag 'nfs-for-4.2-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
[firefly-linux-kernel-4.4.55.git] / drivers / iio / magnetometer / st_magn_core.c
1 /*
2  * STMicroelectronics magnetometers driver
3  *
4  * Copyright 2012-2013 STMicroelectronics Inc.
5  *
6  * Denis Ciocca <denis.ciocca@st.com>
7  *
8  * Licensed under the GPL-2.
9  */
10
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/slab.h>
14 #include <linux/errno.h>
15 #include <linux/types.h>
16 #include <linux/mutex.h>
17 #include <linux/interrupt.h>
18 #include <linux/i2c.h>
19 #include <linux/gpio.h>
20 #include <linux/irq.h>
21 #include <linux/delay.h>
22 #include <linux/iio/iio.h>
23 #include <linux/iio/sysfs.h>
24 #include <linux/iio/buffer.h>
25
26 #include <linux/iio/common/st_sensors.h>
27 #include "st_magn.h"
28
29 #define ST_MAGN_NUMBER_DATA_CHANNELS            3
30
31 /* DEFAULT VALUE FOR SENSORS */
32 #define ST_MAGN_DEFAULT_OUT_X_H_ADDR            0X03
33 #define ST_MAGN_DEFAULT_OUT_Y_H_ADDR            0X07
34 #define ST_MAGN_DEFAULT_OUT_Z_H_ADDR            0X05
35
36 /* FULLSCALE */
37 #define ST_MAGN_FS_AVL_1300MG                   1300
38 #define ST_MAGN_FS_AVL_1900MG                   1900
39 #define ST_MAGN_FS_AVL_2500MG                   2500
40 #define ST_MAGN_FS_AVL_4000MG                   4000
41 #define ST_MAGN_FS_AVL_4700MG                   4700
42 #define ST_MAGN_FS_AVL_5600MG                   5600
43 #define ST_MAGN_FS_AVL_8000MG                   8000
44 #define ST_MAGN_FS_AVL_8100MG                   8100
45 #define ST_MAGN_FS_AVL_12000MG                  12000
46 #define ST_MAGN_FS_AVL_16000MG                  16000
47
48 /* CUSTOM VALUES FOR SENSOR 0 */
49 #define ST_MAGN_0_ODR_ADDR                      0x00
50 #define ST_MAGN_0_ODR_MASK                      0x1c
51 #define ST_MAGN_0_ODR_AVL_1HZ_VAL               0x00
52 #define ST_MAGN_0_ODR_AVL_2HZ_VAL               0x01
53 #define ST_MAGN_0_ODR_AVL_3HZ_VAL               0x02
54 #define ST_MAGN_0_ODR_AVL_8HZ_VAL               0x03
55 #define ST_MAGN_0_ODR_AVL_15HZ_VAL              0x04
56 #define ST_MAGN_0_ODR_AVL_30HZ_VAL              0x05
57 #define ST_MAGN_0_ODR_AVL_75HZ_VAL              0x06
58 #define ST_MAGN_0_ODR_AVL_220HZ_VAL             0x07
59 #define ST_MAGN_0_PW_ADDR                       0x02
60 #define ST_MAGN_0_PW_MASK                       0x03
61 #define ST_MAGN_0_PW_ON                         0x00
62 #define ST_MAGN_0_PW_OFF                        0x03
63 #define ST_MAGN_0_FS_ADDR                       0x01
64 #define ST_MAGN_0_FS_MASK                       0xe0
65 #define ST_MAGN_0_FS_AVL_1300_VAL               0x01
66 #define ST_MAGN_0_FS_AVL_1900_VAL               0x02
67 #define ST_MAGN_0_FS_AVL_2500_VAL               0x03
68 #define ST_MAGN_0_FS_AVL_4000_VAL               0x04
69 #define ST_MAGN_0_FS_AVL_4700_VAL               0x05
70 #define ST_MAGN_0_FS_AVL_5600_VAL               0x06
71 #define ST_MAGN_0_FS_AVL_8100_VAL               0x07
72 #define ST_MAGN_0_FS_AVL_1300_GAIN_XY           1100
73 #define ST_MAGN_0_FS_AVL_1900_GAIN_XY           855
74 #define ST_MAGN_0_FS_AVL_2500_GAIN_XY           670
75 #define ST_MAGN_0_FS_AVL_4000_GAIN_XY           450
76 #define ST_MAGN_0_FS_AVL_4700_GAIN_XY           400
77 #define ST_MAGN_0_FS_AVL_5600_GAIN_XY           330
78 #define ST_MAGN_0_FS_AVL_8100_GAIN_XY           230
79 #define ST_MAGN_0_FS_AVL_1300_GAIN_Z            980
80 #define ST_MAGN_0_FS_AVL_1900_GAIN_Z            760
81 #define ST_MAGN_0_FS_AVL_2500_GAIN_Z            600
82 #define ST_MAGN_0_FS_AVL_4000_GAIN_Z            400
83 #define ST_MAGN_0_FS_AVL_4700_GAIN_Z            355
84 #define ST_MAGN_0_FS_AVL_5600_GAIN_Z            295
85 #define ST_MAGN_0_FS_AVL_8100_GAIN_Z            205
86 #define ST_MAGN_0_MULTIREAD_BIT                 false
87
88 /* CUSTOM VALUES FOR SENSOR 1 */
89 #define ST_MAGN_1_WAI_EXP                       0x3c
90 #define ST_MAGN_1_ODR_ADDR                      0x00
91 #define ST_MAGN_1_ODR_MASK                      0x1c
92 #define ST_MAGN_1_ODR_AVL_1HZ_VAL               0x00
93 #define ST_MAGN_1_ODR_AVL_2HZ_VAL               0x01
94 #define ST_MAGN_1_ODR_AVL_3HZ_VAL               0x02
95 #define ST_MAGN_1_ODR_AVL_8HZ_VAL               0x03
96 #define ST_MAGN_1_ODR_AVL_15HZ_VAL              0x04
97 #define ST_MAGN_1_ODR_AVL_30HZ_VAL              0x05
98 #define ST_MAGN_1_ODR_AVL_75HZ_VAL              0x06
99 #define ST_MAGN_1_ODR_AVL_220HZ_VAL             0x07
100 #define ST_MAGN_1_PW_ADDR                       0x02
101 #define ST_MAGN_1_PW_MASK                       0x03
102 #define ST_MAGN_1_PW_ON                         0x00
103 #define ST_MAGN_1_PW_OFF                        0x03
104 #define ST_MAGN_1_FS_ADDR                       0x01
105 #define ST_MAGN_1_FS_MASK                       0xe0
106 #define ST_MAGN_1_FS_AVL_1300_VAL               0x01
107 #define ST_MAGN_1_FS_AVL_1900_VAL               0x02
108 #define ST_MAGN_1_FS_AVL_2500_VAL               0x03
109 #define ST_MAGN_1_FS_AVL_4000_VAL               0x04
110 #define ST_MAGN_1_FS_AVL_4700_VAL               0x05
111 #define ST_MAGN_1_FS_AVL_5600_VAL               0x06
112 #define ST_MAGN_1_FS_AVL_8100_VAL               0x07
113 #define ST_MAGN_1_FS_AVL_1300_GAIN_XY           909
114 #define ST_MAGN_1_FS_AVL_1900_GAIN_XY           1169
115 #define ST_MAGN_1_FS_AVL_2500_GAIN_XY           1492
116 #define ST_MAGN_1_FS_AVL_4000_GAIN_XY           2222
117 #define ST_MAGN_1_FS_AVL_4700_GAIN_XY           2500
118 #define ST_MAGN_1_FS_AVL_5600_GAIN_XY           3030
119 #define ST_MAGN_1_FS_AVL_8100_GAIN_XY           4347
120 #define ST_MAGN_1_FS_AVL_1300_GAIN_Z            1020
121 #define ST_MAGN_1_FS_AVL_1900_GAIN_Z            1315
122 #define ST_MAGN_1_FS_AVL_2500_GAIN_Z            1666
123 #define ST_MAGN_1_FS_AVL_4000_GAIN_Z            2500
124 #define ST_MAGN_1_FS_AVL_4700_GAIN_Z            2816
125 #define ST_MAGN_1_FS_AVL_5600_GAIN_Z            3389
126 #define ST_MAGN_1_FS_AVL_8100_GAIN_Z            4878
127 #define ST_MAGN_1_MULTIREAD_BIT                 false
128
129 /* CUSTOM VALUES FOR SENSOR 2 */
130 #define ST_MAGN_2_WAI_EXP                       0x3d
131 #define ST_MAGN_2_ODR_ADDR                      0x20
132 #define ST_MAGN_2_ODR_MASK                      0x1c
133 #define ST_MAGN_2_ODR_AVL_1HZ_VAL               0x00
134 #define ST_MAGN_2_ODR_AVL_2HZ_VAL               0x01
135 #define ST_MAGN_2_ODR_AVL_3HZ_VAL               0x02
136 #define ST_MAGN_2_ODR_AVL_5HZ_VAL               0x03
137 #define ST_MAGN_2_ODR_AVL_10HZ_VAL              0x04
138 #define ST_MAGN_2_ODR_AVL_20HZ_VAL              0x05
139 #define ST_MAGN_2_ODR_AVL_40HZ_VAL              0x06
140 #define ST_MAGN_2_ODR_AVL_80HZ_VAL              0x07
141 #define ST_MAGN_2_PW_ADDR                       0x22
142 #define ST_MAGN_2_PW_MASK                       0x03
143 #define ST_MAGN_2_PW_ON                         0x00
144 #define ST_MAGN_2_PW_OFF                        0x03
145 #define ST_MAGN_2_FS_ADDR                       0x21
146 #define ST_MAGN_2_FS_MASK                       0x60
147 #define ST_MAGN_2_FS_AVL_4000_VAL               0x00
148 #define ST_MAGN_2_FS_AVL_8000_VAL               0x01
149 #define ST_MAGN_2_FS_AVL_12000_VAL              0x02
150 #define ST_MAGN_2_FS_AVL_16000_VAL              0x03
151 #define ST_MAGN_2_FS_AVL_4000_GAIN              146
152 #define ST_MAGN_2_FS_AVL_8000_GAIN              292
153 #define ST_MAGN_2_FS_AVL_12000_GAIN             438
154 #define ST_MAGN_2_FS_AVL_16000_GAIN             584
155 #define ST_MAGN_2_MULTIREAD_BIT                 false
156 #define ST_MAGN_2_OUT_X_L_ADDR                  0x28
157 #define ST_MAGN_2_OUT_Y_L_ADDR                  0x2a
158 #define ST_MAGN_2_OUT_Z_L_ADDR                  0x2c
159
160 static const struct iio_chan_spec st_magn_16bit_channels[] = {
161         ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
162                         BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
163                         ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_BE, 16, 16,
164                         ST_MAGN_DEFAULT_OUT_X_H_ADDR),
165         ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
166                         BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
167                         ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_BE, 16, 16,
168                         ST_MAGN_DEFAULT_OUT_Y_H_ADDR),
169         ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
170                         BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
171                         ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_BE, 16, 16,
172                         ST_MAGN_DEFAULT_OUT_Z_H_ADDR),
173         IIO_CHAN_SOFT_TIMESTAMP(3)
174 };
175
176 static const struct iio_chan_spec st_magn_2_16bit_channels[] = {
177         ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
178                         BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
179                         ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,
180                         ST_MAGN_2_OUT_X_L_ADDR),
181         ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
182                         BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
183                         ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,
184                         ST_MAGN_2_OUT_Y_L_ADDR),
185         ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
186                         BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
187                         ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,
188                         ST_MAGN_2_OUT_Z_L_ADDR),
189         IIO_CHAN_SOFT_TIMESTAMP(3)
190 };
191
192 static const struct st_sensor_settings st_magn_sensors_settings[] = {
193         {
194                 .wai = 0, /* This sensor has no valid WhoAmI report 0 */
195                 .sensors_supported = {
196                         [0] = LSM303DLH_MAGN_DEV_NAME,
197                 },
198                 .ch = (struct iio_chan_spec *)st_magn_16bit_channels,
199                 .odr = {
200                         .addr = ST_MAGN_0_ODR_ADDR,
201                         .mask = ST_MAGN_0_ODR_MASK,
202                         .odr_avl = {
203                                 { 1, ST_MAGN_0_ODR_AVL_1HZ_VAL, },
204                                 { 2, ST_MAGN_0_ODR_AVL_2HZ_VAL, },
205                                 { 3, ST_MAGN_0_ODR_AVL_3HZ_VAL, },
206                                 { 8, ST_MAGN_0_ODR_AVL_8HZ_VAL, },
207                                 { 15, ST_MAGN_0_ODR_AVL_15HZ_VAL, },
208                                 { 30, ST_MAGN_0_ODR_AVL_30HZ_VAL, },
209                                 { 75, ST_MAGN_0_ODR_AVL_75HZ_VAL, },
210                         },
211                 },
212                 .pw = {
213                         .addr = ST_MAGN_0_PW_ADDR,
214                         .mask = ST_MAGN_0_PW_MASK,
215                         .value_on = ST_MAGN_0_PW_ON,
216                         .value_off = ST_MAGN_0_PW_OFF,
217                 },
218                 .fs = {
219                         .addr = ST_MAGN_0_FS_ADDR,
220                         .mask = ST_MAGN_0_FS_MASK,
221                         .fs_avl = {
222                                 [0] = {
223                                         .num = ST_MAGN_FS_AVL_1300MG,
224                                         .value = ST_MAGN_0_FS_AVL_1300_VAL,
225                                         .gain = ST_MAGN_0_FS_AVL_1300_GAIN_XY,
226                                         .gain2 = ST_MAGN_0_FS_AVL_1300_GAIN_Z,
227                                 },
228                                 [1] = {
229                                         .num = ST_MAGN_FS_AVL_1900MG,
230                                         .value = ST_MAGN_0_FS_AVL_1900_VAL,
231                                         .gain = ST_MAGN_0_FS_AVL_1900_GAIN_XY,
232                                         .gain2 = ST_MAGN_0_FS_AVL_1900_GAIN_Z,
233                                 },
234                                 [2] = {
235                                         .num = ST_MAGN_FS_AVL_2500MG,
236                                         .value = ST_MAGN_0_FS_AVL_2500_VAL,
237                                         .gain = ST_MAGN_0_FS_AVL_2500_GAIN_XY,
238                                         .gain2 = ST_MAGN_0_FS_AVL_2500_GAIN_Z,
239                                 },
240                                 [3] = {
241                                         .num = ST_MAGN_FS_AVL_4000MG,
242                                         .value = ST_MAGN_0_FS_AVL_4000_VAL,
243                                         .gain = ST_MAGN_0_FS_AVL_4000_GAIN_XY,
244                                         .gain2 = ST_MAGN_0_FS_AVL_4000_GAIN_Z,
245                                 },
246                                 [4] = {
247                                         .num = ST_MAGN_FS_AVL_4700MG,
248                                         .value = ST_MAGN_0_FS_AVL_4700_VAL,
249                                         .gain = ST_MAGN_0_FS_AVL_4700_GAIN_XY,
250                                         .gain2 = ST_MAGN_0_FS_AVL_4700_GAIN_Z,
251                                 },
252                                 [5] = {
253                                         .num = ST_MAGN_FS_AVL_5600MG,
254                                         .value = ST_MAGN_0_FS_AVL_5600_VAL,
255                                         .gain = ST_MAGN_0_FS_AVL_5600_GAIN_XY,
256                                         .gain2 = ST_MAGN_0_FS_AVL_5600_GAIN_Z,
257                                 },
258                                 [6] = {
259                                         .num = ST_MAGN_FS_AVL_8100MG,
260                                         .value = ST_MAGN_0_FS_AVL_8100_VAL,
261                                         .gain = ST_MAGN_0_FS_AVL_8100_GAIN_XY,
262                                         .gain2 = ST_MAGN_0_FS_AVL_8100_GAIN_Z,
263                                 },
264                         },
265                 },
266                 .multi_read_bit = ST_MAGN_0_MULTIREAD_BIT,
267                 .bootime = 2,
268         },
269         {
270                 .wai = ST_MAGN_1_WAI_EXP,
271                 .sensors_supported = {
272                         [0] = LSM303DLHC_MAGN_DEV_NAME,
273                         [1] = LSM303DLM_MAGN_DEV_NAME,
274                 },
275                 .ch = (struct iio_chan_spec *)st_magn_16bit_channels,
276                 .odr = {
277                         .addr = ST_MAGN_1_ODR_ADDR,
278                         .mask = ST_MAGN_1_ODR_MASK,
279                         .odr_avl = {
280                                 { 1, ST_MAGN_1_ODR_AVL_1HZ_VAL, },
281                                 { 2, ST_MAGN_1_ODR_AVL_2HZ_VAL, },
282                                 { 3, ST_MAGN_1_ODR_AVL_3HZ_VAL, },
283                                 { 8, ST_MAGN_1_ODR_AVL_8HZ_VAL, },
284                                 { 15, ST_MAGN_1_ODR_AVL_15HZ_VAL, },
285                                 { 30, ST_MAGN_1_ODR_AVL_30HZ_VAL, },
286                                 { 75, ST_MAGN_1_ODR_AVL_75HZ_VAL, },
287                                 { 220, ST_MAGN_1_ODR_AVL_220HZ_VAL, },
288                         },
289                 },
290                 .pw = {
291                         .addr = ST_MAGN_1_PW_ADDR,
292                         .mask = ST_MAGN_1_PW_MASK,
293                         .value_on = ST_MAGN_1_PW_ON,
294                         .value_off = ST_MAGN_1_PW_OFF,
295                 },
296                 .fs = {
297                         .addr = ST_MAGN_1_FS_ADDR,
298                         .mask = ST_MAGN_1_FS_MASK,
299                         .fs_avl = {
300                                 [0] = {
301                                         .num = ST_MAGN_FS_AVL_1300MG,
302                                         .value = ST_MAGN_1_FS_AVL_1300_VAL,
303                                         .gain = ST_MAGN_1_FS_AVL_1300_GAIN_XY,
304                                         .gain2 = ST_MAGN_1_FS_AVL_1300_GAIN_Z,
305                                 },
306                                 [1] = {
307                                         .num = ST_MAGN_FS_AVL_1900MG,
308                                         .value = ST_MAGN_1_FS_AVL_1900_VAL,
309                                         .gain = ST_MAGN_1_FS_AVL_1900_GAIN_XY,
310                                         .gain2 = ST_MAGN_1_FS_AVL_1900_GAIN_Z,
311                                 },
312                                 [2] = {
313                                         .num = ST_MAGN_FS_AVL_2500MG,
314                                         .value = ST_MAGN_1_FS_AVL_2500_VAL,
315                                         .gain = ST_MAGN_1_FS_AVL_2500_GAIN_XY,
316                                         .gain2 = ST_MAGN_1_FS_AVL_2500_GAIN_Z,
317                                 },
318                                 [3] = {
319                                         .num = ST_MAGN_FS_AVL_4000MG,
320                                         .value = ST_MAGN_1_FS_AVL_4000_VAL,
321                                         .gain = ST_MAGN_1_FS_AVL_4000_GAIN_XY,
322                                         .gain2 = ST_MAGN_1_FS_AVL_4000_GAIN_Z,
323                                 },
324                                 [4] = {
325                                         .num = ST_MAGN_FS_AVL_4700MG,
326                                         .value = ST_MAGN_1_FS_AVL_4700_VAL,
327                                         .gain = ST_MAGN_1_FS_AVL_4700_GAIN_XY,
328                                         .gain2 = ST_MAGN_1_FS_AVL_4700_GAIN_Z,
329                                 },
330                                 [5] = {
331                                         .num = ST_MAGN_FS_AVL_5600MG,
332                                         .value = ST_MAGN_1_FS_AVL_5600_VAL,
333                                         .gain = ST_MAGN_1_FS_AVL_5600_GAIN_XY,
334                                         .gain2 = ST_MAGN_1_FS_AVL_5600_GAIN_Z,
335                                 },
336                                 [6] = {
337                                         .num = ST_MAGN_FS_AVL_8100MG,
338                                         .value = ST_MAGN_1_FS_AVL_8100_VAL,
339                                         .gain = ST_MAGN_1_FS_AVL_8100_GAIN_XY,
340                                         .gain2 = ST_MAGN_1_FS_AVL_8100_GAIN_Z,
341                                 },
342                         },
343                 },
344                 .multi_read_bit = ST_MAGN_1_MULTIREAD_BIT,
345                 .bootime = 2,
346         },
347         {
348                 .wai = ST_MAGN_2_WAI_EXP,
349                 .sensors_supported = {
350                         [0] = LIS3MDL_MAGN_DEV_NAME,
351                 },
352                 .ch = (struct iio_chan_spec *)st_magn_2_16bit_channels,
353                 .odr = {
354                         .addr = ST_MAGN_2_ODR_ADDR,
355                         .mask = ST_MAGN_2_ODR_MASK,
356                         .odr_avl = {
357                                 { 1, ST_MAGN_2_ODR_AVL_1HZ_VAL, },
358                                 { 2, ST_MAGN_2_ODR_AVL_2HZ_VAL, },
359                                 { 3, ST_MAGN_2_ODR_AVL_3HZ_VAL, },
360                                 { 5, ST_MAGN_2_ODR_AVL_5HZ_VAL, },
361                                 { 10, ST_MAGN_2_ODR_AVL_10HZ_VAL, },
362                                 { 20, ST_MAGN_2_ODR_AVL_20HZ_VAL, },
363                                 { 40, ST_MAGN_2_ODR_AVL_40HZ_VAL, },
364                                 { 80, ST_MAGN_2_ODR_AVL_80HZ_VAL, },
365                         },
366                 },
367                 .pw = {
368                         .addr = ST_MAGN_2_PW_ADDR,
369                         .mask = ST_MAGN_2_PW_MASK,
370                         .value_on = ST_MAGN_2_PW_ON,
371                         .value_off = ST_MAGN_2_PW_OFF,
372                 },
373                 .fs = {
374                         .addr = ST_MAGN_2_FS_ADDR,
375                         .mask = ST_MAGN_2_FS_MASK,
376                         .fs_avl = {
377                                 [0] = {
378                                         .num = ST_MAGN_FS_AVL_4000MG,
379                                         .value = ST_MAGN_2_FS_AVL_4000_VAL,
380                                         .gain = ST_MAGN_2_FS_AVL_4000_GAIN,
381                                 },
382                                 [1] = {
383                                         .num = ST_MAGN_FS_AVL_8000MG,
384                                         .value = ST_MAGN_2_FS_AVL_8000_VAL,
385                                         .gain = ST_MAGN_2_FS_AVL_8000_GAIN,
386                                 },
387                                 [2] = {
388                                         .num = ST_MAGN_FS_AVL_12000MG,
389                                         .value = ST_MAGN_2_FS_AVL_12000_VAL,
390                                         .gain = ST_MAGN_2_FS_AVL_12000_GAIN,
391                                 },
392                                 [3] = {
393                                         .num = ST_MAGN_FS_AVL_16000MG,
394                                         .value = ST_MAGN_2_FS_AVL_16000_VAL,
395                                         .gain = ST_MAGN_2_FS_AVL_16000_GAIN,
396                                 },
397                         },
398                 },
399                 .multi_read_bit = ST_MAGN_2_MULTIREAD_BIT,
400                 .bootime = 2,
401         },
402 };
403
404 static int st_magn_read_raw(struct iio_dev *indio_dev,
405                         struct iio_chan_spec const *ch, int *val,
406                                                         int *val2, long mask)
407 {
408         int err;
409         struct st_sensor_data *mdata = iio_priv(indio_dev);
410
411         switch (mask) {
412         case IIO_CHAN_INFO_RAW:
413                 err = st_sensors_read_info_raw(indio_dev, ch, val);
414                 if (err < 0)
415                         goto read_error;
416
417                 return IIO_VAL_INT;
418         case IIO_CHAN_INFO_SCALE:
419                 *val = 0;
420                 if ((ch->scan_index == ST_SENSORS_SCAN_Z) &&
421                                         (mdata->current_fullscale->gain2 != 0))
422                         *val2 = mdata->current_fullscale->gain2;
423                 else
424                         *val2 = mdata->current_fullscale->gain;
425                 return IIO_VAL_INT_PLUS_MICRO;
426         case IIO_CHAN_INFO_SAMP_FREQ:
427                 *val = mdata->odr;
428                 return IIO_VAL_INT;
429         default:
430                 return -EINVAL;
431         }
432
433 read_error:
434         return err;
435 }
436
437 static int st_magn_write_raw(struct iio_dev *indio_dev,
438                 struct iio_chan_spec const *chan, int val, int val2, long mask)
439 {
440         int err;
441
442         switch (mask) {
443         case IIO_CHAN_INFO_SCALE:
444                 err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
445                 break;
446         case IIO_CHAN_INFO_SAMP_FREQ:
447                 if (val2)
448                         return -EINVAL;
449                 mutex_lock(&indio_dev->mlock);
450                 err = st_sensors_set_odr(indio_dev, val);
451                 mutex_unlock(&indio_dev->mlock);
452                 return err;
453         default:
454                 err = -EINVAL;
455         }
456
457         return err;
458 }
459
460 static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
461 static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_magn_scale_available);
462
463 static struct attribute *st_magn_attributes[] = {
464         &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
465         &iio_dev_attr_in_magn_scale_available.dev_attr.attr,
466         NULL,
467 };
468
469 static const struct attribute_group st_magn_attribute_group = {
470         .attrs = st_magn_attributes,
471 };
472
473 static const struct iio_info magn_info = {
474         .driver_module = THIS_MODULE,
475         .attrs = &st_magn_attribute_group,
476         .read_raw = &st_magn_read_raw,
477         .write_raw = &st_magn_write_raw,
478 };
479
480 int st_magn_common_probe(struct iio_dev *indio_dev)
481 {
482         struct st_sensor_data *mdata = iio_priv(indio_dev);
483         int irq = mdata->get_irq_data_ready(indio_dev);
484         int err;
485
486         indio_dev->modes = INDIO_DIRECT_MODE;
487         indio_dev->info = &magn_info;
488         mutex_init(&mdata->tb.buf_lock);
489
490         st_sensors_power_enable(indio_dev);
491
492         err = st_sensors_check_device_support(indio_dev,
493                                         ARRAY_SIZE(st_magn_sensors_settings),
494                                         st_magn_sensors_settings);
495         if (err < 0)
496                 return err;
497
498         mdata->num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS;
499         mdata->multiread_bit = mdata->sensor_settings->multi_read_bit;
500         indio_dev->channels = mdata->sensor_settings->ch;
501         indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
502
503         mdata->current_fullscale = (struct st_sensor_fullscale_avl *)
504                                         &mdata->sensor_settings->fs.fs_avl[0];
505         mdata->odr = mdata->sensor_settings->odr.odr_avl[0].hz;
506
507         err = st_sensors_init_sensor(indio_dev, NULL);
508         if (err < 0)
509                 return err;
510
511         err = st_magn_allocate_ring(indio_dev);
512         if (err < 0)
513                 return err;
514
515         if (irq > 0) {
516                 err = st_sensors_allocate_trigger(indio_dev, NULL);
517                 if (err < 0)
518                         goto st_magn_probe_trigger_error;
519         }
520
521         err = iio_device_register(indio_dev);
522         if (err)
523                 goto st_magn_device_register_error;
524
525         dev_info(&indio_dev->dev, "registered magnetometer %s\n",
526                  indio_dev->name);
527
528         return 0;
529
530 st_magn_device_register_error:
531         if (irq > 0)
532                 st_sensors_deallocate_trigger(indio_dev);
533 st_magn_probe_trigger_error:
534         st_magn_deallocate_ring(indio_dev);
535
536         return err;
537 }
538 EXPORT_SYMBOL(st_magn_common_probe);
539
540 void st_magn_common_remove(struct iio_dev *indio_dev)
541 {
542         struct st_sensor_data *mdata = iio_priv(indio_dev);
543
544         st_sensors_power_disable(indio_dev);
545
546         iio_device_unregister(indio_dev);
547         if (mdata->get_irq_data_ready(indio_dev) > 0)
548                 st_sensors_deallocate_trigger(indio_dev);
549
550         st_magn_deallocate_ring(indio_dev);
551 }
552 EXPORT_SYMBOL(st_magn_common_remove);
553
554 MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
555 MODULE_DESCRIPTION("STMicroelectronics magnetometers driver");
556 MODULE_LICENSE("GPL v2");