1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * ADXL372 3-Axis Digital Accelerometer core driver |
4 | * |
5 | * Copyright 2018 Analog Devices Inc. |
6 | */ |
7 | |
8 | #include <linux/bitfield.h> |
9 | #include <linux/bitops.h> |
10 | #include <linux/interrupt.h> |
11 | #include <linux/irq.h> |
12 | #include <linux/module.h> |
13 | #include <linux/regmap.h> |
14 | #include <linux/spi/spi.h> |
15 | |
16 | #include <linux/iio/iio.h> |
17 | #include <linux/iio/sysfs.h> |
18 | #include <linux/iio/buffer.h> |
19 | #include <linux/iio/events.h> |
20 | #include <linux/iio/trigger.h> |
21 | #include <linux/iio/trigger_consumer.h> |
22 | #include <linux/iio/triggered_buffer.h> |
23 | |
24 | #include "adxl372.h" |
25 | |
26 | /* ADXL372 registers definition */ |
27 | #define ADXL372_DEVID 0x00 |
28 | #define ADXL372_DEVID_MST 0x01 |
29 | #define ADXL372_PARTID 0x02 |
30 | #define ADXL372_STATUS_1 0x04 |
31 | #define ADXL372_STATUS_2 0x05 |
32 | #define ADXL372_FIFO_ENTRIES_2 0x06 |
33 | #define ADXL372_FIFO_ENTRIES_1 0x07 |
34 | #define ADXL372_X_DATA_H 0x08 |
35 | #define ADXL372_X_DATA_L 0x09 |
36 | #define ADXL372_Y_DATA_H 0x0A |
37 | #define ADXL372_Y_DATA_L 0x0B |
38 | #define ADXL372_Z_DATA_H 0x0C |
39 | #define ADXL372_Z_DATA_L 0x0D |
40 | #define ADXL372_X_MAXPEAK_H 0x15 |
41 | #define ADXL372_X_MAXPEAK_L 0x16 |
42 | #define ADXL372_Y_MAXPEAK_H 0x17 |
43 | #define ADXL372_Y_MAXPEAK_L 0x18 |
44 | #define ADXL372_Z_MAXPEAK_H 0x19 |
45 | #define ADXL372_Z_MAXPEAK_L 0x1A |
46 | #define ADXL372_OFFSET_X 0x20 |
47 | #define ADXL372_OFFSET_Y 0x21 |
48 | #define ADXL372_OFFSET_Z 0x22 |
49 | #define ADXL372_X_THRESH_ACT_H 0x23 |
50 | #define ADXL372_X_THRESH_ACT_L 0x24 |
51 | #define ADXL372_Y_THRESH_ACT_H 0x25 |
52 | #define ADXL372_Y_THRESH_ACT_L 0x26 |
53 | #define ADXL372_Z_THRESH_ACT_H 0x27 |
54 | #define ADXL372_Z_THRESH_ACT_L 0x28 |
55 | #define ADXL372_TIME_ACT 0x29 |
56 | #define ADXL372_X_THRESH_INACT_H 0x2A |
57 | #define ADXL372_X_THRESH_INACT_L 0x2B |
58 | #define ADXL372_Y_THRESH_INACT_H 0x2C |
59 | #define ADXL372_Y_THRESH_INACT_L 0x2D |
60 | #define ADXL372_Z_THRESH_INACT_H 0x2E |
61 | #define ADXL372_Z_THRESH_INACT_L 0x2F |
62 | #define ADXL372_TIME_INACT_H 0x30 |
63 | #define ADXL372_TIME_INACT_L 0x31 |
64 | #define ADXL372_X_THRESH_ACT2_H 0x32 |
65 | #define ADXL372_X_THRESH_ACT2_L 0x33 |
66 | #define ADXL372_Y_THRESH_ACT2_H 0x34 |
67 | #define ADXL372_Y_THRESH_ACT2_L 0x35 |
68 | #define ADXL372_Z_THRESH_ACT2_H 0x36 |
69 | #define ADXL372_Z_THRESH_ACT2_L 0x37 |
70 | #define ADXL372_HPF 0x38 |
71 | #define ADXL372_FIFO_SAMPLES 0x39 |
72 | #define ADXL372_FIFO_CTL 0x3A |
73 | #define ADXL372_INT1_MAP 0x3B |
74 | #define ADXL372_INT2_MAP 0x3C |
75 | #define ADXL372_TIMING 0x3D |
76 | #define ADXL372_MEASURE 0x3E |
77 | #define ADXL372_POWER_CTL 0x3F |
78 | #define ADXL372_SELF_TEST 0x40 |
79 | #define ADXL372_RESET 0x41 |
80 | #define ADXL372_FIFO_DATA 0x42 |
81 | |
82 | #define ADXL372_DEVID_VAL 0xAD |
83 | #define ADXL372_PARTID_VAL 0xFA |
84 | #define ADXL372_RESET_CODE 0x52 |
85 | |
86 | /* ADXL372_POWER_CTL */ |
87 | #define ADXL372_POWER_CTL_MODE_MSK GENMASK_ULL(1, 0) |
88 | #define ADXL372_POWER_CTL_MODE(x) (((x) & 0x3) << 0) |
89 | |
90 | /* ADXL372_MEASURE */ |
91 | #define ADXL372_MEASURE_LINKLOOP_MSK GENMASK_ULL(5, 4) |
92 | #define ADXL372_MEASURE_LINKLOOP_MODE(x) (((x) & 0x3) << 4) |
93 | #define ADXL372_MEASURE_BANDWIDTH_MSK GENMASK_ULL(2, 0) |
94 | #define ADXL372_MEASURE_BANDWIDTH_MODE(x) (((x) & 0x7) << 0) |
95 | |
96 | /* ADXL372_TIMING */ |
97 | #define ADXL372_TIMING_ODR_MSK GENMASK_ULL(7, 5) |
98 | #define ADXL372_TIMING_ODR_MODE(x) (((x) & 0x7) << 5) |
99 | |
100 | /* ADXL372_FIFO_CTL */ |
101 | #define ADXL372_FIFO_CTL_FORMAT_MSK GENMASK(5, 3) |
102 | #define ADXL372_FIFO_CTL_FORMAT_MODE(x) (((x) & 0x7) << 3) |
103 | #define ADXL372_FIFO_CTL_MODE_MSK GENMASK(2, 1) |
104 | #define ADXL372_FIFO_CTL_MODE_MODE(x) (((x) & 0x3) << 1) |
105 | #define ADXL372_FIFO_CTL_SAMPLES_MSK BIT(1) |
106 | #define ADXL372_FIFO_CTL_SAMPLES_MODE(x) (((x) > 0xFF) ? 1 : 0) |
107 | |
108 | /* ADXL372_STATUS_1 */ |
109 | #define ADXL372_STATUS_1_DATA_RDY(x) (((x) >> 0) & 0x1) |
110 | #define ADXL372_STATUS_1_FIFO_RDY(x) (((x) >> 1) & 0x1) |
111 | #define ADXL372_STATUS_1_FIFO_FULL(x) (((x) >> 2) & 0x1) |
112 | #define ADXL372_STATUS_1_FIFO_OVR(x) (((x) >> 3) & 0x1) |
113 | #define ADXL372_STATUS_1_USR_NVM_BUSY(x) (((x) >> 5) & 0x1) |
114 | #define ADXL372_STATUS_1_AWAKE(x) (((x) >> 6) & 0x1) |
115 | #define ADXL372_STATUS_1_ERR_USR_REGS(x) (((x) >> 7) & 0x1) |
116 | |
117 | /* ADXL372_STATUS_2 */ |
118 | #define ADXL372_STATUS_2_INACT(x) (((x) >> 4) & 0x1) |
119 | #define ADXL372_STATUS_2_ACT(x) (((x) >> 5) & 0x1) |
120 | #define ADXL372_STATUS_2_AC2(x) (((x) >> 6) & 0x1) |
121 | |
122 | /* ADXL372_INT1_MAP */ |
123 | #define ADXL372_INT1_MAP_DATA_RDY_MSK BIT(0) |
124 | #define ADXL372_INT1_MAP_DATA_RDY_MODE(x) (((x) & 0x1) << 0) |
125 | #define ADXL372_INT1_MAP_FIFO_RDY_MSK BIT(1) |
126 | #define ADXL372_INT1_MAP_FIFO_RDY_MODE(x) (((x) & 0x1) << 1) |
127 | #define ADXL372_INT1_MAP_FIFO_FULL_MSK BIT(2) |
128 | #define ADXL372_INT1_MAP_FIFO_FULL_MODE(x) (((x) & 0x1) << 2) |
129 | #define ADXL372_INT1_MAP_FIFO_OVR_MSK BIT(3) |
130 | #define ADXL372_INT1_MAP_FIFO_OVR_MODE(x) (((x) & 0x1) << 3) |
131 | #define ADXL372_INT1_MAP_INACT_MSK BIT(4) |
132 | #define ADXL372_INT1_MAP_INACT_MODE(x) (((x) & 0x1) << 4) |
133 | #define ADXL372_INT1_MAP_ACT_MSK BIT(5) |
134 | #define ADXL372_INT1_MAP_ACT_MODE(x) (((x) & 0x1) << 5) |
135 | #define ADXL372_INT1_MAP_AWAKE_MSK BIT(6) |
136 | #define ADXL372_INT1_MAP_AWAKE_MODE(x) (((x) & 0x1) << 6) |
137 | #define ADXL372_INT1_MAP_LOW_MSK BIT(7) |
138 | #define ADXL372_INT1_MAP_LOW_MODE(x) (((x) & 0x1) << 7) |
139 | |
140 | /* ADX372_THRESH */ |
141 | #define ADXL372_THRESH_VAL_H_MSK GENMASK(10, 3) |
142 | #define ADXL372_THRESH_VAL_H_SEL(x) FIELD_GET(ADXL372_THRESH_VAL_H_MSK, x) |
143 | #define ADXL372_THRESH_VAL_L_MSK GENMASK(2, 0) |
144 | #define ADXL372_THRESH_VAL_L_SEL(x) FIELD_GET(ADXL372_THRESH_VAL_L_MSK, x) |
145 | |
146 | /* The ADXL372 includes a deep, 512 sample FIFO buffer */ |
147 | #define ADXL372_FIFO_SIZE 512 |
148 | #define ADXL372_X_AXIS_EN(x) ((x) & BIT(0)) |
149 | #define ADXL372_Y_AXIS_EN(x) ((x) & BIT(1)) |
150 | #define ADXL372_Z_AXIS_EN(x) ((x) & BIT(2)) |
151 | |
152 | /* |
153 | * At +/- 200g with 12-bit resolution, scale is computed as: |
154 | * (200 + 200) * 9.81 / (2^12 - 1) = 0.958241 |
155 | */ |
156 | #define ADXL372_USCALE 958241 |
157 | |
158 | enum adxl372_op_mode { |
159 | ADXL372_STANDBY, |
160 | ADXL372_WAKE_UP, |
161 | ADXL372_INSTANT_ON, |
162 | ADXL372_FULL_BW_MEASUREMENT, |
163 | }; |
164 | |
165 | enum adxl372_act_proc_mode { |
166 | ADXL372_DEFAULT, |
167 | ADXL372_LINKED, |
168 | ADXL372_LOOPED, |
169 | }; |
170 | |
171 | enum adxl372_th_activity { |
172 | ADXL372_ACTIVITY, |
173 | ADXL372_ACTIVITY2, |
174 | ADXL372_INACTIVITY, |
175 | }; |
176 | |
177 | enum adxl372_odr { |
178 | ADXL372_ODR_400HZ, |
179 | ADXL372_ODR_800HZ, |
180 | ADXL372_ODR_1600HZ, |
181 | ADXL372_ODR_3200HZ, |
182 | ADXL372_ODR_6400HZ, |
183 | }; |
184 | |
185 | enum adxl372_bandwidth { |
186 | ADXL372_BW_200HZ, |
187 | ADXL372_BW_400HZ, |
188 | ADXL372_BW_800HZ, |
189 | ADXL372_BW_1600HZ, |
190 | ADXL372_BW_3200HZ, |
191 | }; |
192 | |
193 | static const unsigned int adxl372_th_reg_high_addr[3] = { |
194 | [ADXL372_ACTIVITY] = ADXL372_X_THRESH_ACT_H, |
195 | [ADXL372_ACTIVITY2] = ADXL372_X_THRESH_ACT2_H, |
196 | [ADXL372_INACTIVITY] = ADXL372_X_THRESH_INACT_H, |
197 | }; |
198 | |
199 | enum adxl372_fifo_format { |
200 | ADXL372_XYZ_FIFO, |
201 | ADXL372_X_FIFO, |
202 | ADXL372_Y_FIFO, |
203 | ADXL372_XY_FIFO, |
204 | ADXL372_Z_FIFO, |
205 | ADXL372_XZ_FIFO, |
206 | ADXL372_YZ_FIFO, |
207 | ADXL372_XYZ_PEAK_FIFO, |
208 | }; |
209 | |
210 | enum adxl372_fifo_mode { |
211 | ADXL372_FIFO_BYPASSED, |
212 | ADXL372_FIFO_STREAMED, |
213 | ADXL372_FIFO_TRIGGERED, |
214 | ADXL372_FIFO_OLD_SAVED |
215 | }; |
216 | |
217 | static const int adxl372_samp_freq_tbl[5] = { |
218 | 400, 800, 1600, 3200, 6400, |
219 | }; |
220 | |
221 | static const int adxl372_bw_freq_tbl[5] = { |
222 | 200, 400, 800, 1600, 3200, |
223 | }; |
224 | |
225 | struct adxl372_axis_lookup { |
226 | unsigned int bits; |
227 | enum adxl372_fifo_format fifo_format; |
228 | }; |
229 | |
230 | static const struct adxl372_axis_lookup adxl372_axis_lookup_table[] = { |
231 | { BIT(0), ADXL372_X_FIFO }, |
232 | { BIT(1), ADXL372_Y_FIFO }, |
233 | { BIT(2), ADXL372_Z_FIFO }, |
234 | { BIT(0) | BIT(1), ADXL372_XY_FIFO }, |
235 | { BIT(0) | BIT(2), ADXL372_XZ_FIFO }, |
236 | { BIT(1) | BIT(2), ADXL372_YZ_FIFO }, |
237 | { BIT(0) | BIT(1) | BIT(2), ADXL372_XYZ_FIFO }, |
238 | }; |
239 | |
240 | static const struct iio_event_spec adxl372_events[] = { |
241 | { |
242 | .type = IIO_EV_TYPE_THRESH, |
243 | .dir = IIO_EV_DIR_RISING, |
244 | .mask_separate = BIT(IIO_EV_INFO_VALUE), |
245 | .mask_shared_by_all = BIT(IIO_EV_INFO_PERIOD) | BIT(IIO_EV_INFO_ENABLE), |
246 | }, { |
247 | .type = IIO_EV_TYPE_THRESH, |
248 | .dir = IIO_EV_DIR_FALLING, |
249 | .mask_separate = BIT(IIO_EV_INFO_VALUE), |
250 | .mask_shared_by_all = BIT(IIO_EV_INFO_PERIOD) | BIT(IIO_EV_INFO_ENABLE), |
251 | }, |
252 | }; |
253 | |
254 | #define ADXL372_ACCEL_CHANNEL(index, reg, axis) { \ |
255 | .type = IIO_ACCEL, \ |
256 | .address = reg, \ |
257 | .modified = 1, \ |
258 | .channel2 = IIO_MOD_##axis, \ |
259 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ |
260 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ |
261 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ |
262 | BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ |
263 | .scan_index = index, \ |
264 | .scan_type = { \ |
265 | .sign = 's', \ |
266 | .realbits = 12, \ |
267 | .storagebits = 16, \ |
268 | .shift = 4, \ |
269 | .endianness = IIO_BE, \ |
270 | }, \ |
271 | .event_spec = adxl372_events, \ |
272 | .num_event_specs = ARRAY_SIZE(adxl372_events) \ |
273 | } |
274 | |
275 | static const struct iio_chan_spec adxl372_channels[] = { |
276 | ADXL372_ACCEL_CHANNEL(0, ADXL372_X_DATA_H, X), |
277 | ADXL372_ACCEL_CHANNEL(1, ADXL372_Y_DATA_H, Y), |
278 | ADXL372_ACCEL_CHANNEL(2, ADXL372_Z_DATA_H, Z), |
279 | }; |
280 | |
281 | struct adxl372_state { |
282 | int irq; |
283 | struct device *dev; |
284 | struct regmap *regmap; |
285 | struct iio_trigger *dready_trig; |
286 | struct iio_trigger *peak_datardy_trig; |
287 | enum adxl372_fifo_mode fifo_mode; |
288 | enum adxl372_fifo_format fifo_format; |
289 | unsigned int fifo_axis_mask; |
290 | enum adxl372_op_mode op_mode; |
291 | enum adxl372_act_proc_mode act_proc_mode; |
292 | enum adxl372_odr odr; |
293 | enum adxl372_bandwidth bw; |
294 | u32 act_time_ms; |
295 | u32 inact_time_ms; |
296 | u8 fifo_set_size; |
297 | unsigned long int1_bitmask; |
298 | unsigned long int2_bitmask; |
299 | u16 watermark; |
300 | __be16 fifo_buf[ADXL372_FIFO_SIZE]; |
301 | bool peak_fifo_mode_en; |
302 | struct mutex threshold_m; /* lock for threshold */ |
303 | }; |
304 | |
305 | static const unsigned long adxl372_channel_masks[] = { |
306 | BIT(0), BIT(1), BIT(2), |
307 | BIT(0) | BIT(1), |
308 | BIT(0) | BIT(2), |
309 | BIT(1) | BIT(2), |
310 | BIT(0) | BIT(1) | BIT(2), |
311 | 0 |
312 | }; |
313 | |
314 | static ssize_t adxl372_read_threshold_value(struct iio_dev *indio_dev, unsigned int addr, |
315 | u16 *threshold) |
316 | { |
317 | struct adxl372_state *st = iio_priv(indio_dev); |
318 | __be16 raw_regval; |
319 | u16 regval; |
320 | int ret; |
321 | |
322 | ret = regmap_bulk_read(map: st->regmap, reg: addr, val: &raw_regval, val_count: sizeof(raw_regval)); |
323 | if (ret < 0) |
324 | return ret; |
325 | |
326 | regval = be16_to_cpu(raw_regval); |
327 | regval >>= 5; |
328 | |
329 | *threshold = regval; |
330 | |
331 | return 0; |
332 | } |
333 | |
334 | static ssize_t adxl372_write_threshold_value(struct iio_dev *indio_dev, unsigned int addr, |
335 | u16 threshold) |
336 | { |
337 | struct adxl372_state *st = iio_priv(indio_dev); |
338 | int ret; |
339 | |
340 | mutex_lock(&st->threshold_m); |
341 | ret = regmap_write(map: st->regmap, reg: addr, ADXL372_THRESH_VAL_H_SEL(threshold)); |
342 | if (ret < 0) |
343 | goto unlock; |
344 | |
345 | ret = regmap_update_bits(map: st->regmap, reg: addr + 1, GENMASK(7, 5), |
346 | ADXL372_THRESH_VAL_L_SEL(threshold) << 5); |
347 | |
348 | unlock: |
349 | mutex_unlock(lock: &st->threshold_m); |
350 | |
351 | return ret; |
352 | } |
353 | |
354 | static int adxl372_read_axis(struct adxl372_state *st, u8 addr) |
355 | { |
356 | __be16 regval; |
357 | int ret; |
358 | |
359 | ret = regmap_bulk_read(map: st->regmap, reg: addr, val: ®val, val_count: sizeof(regval)); |
360 | if (ret < 0) |
361 | return ret; |
362 | |
363 | return be16_to_cpu(regval); |
364 | } |
365 | |
366 | static int adxl372_set_op_mode(struct adxl372_state *st, |
367 | enum adxl372_op_mode op_mode) |
368 | { |
369 | int ret; |
370 | |
371 | ret = regmap_update_bits(map: st->regmap, ADXL372_POWER_CTL, |
372 | ADXL372_POWER_CTL_MODE_MSK, |
373 | ADXL372_POWER_CTL_MODE(op_mode)); |
374 | if (ret < 0) |
375 | return ret; |
376 | |
377 | st->op_mode = op_mode; |
378 | |
379 | return ret; |
380 | } |
381 | |
382 | static int adxl372_set_odr(struct adxl372_state *st, |
383 | enum adxl372_odr odr) |
384 | { |
385 | int ret; |
386 | |
387 | ret = regmap_update_bits(map: st->regmap, ADXL372_TIMING, |
388 | ADXL372_TIMING_ODR_MSK, |
389 | ADXL372_TIMING_ODR_MODE(odr)); |
390 | if (ret < 0) |
391 | return ret; |
392 | |
393 | st->odr = odr; |
394 | |
395 | return ret; |
396 | } |
397 | |
398 | static int adxl372_find_closest_match(const int *array, |
399 | unsigned int size, int val) |
400 | { |
401 | int i; |
402 | |
403 | for (i = 0; i < size; i++) { |
404 | if (val <= array[i]) |
405 | return i; |
406 | } |
407 | |
408 | return size - 1; |
409 | } |
410 | |
411 | static int adxl372_set_bandwidth(struct adxl372_state *st, |
412 | enum adxl372_bandwidth bw) |
413 | { |
414 | int ret; |
415 | |
416 | ret = regmap_update_bits(map: st->regmap, ADXL372_MEASURE, |
417 | ADXL372_MEASURE_BANDWIDTH_MSK, |
418 | ADXL372_MEASURE_BANDWIDTH_MODE(bw)); |
419 | if (ret < 0) |
420 | return ret; |
421 | |
422 | st->bw = bw; |
423 | |
424 | return ret; |
425 | } |
426 | |
427 | static int adxl372_set_act_proc_mode(struct adxl372_state *st, |
428 | enum adxl372_act_proc_mode mode) |
429 | { |
430 | int ret; |
431 | |
432 | ret = regmap_update_bits(map: st->regmap, |
433 | ADXL372_MEASURE, |
434 | ADXL372_MEASURE_LINKLOOP_MSK, |
435 | ADXL372_MEASURE_LINKLOOP_MODE(mode)); |
436 | if (ret < 0) |
437 | return ret; |
438 | |
439 | st->act_proc_mode = mode; |
440 | |
441 | return ret; |
442 | } |
443 | |
444 | static int adxl372_set_activity_threshold(struct adxl372_state *st, |
445 | enum adxl372_th_activity act, |
446 | bool ref_en, bool enable, |
447 | unsigned int threshold) |
448 | { |
449 | unsigned char buf[6]; |
450 | unsigned char th_reg_high_val, th_reg_low_val, th_reg_high_addr; |
451 | |
452 | /* scale factor is 100 mg/code */ |
453 | th_reg_high_val = (threshold / 100) >> 3; |
454 | th_reg_low_val = ((threshold / 100) << 5) | (ref_en << 1) | enable; |
455 | th_reg_high_addr = adxl372_th_reg_high_addr[act]; |
456 | |
457 | buf[0] = th_reg_high_val; |
458 | buf[1] = th_reg_low_val; |
459 | buf[2] = th_reg_high_val; |
460 | buf[3] = th_reg_low_val; |
461 | buf[4] = th_reg_high_val; |
462 | buf[5] = th_reg_low_val; |
463 | |
464 | return regmap_bulk_write(map: st->regmap, reg: th_reg_high_addr, |
465 | val: buf, ARRAY_SIZE(buf)); |
466 | } |
467 | |
468 | static int adxl372_set_activity_time_ms(struct adxl372_state *st, |
469 | unsigned int act_time_ms) |
470 | { |
471 | unsigned int reg_val, scale_factor; |
472 | int ret; |
473 | |
474 | /* |
475 | * 3.3 ms per code is the scale factor of the TIME_ACT register for |
476 | * ODR = 6400 Hz. It is 6.6 ms per code for ODR = 3200 Hz and below. |
477 | */ |
478 | if (st->odr == ADXL372_ODR_6400HZ) |
479 | scale_factor = 3300; |
480 | else |
481 | scale_factor = 6600; |
482 | |
483 | reg_val = DIV_ROUND_CLOSEST(act_time_ms * 1000, scale_factor); |
484 | |
485 | /* TIME_ACT register is 8 bits wide */ |
486 | if (reg_val > 0xFF) |
487 | reg_val = 0xFF; |
488 | |
489 | ret = regmap_write(map: st->regmap, ADXL372_TIME_ACT, val: reg_val); |
490 | if (ret < 0) |
491 | return ret; |
492 | |
493 | st->act_time_ms = act_time_ms; |
494 | |
495 | return ret; |
496 | } |
497 | |
498 | static int adxl372_set_inactivity_time_ms(struct adxl372_state *st, |
499 | unsigned int inact_time_ms) |
500 | { |
501 | unsigned int reg_val_h, reg_val_l, res, scale_factor; |
502 | int ret; |
503 | |
504 | /* |
505 | * 13 ms per code is the scale factor of the TIME_INACT register for |
506 | * ODR = 6400 Hz. It is 26 ms per code for ODR = 3200 Hz and below. |
507 | */ |
508 | if (st->odr == ADXL372_ODR_6400HZ) |
509 | scale_factor = 13; |
510 | else |
511 | scale_factor = 26; |
512 | |
513 | res = DIV_ROUND_CLOSEST(inact_time_ms, scale_factor); |
514 | reg_val_h = (res >> 8) & 0xFF; |
515 | reg_val_l = res & 0xFF; |
516 | |
517 | ret = regmap_write(map: st->regmap, ADXL372_TIME_INACT_H, val: reg_val_h); |
518 | if (ret < 0) |
519 | return ret; |
520 | |
521 | ret = regmap_write(map: st->regmap, ADXL372_TIME_INACT_L, val: reg_val_l); |
522 | if (ret < 0) |
523 | return ret; |
524 | |
525 | st->inact_time_ms = inact_time_ms; |
526 | |
527 | return ret; |
528 | } |
529 | |
530 | static int adxl372_set_interrupts(struct adxl372_state *st, |
531 | unsigned long int1_bitmask, |
532 | unsigned long int2_bitmask) |
533 | { |
534 | int ret; |
535 | |
536 | ret = regmap_write(map: st->regmap, ADXL372_INT1_MAP, val: int1_bitmask); |
537 | if (ret < 0) |
538 | return ret; |
539 | |
540 | return regmap_write(map: st->regmap, ADXL372_INT2_MAP, val: int2_bitmask); |
541 | } |
542 | |
543 | static int adxl372_configure_fifo(struct adxl372_state *st) |
544 | { |
545 | unsigned int fifo_samples, fifo_ctl; |
546 | int ret; |
547 | |
548 | /* FIFO must be configured while in standby mode */ |
549 | ret = adxl372_set_op_mode(st, op_mode: ADXL372_STANDBY); |
550 | if (ret < 0) |
551 | return ret; |
552 | |
553 | /* |
554 | * watermark stores the number of sets; we need to write the FIFO |
555 | * registers with the number of samples |
556 | */ |
557 | fifo_samples = (st->watermark * st->fifo_set_size); |
558 | fifo_ctl = ADXL372_FIFO_CTL_FORMAT_MODE(st->fifo_format) | |
559 | ADXL372_FIFO_CTL_MODE_MODE(st->fifo_mode) | |
560 | ADXL372_FIFO_CTL_SAMPLES_MODE(fifo_samples); |
561 | |
562 | ret = regmap_write(map: st->regmap, |
563 | ADXL372_FIFO_SAMPLES, val: fifo_samples & 0xFF); |
564 | if (ret < 0) |
565 | return ret; |
566 | |
567 | ret = regmap_write(map: st->regmap, ADXL372_FIFO_CTL, val: fifo_ctl); |
568 | if (ret < 0) |
569 | return ret; |
570 | |
571 | return adxl372_set_op_mode(st, op_mode: ADXL372_FULL_BW_MEASUREMENT); |
572 | } |
573 | |
574 | static int adxl372_get_status(struct adxl372_state *st, |
575 | u8 *status1, u8 *status2, |
576 | u16 *fifo_entries) |
577 | { |
578 | __be32 buf; |
579 | u32 val; |
580 | int ret; |
581 | |
582 | /* STATUS1, STATUS2, FIFO_ENTRIES2 and FIFO_ENTRIES are adjacent regs */ |
583 | ret = regmap_bulk_read(map: st->regmap, ADXL372_STATUS_1, |
584 | val: &buf, val_count: sizeof(buf)); |
585 | if (ret < 0) |
586 | return ret; |
587 | |
588 | val = be32_to_cpu(buf); |
589 | |
590 | *status1 = (val >> 24) & 0x0F; |
591 | *status2 = (val >> 16) & 0x0F; |
592 | /* |
593 | * FIFO_ENTRIES contains the least significant byte, and FIFO_ENTRIES2 |
594 | * contains the two most significant bits |
595 | */ |
596 | *fifo_entries = val & 0x3FF; |
597 | |
598 | return ret; |
599 | } |
600 | |
601 | static void adxl372_arrange_axis_data(struct adxl372_state *st, __be16 *sample) |
602 | { |
603 | __be16 axis_sample[3]; |
604 | int i = 0; |
605 | |
606 | memset(axis_sample, 0, 3 * sizeof(__be16)); |
607 | if (ADXL372_X_AXIS_EN(st->fifo_axis_mask)) |
608 | axis_sample[i++] = sample[0]; |
609 | if (ADXL372_Y_AXIS_EN(st->fifo_axis_mask)) |
610 | axis_sample[i++] = sample[1]; |
611 | if (ADXL372_Z_AXIS_EN(st->fifo_axis_mask)) |
612 | axis_sample[i++] = sample[2]; |
613 | |
614 | memcpy(sample, axis_sample, 3 * sizeof(__be16)); |
615 | } |
616 | |
617 | static void adxl372_push_event(struct iio_dev *indio_dev, s64 timestamp, u8 status2) |
618 | { |
619 | unsigned int ev_dir = IIO_EV_DIR_NONE; |
620 | |
621 | if (ADXL372_STATUS_2_ACT(status2)) |
622 | ev_dir = IIO_EV_DIR_RISING; |
623 | |
624 | if (ADXL372_STATUS_2_INACT(status2)) |
625 | ev_dir = IIO_EV_DIR_FALLING; |
626 | |
627 | if (ev_dir != IIO_EV_DIR_NONE) |
628 | iio_push_event(indio_dev, |
629 | IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z, |
630 | IIO_EV_TYPE_THRESH, ev_dir), |
631 | timestamp); |
632 | } |
633 | |
634 | static irqreturn_t adxl372_trigger_handler(int irq, void *p) |
635 | { |
636 | struct iio_poll_func *pf = p; |
637 | struct iio_dev *indio_dev = pf->indio_dev; |
638 | struct adxl372_state *st = iio_priv(indio_dev); |
639 | u8 status1, status2; |
640 | u16 fifo_entries; |
641 | int i, ret; |
642 | |
643 | ret = adxl372_get_status(st, status1: &status1, status2: &status2, fifo_entries: &fifo_entries); |
644 | if (ret < 0) |
645 | goto err; |
646 | |
647 | adxl372_push_event(indio_dev, timestamp: iio_get_time_ns(indio_dev), status2); |
648 | |
649 | if (st->fifo_mode != ADXL372_FIFO_BYPASSED && |
650 | ADXL372_STATUS_1_FIFO_FULL(status1)) { |
651 | /* |
652 | * When reading data from multiple axes from the FIFO, |
653 | * to ensure that data is not overwritten and stored out |
654 | * of order at least one sample set must be left in the |
655 | * FIFO after every read. |
656 | */ |
657 | fifo_entries -= st->fifo_set_size; |
658 | |
659 | /* Read data from the FIFO */ |
660 | ret = regmap_noinc_read(map: st->regmap, ADXL372_FIFO_DATA, |
661 | val: st->fifo_buf, |
662 | val_len: fifo_entries * sizeof(u16)); |
663 | if (ret < 0) |
664 | goto err; |
665 | |
666 | /* Each sample is 2 bytes */ |
667 | for (i = 0; i < fifo_entries; i += st->fifo_set_size) { |
668 | /* filter peak detection data */ |
669 | if (st->peak_fifo_mode_en) |
670 | adxl372_arrange_axis_data(st, sample: &st->fifo_buf[i]); |
671 | iio_push_to_buffers(indio_dev, data: &st->fifo_buf[i]); |
672 | } |
673 | } |
674 | err: |
675 | iio_trigger_notify_done(trig: indio_dev->trig); |
676 | return IRQ_HANDLED; |
677 | } |
678 | |
679 | static int adxl372_setup(struct adxl372_state *st) |
680 | { |
681 | unsigned int regval; |
682 | int ret; |
683 | |
684 | ret = regmap_read(map: st->regmap, ADXL372_DEVID, val: ®val); |
685 | if (ret < 0) |
686 | return ret; |
687 | |
688 | if (regval != ADXL372_DEVID_VAL) { |
689 | dev_err(st->dev, "Invalid chip id %x\n" , regval); |
690 | return -ENODEV; |
691 | } |
692 | |
693 | /* |
694 | * Perform a software reset to make sure the device is in a consistent |
695 | * state after start up. |
696 | */ |
697 | ret = regmap_write(map: st->regmap, ADXL372_RESET, ADXL372_RESET_CODE); |
698 | if (ret < 0) |
699 | return ret; |
700 | |
701 | ret = adxl372_set_op_mode(st, op_mode: ADXL372_STANDBY); |
702 | if (ret < 0) |
703 | return ret; |
704 | |
705 | /* Set threshold for activity detection to 1g */ |
706 | ret = adxl372_set_activity_threshold(st, act: ADXL372_ACTIVITY, |
707 | ref_en: true, enable: true, threshold: 1000); |
708 | if (ret < 0) |
709 | return ret; |
710 | |
711 | /* Set threshold for inactivity detection to 100mg */ |
712 | ret = adxl372_set_activity_threshold(st, act: ADXL372_INACTIVITY, |
713 | ref_en: true, enable: true, threshold: 100); |
714 | if (ret < 0) |
715 | return ret; |
716 | |
717 | /* Set activity processing in Looped mode */ |
718 | ret = adxl372_set_act_proc_mode(st, mode: ADXL372_LOOPED); |
719 | if (ret < 0) |
720 | return ret; |
721 | |
722 | ret = adxl372_set_odr(st, odr: ADXL372_ODR_6400HZ); |
723 | if (ret < 0) |
724 | return ret; |
725 | |
726 | ret = adxl372_set_bandwidth(st, bw: ADXL372_BW_3200HZ); |
727 | if (ret < 0) |
728 | return ret; |
729 | |
730 | /* Set activity timer to 1ms */ |
731 | ret = adxl372_set_activity_time_ms(st, act_time_ms: 1); |
732 | if (ret < 0) |
733 | return ret; |
734 | |
735 | /* Set inactivity timer to 10s */ |
736 | ret = adxl372_set_inactivity_time_ms(st, inact_time_ms: 10000); |
737 | if (ret < 0) |
738 | return ret; |
739 | |
740 | /* Set the mode of operation to full bandwidth measurement mode */ |
741 | return adxl372_set_op_mode(st, op_mode: ADXL372_FULL_BW_MEASUREMENT); |
742 | } |
743 | |
744 | static int adxl372_reg_access(struct iio_dev *indio_dev, |
745 | unsigned int reg, |
746 | unsigned int writeval, |
747 | unsigned int *readval) |
748 | { |
749 | struct adxl372_state *st = iio_priv(indio_dev); |
750 | |
751 | if (readval) |
752 | return regmap_read(map: st->regmap, reg, val: readval); |
753 | else |
754 | return regmap_write(map: st->regmap, reg, val: writeval); |
755 | } |
756 | |
757 | static int adxl372_read_raw(struct iio_dev *indio_dev, |
758 | struct iio_chan_spec const *chan, |
759 | int *val, int *val2, long info) |
760 | { |
761 | struct adxl372_state *st = iio_priv(indio_dev); |
762 | int ret; |
763 | |
764 | switch (info) { |
765 | case IIO_CHAN_INFO_RAW: |
766 | ret = iio_device_claim_direct_mode(indio_dev); |
767 | if (ret) |
768 | return ret; |
769 | |
770 | ret = adxl372_read_axis(st, addr: chan->address); |
771 | iio_device_release_direct_mode(indio_dev); |
772 | if (ret < 0) |
773 | return ret; |
774 | |
775 | *val = sign_extend32(value: ret >> chan->scan_type.shift, |
776 | index: chan->scan_type.realbits - 1); |
777 | return IIO_VAL_INT; |
778 | case IIO_CHAN_INFO_SCALE: |
779 | *val = 0; |
780 | *val2 = ADXL372_USCALE; |
781 | return IIO_VAL_INT_PLUS_MICRO; |
782 | case IIO_CHAN_INFO_SAMP_FREQ: |
783 | *val = adxl372_samp_freq_tbl[st->odr]; |
784 | return IIO_VAL_INT; |
785 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: |
786 | *val = adxl372_bw_freq_tbl[st->bw]; |
787 | return IIO_VAL_INT; |
788 | } |
789 | |
790 | return -EINVAL; |
791 | } |
792 | |
793 | static int adxl372_write_raw(struct iio_dev *indio_dev, |
794 | struct iio_chan_spec const *chan, |
795 | int val, int val2, long info) |
796 | { |
797 | struct adxl372_state *st = iio_priv(indio_dev); |
798 | int odr_index, bw_index, ret; |
799 | |
800 | switch (info) { |
801 | case IIO_CHAN_INFO_SAMP_FREQ: |
802 | odr_index = adxl372_find_closest_match(array: adxl372_samp_freq_tbl, |
803 | ARRAY_SIZE(adxl372_samp_freq_tbl), |
804 | val); |
805 | ret = adxl372_set_odr(st, odr: odr_index); |
806 | if (ret < 0) |
807 | return ret; |
808 | /* |
809 | * The timer period depends on the ODR selected. |
810 | * At 3200 Hz and below, it is 6.6 ms; at 6400 Hz, it is 3.3 ms |
811 | */ |
812 | ret = adxl372_set_activity_time_ms(st, act_time_ms: st->act_time_ms); |
813 | if (ret < 0) |
814 | return ret; |
815 | /* |
816 | * The timer period depends on the ODR selected. |
817 | * At 3200 Hz and below, it is 26 ms; at 6400 Hz, it is 13 ms |
818 | */ |
819 | ret = adxl372_set_inactivity_time_ms(st, inact_time_ms: st->inact_time_ms); |
820 | if (ret < 0) |
821 | return ret; |
822 | /* |
823 | * The maximum bandwidth is constrained to at most half of |
824 | * the ODR to ensure that the Nyquist criteria is not violated |
825 | */ |
826 | if (st->bw > odr_index) |
827 | ret = adxl372_set_bandwidth(st, bw: odr_index); |
828 | |
829 | return ret; |
830 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: |
831 | bw_index = adxl372_find_closest_match(array: adxl372_bw_freq_tbl, |
832 | ARRAY_SIZE(adxl372_bw_freq_tbl), |
833 | val); |
834 | return adxl372_set_bandwidth(st, bw: bw_index); |
835 | default: |
836 | return -EINVAL; |
837 | } |
838 | } |
839 | |
840 | static int adxl372_read_event_value(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, |
841 | enum iio_event_type type, enum iio_event_direction dir, |
842 | enum iio_event_info info, int *val, int *val2) |
843 | { |
844 | struct adxl372_state *st = iio_priv(indio_dev); |
845 | unsigned int addr; |
846 | u16 raw_value; |
847 | int ret; |
848 | |
849 | switch (info) { |
850 | case IIO_EV_INFO_VALUE: |
851 | switch (dir) { |
852 | case IIO_EV_DIR_RISING: |
853 | addr = ADXL372_X_THRESH_ACT_H + 2 * chan->scan_index; |
854 | ret = adxl372_read_threshold_value(indio_dev, addr, threshold: &raw_value); |
855 | if (ret < 0) |
856 | return ret; |
857 | *val = raw_value * ADXL372_USCALE; |
858 | *val2 = 1000000; |
859 | return IIO_VAL_FRACTIONAL; |
860 | case IIO_EV_DIR_FALLING: |
861 | addr = ADXL372_X_THRESH_INACT_H + 2 * chan->scan_index; |
862 | ret = adxl372_read_threshold_value(indio_dev, addr, threshold: &raw_value); |
863 | if (ret < 0) |
864 | return ret; |
865 | *val = raw_value * ADXL372_USCALE; |
866 | *val2 = 1000000; |
867 | return IIO_VAL_FRACTIONAL; |
868 | default: |
869 | return -EINVAL; |
870 | } |
871 | case IIO_EV_INFO_PERIOD: |
872 | switch (dir) { |
873 | case IIO_EV_DIR_RISING: |
874 | *val = st->act_time_ms; |
875 | *val2 = 1000; |
876 | return IIO_VAL_FRACTIONAL; |
877 | case IIO_EV_DIR_FALLING: |
878 | *val = st->inact_time_ms; |
879 | *val2 = 1000; |
880 | return IIO_VAL_FRACTIONAL; |
881 | default: |
882 | return -EINVAL; |
883 | } |
884 | default: |
885 | return -EINVAL; |
886 | } |
887 | } |
888 | |
889 | static int adxl372_write_event_value(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, |
890 | enum iio_event_type type, enum iio_event_direction dir, |
891 | enum iio_event_info info, int val, int val2) |
892 | { |
893 | struct adxl372_state *st = iio_priv(indio_dev); |
894 | unsigned int val_ms; |
895 | unsigned int addr; |
896 | u16 raw_val; |
897 | |
898 | switch (info) { |
899 | case IIO_EV_INFO_VALUE: |
900 | raw_val = DIV_ROUND_UP(val * 1000000, ADXL372_USCALE); |
901 | switch (dir) { |
902 | case IIO_EV_DIR_RISING: |
903 | addr = ADXL372_X_THRESH_ACT_H + 2 * chan->scan_index; |
904 | return adxl372_write_threshold_value(indio_dev, addr, threshold: raw_val); |
905 | case IIO_EV_DIR_FALLING: |
906 | addr = ADXL372_X_THRESH_INACT_H + 2 * chan->scan_index; |
907 | return adxl372_write_threshold_value(indio_dev, addr, threshold: raw_val); |
908 | default: |
909 | return -EINVAL; |
910 | } |
911 | case IIO_EV_INFO_PERIOD: |
912 | val_ms = val * 1000 + DIV_ROUND_UP(val2, 1000); |
913 | switch (dir) { |
914 | case IIO_EV_DIR_RISING: |
915 | return adxl372_set_activity_time_ms(st, act_time_ms: val_ms); |
916 | case IIO_EV_DIR_FALLING: |
917 | return adxl372_set_inactivity_time_ms(st, inact_time_ms: val_ms); |
918 | default: |
919 | return -EINVAL; |
920 | } |
921 | default: |
922 | return -EINVAL; |
923 | } |
924 | } |
925 | |
926 | static int adxl372_read_event_config(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, |
927 | enum iio_event_type type, enum iio_event_direction dir) |
928 | { |
929 | struct adxl372_state *st = iio_priv(indio_dev); |
930 | |
931 | switch (dir) { |
932 | case IIO_EV_DIR_RISING: |
933 | return FIELD_GET(ADXL372_INT1_MAP_ACT_MSK, st->int1_bitmask); |
934 | case IIO_EV_DIR_FALLING: |
935 | return FIELD_GET(ADXL372_INT1_MAP_INACT_MSK, st->int1_bitmask); |
936 | default: |
937 | return -EINVAL; |
938 | } |
939 | } |
940 | |
941 | static int adxl372_write_event_config(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, |
942 | enum iio_event_type type, enum iio_event_direction dir, |
943 | int state) |
944 | { |
945 | struct adxl372_state *st = iio_priv(indio_dev); |
946 | |
947 | switch (dir) { |
948 | case IIO_EV_DIR_RISING: |
949 | set_mask_bits(&st->int1_bitmask, ADXL372_INT1_MAP_ACT_MSK, |
950 | ADXL372_INT1_MAP_ACT_MODE(state)); |
951 | break; |
952 | case IIO_EV_DIR_FALLING: |
953 | set_mask_bits(&st->int1_bitmask, ADXL372_INT1_MAP_INACT_MSK, |
954 | ADXL372_INT1_MAP_INACT_MODE(state)); |
955 | break; |
956 | default: |
957 | return -EINVAL; |
958 | } |
959 | |
960 | return adxl372_set_interrupts(st, int1_bitmask: st->int1_bitmask, int2_bitmask: 0); |
961 | } |
962 | |
963 | static ssize_t adxl372_show_filter_freq_avail(struct device *dev, |
964 | struct device_attribute *attr, |
965 | char *buf) |
966 | { |
967 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
968 | struct adxl372_state *st = iio_priv(indio_dev); |
969 | int i; |
970 | size_t len = 0; |
971 | |
972 | for (i = 0; i <= st->odr; i++) |
973 | len += scnprintf(buf: buf + len, PAGE_SIZE - len, |
974 | fmt: "%d " , adxl372_bw_freq_tbl[i]); |
975 | |
976 | buf[len - 1] = '\n'; |
977 | |
978 | return len; |
979 | } |
980 | |
981 | static ssize_t adxl372_get_fifo_enabled(struct device *dev, |
982 | struct device_attribute *attr, |
983 | char *buf) |
984 | { |
985 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
986 | struct adxl372_state *st = iio_priv(indio_dev); |
987 | |
988 | return sprintf(buf, fmt: "%d\n" , st->fifo_mode); |
989 | } |
990 | |
991 | static ssize_t adxl372_get_fifo_watermark(struct device *dev, |
992 | struct device_attribute *attr, |
993 | char *buf) |
994 | { |
995 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
996 | struct adxl372_state *st = iio_priv(indio_dev); |
997 | |
998 | return sprintf(buf, fmt: "%d\n" , st->watermark); |
999 | } |
1000 | |
1001 | IIO_STATIC_CONST_DEVICE_ATTR(hwfifo_watermark_min, "1" ); |
1002 | IIO_STATIC_CONST_DEVICE_ATTR(hwfifo_watermark_max, |
1003 | __stringify(ADXL372_FIFO_SIZE)); |
1004 | static IIO_DEVICE_ATTR(hwfifo_watermark, 0444, |
1005 | adxl372_get_fifo_watermark, NULL, 0); |
1006 | static IIO_DEVICE_ATTR(hwfifo_enabled, 0444, |
1007 | adxl372_get_fifo_enabled, NULL, 0); |
1008 | |
1009 | static const struct iio_dev_attr *adxl372_fifo_attributes[] = { |
1010 | &iio_dev_attr_hwfifo_watermark_min, |
1011 | &iio_dev_attr_hwfifo_watermark_max, |
1012 | &iio_dev_attr_hwfifo_watermark, |
1013 | &iio_dev_attr_hwfifo_enabled, |
1014 | NULL, |
1015 | }; |
1016 | |
1017 | static int adxl372_set_watermark(struct iio_dev *indio_dev, unsigned int val) |
1018 | { |
1019 | struct adxl372_state *st = iio_priv(indio_dev); |
1020 | |
1021 | if (val > ADXL372_FIFO_SIZE) |
1022 | val = ADXL372_FIFO_SIZE; |
1023 | |
1024 | st->watermark = val; |
1025 | |
1026 | return 0; |
1027 | } |
1028 | |
1029 | static int adxl372_buffer_postenable(struct iio_dev *indio_dev) |
1030 | { |
1031 | struct adxl372_state *st = iio_priv(indio_dev); |
1032 | unsigned int mask; |
1033 | int i, ret; |
1034 | |
1035 | st->int1_bitmask |= ADXL372_INT1_MAP_FIFO_FULL_MSK; |
1036 | ret = adxl372_set_interrupts(st, int1_bitmask: st->int1_bitmask, int2_bitmask: 0); |
1037 | if (ret < 0) |
1038 | return ret; |
1039 | |
1040 | mask = *indio_dev->active_scan_mask; |
1041 | |
1042 | for (i = 0; i < ARRAY_SIZE(adxl372_axis_lookup_table); i++) { |
1043 | if (mask == adxl372_axis_lookup_table[i].bits) |
1044 | break; |
1045 | } |
1046 | |
1047 | if (i == ARRAY_SIZE(adxl372_axis_lookup_table)) |
1048 | return -EINVAL; |
1049 | |
1050 | st->fifo_format = adxl372_axis_lookup_table[i].fifo_format; |
1051 | st->fifo_axis_mask = adxl372_axis_lookup_table[i].bits; |
1052 | st->fifo_set_size = bitmap_weight(src: indio_dev->active_scan_mask, |
1053 | nbits: indio_dev->masklength); |
1054 | |
1055 | /* Configure the FIFO to store sets of impact event peak. */ |
1056 | if (st->peak_fifo_mode_en) { |
1057 | st->fifo_set_size = 3; |
1058 | st->fifo_format = ADXL372_XYZ_PEAK_FIFO; |
1059 | } |
1060 | |
1061 | /* |
1062 | * The 512 FIFO samples can be allotted in several ways, such as: |
1063 | * 170 sample sets of concurrent 3-axis data |
1064 | * 256 sample sets of concurrent 2-axis data (user selectable) |
1065 | * 512 sample sets of single-axis data |
1066 | * 170 sets of impact event peak (x, y, z) |
1067 | */ |
1068 | if ((st->watermark * st->fifo_set_size) > ADXL372_FIFO_SIZE) |
1069 | st->watermark = (ADXL372_FIFO_SIZE / st->fifo_set_size); |
1070 | |
1071 | st->fifo_mode = ADXL372_FIFO_STREAMED; |
1072 | |
1073 | ret = adxl372_configure_fifo(st); |
1074 | if (ret < 0) { |
1075 | st->fifo_mode = ADXL372_FIFO_BYPASSED; |
1076 | st->int1_bitmask &= ~ADXL372_INT1_MAP_FIFO_FULL_MSK; |
1077 | adxl372_set_interrupts(st, int1_bitmask: st->int1_bitmask, int2_bitmask: 0); |
1078 | return ret; |
1079 | } |
1080 | |
1081 | return 0; |
1082 | } |
1083 | |
1084 | static int adxl372_buffer_predisable(struct iio_dev *indio_dev) |
1085 | { |
1086 | struct adxl372_state *st = iio_priv(indio_dev); |
1087 | |
1088 | st->int1_bitmask &= ~ADXL372_INT1_MAP_FIFO_FULL_MSK; |
1089 | adxl372_set_interrupts(st, int1_bitmask: st->int1_bitmask, int2_bitmask: 0); |
1090 | st->fifo_mode = ADXL372_FIFO_BYPASSED; |
1091 | adxl372_configure_fifo(st); |
1092 | |
1093 | return 0; |
1094 | } |
1095 | |
1096 | static const struct iio_buffer_setup_ops adxl372_buffer_ops = { |
1097 | .postenable = adxl372_buffer_postenable, |
1098 | .predisable = adxl372_buffer_predisable, |
1099 | }; |
1100 | |
1101 | static int adxl372_dready_trig_set_state(struct iio_trigger *trig, |
1102 | bool state) |
1103 | { |
1104 | struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); |
1105 | struct adxl372_state *st = iio_priv(indio_dev); |
1106 | |
1107 | if (state) |
1108 | st->int1_bitmask |= ADXL372_INT1_MAP_FIFO_FULL_MSK; |
1109 | |
1110 | return adxl372_set_interrupts(st, int1_bitmask: st->int1_bitmask, int2_bitmask: 0); |
1111 | } |
1112 | |
1113 | static int adxl372_validate_trigger(struct iio_dev *indio_dev, |
1114 | struct iio_trigger *trig) |
1115 | { |
1116 | struct adxl372_state *st = iio_priv(indio_dev); |
1117 | |
1118 | if (st->dready_trig != trig && st->peak_datardy_trig != trig) |
1119 | return -EINVAL; |
1120 | |
1121 | return 0; |
1122 | } |
1123 | |
1124 | static const struct iio_trigger_ops adxl372_trigger_ops = { |
1125 | .validate_device = &iio_trigger_validate_own_device, |
1126 | .set_trigger_state = adxl372_dready_trig_set_state, |
1127 | }; |
1128 | |
1129 | static int adxl372_peak_dready_trig_set_state(struct iio_trigger *trig, |
1130 | bool state) |
1131 | { |
1132 | struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); |
1133 | struct adxl372_state *st = iio_priv(indio_dev); |
1134 | |
1135 | if (state) |
1136 | st->int1_bitmask |= ADXL372_INT1_MAP_FIFO_FULL_MSK; |
1137 | |
1138 | st->peak_fifo_mode_en = state; |
1139 | |
1140 | return adxl372_set_interrupts(st, int1_bitmask: st->int1_bitmask, int2_bitmask: 0); |
1141 | } |
1142 | |
1143 | static const struct iio_trigger_ops adxl372_peak_data_trigger_ops = { |
1144 | .validate_device = &iio_trigger_validate_own_device, |
1145 | .set_trigger_state = adxl372_peak_dready_trig_set_state, |
1146 | }; |
1147 | |
1148 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("400 800 1600 3200 6400" ); |
1149 | static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available, |
1150 | 0444, adxl372_show_filter_freq_avail, NULL, 0); |
1151 | |
1152 | static struct attribute *adxl372_attributes[] = { |
1153 | &iio_const_attr_sampling_frequency_available.dev_attr.attr, |
1154 | &iio_dev_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr, |
1155 | NULL, |
1156 | }; |
1157 | |
1158 | static const struct attribute_group adxl372_attrs_group = { |
1159 | .attrs = adxl372_attributes, |
1160 | }; |
1161 | |
1162 | static const struct iio_info adxl372_info = { |
1163 | .validate_trigger = &adxl372_validate_trigger, |
1164 | .attrs = &adxl372_attrs_group, |
1165 | .read_raw = adxl372_read_raw, |
1166 | .write_raw = adxl372_write_raw, |
1167 | .read_event_config = adxl372_read_event_config, |
1168 | .write_event_config = adxl372_write_event_config, |
1169 | .read_event_value = adxl372_read_event_value, |
1170 | .write_event_value = adxl372_write_event_value, |
1171 | .debugfs_reg_access = &adxl372_reg_access, |
1172 | .hwfifo_set_watermark = adxl372_set_watermark, |
1173 | }; |
1174 | |
1175 | bool adxl372_readable_noinc_reg(struct device *dev, unsigned int reg) |
1176 | { |
1177 | return (reg == ADXL372_FIFO_DATA); |
1178 | } |
1179 | EXPORT_SYMBOL_NS_GPL(adxl372_readable_noinc_reg, IIO_ADXL372); |
1180 | |
1181 | int adxl372_probe(struct device *dev, struct regmap *regmap, |
1182 | int irq, const char *name) |
1183 | { |
1184 | struct iio_dev *indio_dev; |
1185 | struct adxl372_state *st; |
1186 | int ret; |
1187 | |
1188 | indio_dev = devm_iio_device_alloc(parent: dev, sizeof_priv: sizeof(*st)); |
1189 | if (!indio_dev) |
1190 | return -ENOMEM; |
1191 | |
1192 | st = iio_priv(indio_dev); |
1193 | dev_set_drvdata(dev, data: indio_dev); |
1194 | |
1195 | st->dev = dev; |
1196 | st->regmap = regmap; |
1197 | st->irq = irq; |
1198 | |
1199 | mutex_init(&st->threshold_m); |
1200 | |
1201 | indio_dev->channels = adxl372_channels; |
1202 | indio_dev->num_channels = ARRAY_SIZE(adxl372_channels); |
1203 | indio_dev->available_scan_masks = adxl372_channel_masks; |
1204 | indio_dev->name = name; |
1205 | indio_dev->info = &adxl372_info; |
1206 | indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; |
1207 | |
1208 | ret = adxl372_setup(st); |
1209 | if (ret < 0) { |
1210 | dev_err(dev, "ADXL372 setup failed\n" ); |
1211 | return ret; |
1212 | } |
1213 | |
1214 | ret = devm_iio_triggered_buffer_setup_ext(dev, |
1215 | indio_dev, NULL, |
1216 | thread: adxl372_trigger_handler, |
1217 | direction: IIO_BUFFER_DIRECTION_IN, |
1218 | ops: &adxl372_buffer_ops, |
1219 | buffer_attrs: adxl372_fifo_attributes); |
1220 | if (ret < 0) |
1221 | return ret; |
1222 | |
1223 | if (st->irq) { |
1224 | st->dready_trig = devm_iio_trigger_alloc(dev, |
1225 | "%s-dev%d" , |
1226 | indio_dev->name, |
1227 | iio_device_id(indio_dev)); |
1228 | if (st->dready_trig == NULL) |
1229 | return -ENOMEM; |
1230 | |
1231 | st->peak_datardy_trig = devm_iio_trigger_alloc(dev, |
1232 | "%s-dev%d-peak" , |
1233 | indio_dev->name, |
1234 | iio_device_id(indio_dev)); |
1235 | if (!st->peak_datardy_trig) |
1236 | return -ENOMEM; |
1237 | |
1238 | st->dready_trig->ops = &adxl372_trigger_ops; |
1239 | st->peak_datardy_trig->ops = &adxl372_peak_data_trigger_ops; |
1240 | iio_trigger_set_drvdata(trig: st->dready_trig, data: indio_dev); |
1241 | iio_trigger_set_drvdata(trig: st->peak_datardy_trig, data: indio_dev); |
1242 | ret = devm_iio_trigger_register(dev, trig_info: st->dready_trig); |
1243 | if (ret < 0) |
1244 | return ret; |
1245 | |
1246 | ret = devm_iio_trigger_register(dev, trig_info: st->peak_datardy_trig); |
1247 | if (ret < 0) |
1248 | return ret; |
1249 | |
1250 | indio_dev->trig = iio_trigger_get(trig: st->dready_trig); |
1251 | |
1252 | ret = devm_request_threaded_irq(dev, irq: st->irq, |
1253 | handler: iio_trigger_generic_data_rdy_poll, |
1254 | NULL, |
1255 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, |
1256 | devname: indio_dev->name, dev_id: st->dready_trig); |
1257 | if (ret < 0) |
1258 | return ret; |
1259 | } |
1260 | |
1261 | return devm_iio_device_register(dev, indio_dev); |
1262 | } |
1263 | EXPORT_SYMBOL_NS_GPL(adxl372_probe, IIO_ADXL372); |
1264 | |
1265 | MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>" ); |
1266 | MODULE_DESCRIPTION("Analog Devices ADXL372 3-axis accelerometer driver" ); |
1267 | MODULE_LICENSE("GPL" ); |
1268 | |