1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * Copyright (C) 2021 Analog Devices, Inc. |
4 | * Author: Cosmin Tanislav <cosmin.tanislav@analog.com> |
5 | */ |
6 | |
7 | #include <linux/bitfield.h> |
8 | #include <linux/bitops.h> |
9 | #include <linux/iio/buffer.h> |
10 | #include <linux/iio/events.h> |
11 | #include <linux/iio/iio.h> |
12 | #include <linux/iio/kfifo_buf.h> |
13 | #include <linux/iio/sysfs.h> |
14 | #include <linux/interrupt.h> |
15 | #include <linux/irq.h> |
16 | #include <linux/mod_devicetable.h> |
17 | #include <linux/regmap.h> |
18 | #include <linux/regulator/consumer.h> |
19 | #include <asm/unaligned.h> |
20 | |
21 | #include "adxl367.h" |
22 | |
23 | #define ADXL367_REG_DEVID 0x00 |
24 | #define ADXL367_DEVID_AD 0xAD |
25 | |
26 | #define ADXL367_REG_STATUS 0x0B |
27 | #define ADXL367_STATUS_INACT_MASK BIT(5) |
28 | #define ADXL367_STATUS_ACT_MASK BIT(4) |
29 | #define ADXL367_STATUS_FIFO_FULL_MASK BIT(2) |
30 | |
31 | #define ADXL367_FIFO_ENT_H_MASK GENMASK(1, 0) |
32 | |
33 | #define ADXL367_REG_X_DATA_H 0x0E |
34 | #define ADXL367_REG_Y_DATA_H 0x10 |
35 | #define ADXL367_REG_Z_DATA_H 0x12 |
36 | #define ADXL367_REG_TEMP_DATA_H 0x14 |
37 | #define ADXL367_REG_EX_ADC_DATA_H 0x16 |
38 | #define ADXL367_DATA_MASK GENMASK(15, 2) |
39 | |
40 | #define ADXL367_TEMP_25C 165 |
41 | #define ADXL367_TEMP_PER_C 54 |
42 | |
43 | #define ADXL367_VOLTAGE_OFFSET 8192 |
44 | #define ADXL367_VOLTAGE_MAX_MV 1000 |
45 | #define ADXL367_VOLTAGE_MAX_RAW GENMASK(13, 0) |
46 | |
47 | #define ADXL367_REG_RESET 0x1F |
48 | #define ADXL367_RESET_CODE 0x52 |
49 | |
50 | #define ADXL367_REG_THRESH_ACT_H 0x20 |
51 | #define ADXL367_REG_THRESH_INACT_H 0x23 |
52 | #define ADXL367_THRESH_MAX GENMASK(12, 0) |
53 | #define ADXL367_THRESH_VAL_H_MASK GENMASK(12, 6) |
54 | #define ADXL367_THRESH_H_MASK GENMASK(6, 0) |
55 | #define ADXL367_THRESH_VAL_L_MASK GENMASK(5, 0) |
56 | #define ADXL367_THRESH_L_MASK GENMASK(7, 2) |
57 | |
58 | #define ADXL367_REG_TIME_ACT 0x22 |
59 | #define ADXL367_REG_TIME_INACT_H 0x25 |
60 | #define ADXL367_TIME_ACT_MAX GENMASK(7, 0) |
61 | #define ADXL367_TIME_INACT_MAX GENMASK(15, 0) |
62 | #define ADXL367_TIME_INACT_VAL_H_MASK GENMASK(15, 8) |
63 | #define ADXL367_TIME_INACT_H_MASK GENMASK(7, 0) |
64 | #define ADXL367_TIME_INACT_VAL_L_MASK GENMASK(7, 0) |
65 | #define ADXL367_TIME_INACT_L_MASK GENMASK(7, 0) |
66 | |
67 | #define ADXL367_REG_ACT_INACT_CTL 0x27 |
68 | #define ADXL367_ACT_EN_MASK GENMASK(1, 0) |
69 | #define ADXL367_ACT_LINKLOOP_MASK GENMASK(5, 4) |
70 | |
71 | #define ADXL367_REG_FIFO_CTL 0x28 |
72 | #define ADXL367_FIFO_CTL_FORMAT_MASK GENMASK(6, 3) |
73 | #define ADXL367_FIFO_CTL_MODE_MASK GENMASK(1, 0) |
74 | |
75 | #define ADXL367_REG_FIFO_SAMPLES 0x29 |
76 | #define ADXL367_FIFO_SIZE 512 |
77 | #define ADXL367_FIFO_MAX_WATERMARK 511 |
78 | |
79 | #define ADXL367_SAMPLES_VAL_H_MASK BIT(8) |
80 | #define ADXL367_SAMPLES_H_MASK BIT(2) |
81 | #define ADXL367_SAMPLES_VAL_L_MASK GENMASK(7, 0) |
82 | #define ADXL367_SAMPLES_L_MASK GENMASK(7, 0) |
83 | |
84 | #define ADXL367_REG_INT1_MAP 0x2A |
85 | #define ADXL367_INT_INACT_MASK BIT(5) |
86 | #define ADXL367_INT_ACT_MASK BIT(4) |
87 | #define ADXL367_INT_FIFO_WATERMARK_MASK BIT(2) |
88 | |
89 | #define ADXL367_REG_FILTER_CTL 0x2C |
90 | #define ADXL367_FILTER_CTL_RANGE_MASK GENMASK(7, 6) |
91 | #define ADXL367_2G_RANGE_1G 4095 |
92 | #define ADXL367_2G_RANGE_100MG 409 |
93 | #define ADXL367_FILTER_CTL_ODR_MASK GENMASK(2, 0) |
94 | |
95 | #define ADXL367_REG_POWER_CTL 0x2D |
96 | #define ADXL367_POWER_CTL_MODE_MASK GENMASK(1, 0) |
97 | |
98 | #define ADXL367_REG_ADC_CTL 0x3C |
99 | #define ADXL367_REG_TEMP_CTL 0x3D |
100 | #define ADXL367_ADC_EN_MASK BIT(0) |
101 | |
102 | enum adxl367_range { |
103 | ADXL367_2G_RANGE, |
104 | ADXL367_4G_RANGE, |
105 | ADXL367_8G_RANGE, |
106 | }; |
107 | |
108 | enum adxl367_fifo_mode { |
109 | ADXL367_FIFO_MODE_DISABLED = 0b00, |
110 | ADXL367_FIFO_MODE_STREAM = 0b10, |
111 | }; |
112 | |
113 | enum adxl367_fifo_format { |
114 | ADXL367_FIFO_FORMAT_XYZ, |
115 | ADXL367_FIFO_FORMAT_X, |
116 | ADXL367_FIFO_FORMAT_Y, |
117 | ADXL367_FIFO_FORMAT_Z, |
118 | ADXL367_FIFO_FORMAT_XYZT, |
119 | ADXL367_FIFO_FORMAT_XT, |
120 | ADXL367_FIFO_FORMAT_YT, |
121 | ADXL367_FIFO_FORMAT_ZT, |
122 | ADXL367_FIFO_FORMAT_XYZA, |
123 | ADXL367_FIFO_FORMAT_XA, |
124 | ADXL367_FIFO_FORMAT_YA, |
125 | ADXL367_FIFO_FORMAT_ZA, |
126 | }; |
127 | |
128 | enum adxl367_op_mode { |
129 | ADXL367_OP_STANDBY = 0b00, |
130 | ADXL367_OP_MEASURE = 0b10, |
131 | }; |
132 | |
133 | enum adxl367_act_proc_mode { |
134 | ADXL367_LOOPED = 0b11, |
135 | }; |
136 | |
137 | enum adxl367_act_en_mode { |
138 | ADXL367_ACT_DISABLED = 0b00, |
139 | ADCL367_ACT_REF_ENABLED = 0b11, |
140 | }; |
141 | |
142 | enum adxl367_activity_type { |
143 | ADXL367_ACTIVITY, |
144 | ADXL367_INACTIVITY, |
145 | }; |
146 | |
147 | enum adxl367_odr { |
148 | ADXL367_ODR_12P5HZ, |
149 | ADXL367_ODR_25HZ, |
150 | ADXL367_ODR_50HZ, |
151 | ADXL367_ODR_100HZ, |
152 | ADXL367_ODR_200HZ, |
153 | ADXL367_ODR_400HZ, |
154 | }; |
155 | |
156 | struct adxl367_state { |
157 | const struct adxl367_ops *ops; |
158 | void *context; |
159 | |
160 | struct device *dev; |
161 | struct regmap *regmap; |
162 | |
163 | /* |
164 | * Synchronize access to members of driver state, and ensure atomicity |
165 | * of consecutive regmap operations. |
166 | */ |
167 | struct mutex lock; |
168 | |
169 | enum adxl367_odr odr; |
170 | enum adxl367_range range; |
171 | |
172 | unsigned int act_threshold; |
173 | unsigned int act_time_ms; |
174 | unsigned int inact_threshold; |
175 | unsigned int inact_time_ms; |
176 | |
177 | unsigned int fifo_set_size; |
178 | unsigned int fifo_watermark; |
179 | |
180 | __be16 fifo_buf[ADXL367_FIFO_SIZE] __aligned(IIO_DMA_MINALIGN); |
181 | __be16 sample_buf; |
182 | u8 act_threshold_buf[2]; |
183 | u8 inact_time_buf[2]; |
184 | u8 status_buf[3]; |
185 | }; |
186 | |
187 | static const unsigned int adxl367_threshold_h_reg_tbl[] = { |
188 | [ADXL367_ACTIVITY] = ADXL367_REG_THRESH_ACT_H, |
189 | [ADXL367_INACTIVITY] = ADXL367_REG_THRESH_INACT_H, |
190 | }; |
191 | |
192 | static const unsigned int adxl367_act_en_shift_tbl[] = { |
193 | [ADXL367_ACTIVITY] = 0, |
194 | [ADXL367_INACTIVITY] = 2, |
195 | }; |
196 | |
197 | static const unsigned int adxl367_act_int_mask_tbl[] = { |
198 | [ADXL367_ACTIVITY] = ADXL367_INT_ACT_MASK, |
199 | [ADXL367_INACTIVITY] = ADXL367_INT_INACT_MASK, |
200 | }; |
201 | |
202 | static const int adxl367_samp_freq_tbl[][2] = { |
203 | [ADXL367_ODR_12P5HZ] = {12, 500000}, |
204 | [ADXL367_ODR_25HZ] = {25, 0}, |
205 | [ADXL367_ODR_50HZ] = {50, 0}, |
206 | [ADXL367_ODR_100HZ] = {100, 0}, |
207 | [ADXL367_ODR_200HZ] = {200, 0}, |
208 | [ADXL367_ODR_400HZ] = {400, 0}, |
209 | }; |
210 | |
211 | /* (g * 2) * 9.80665 * 1000000 / (2^14 - 1) */ |
212 | static const int adxl367_range_scale_tbl[][2] = { |
213 | [ADXL367_2G_RANGE] = {0, 2394347}, |
214 | [ADXL367_4G_RANGE] = {0, 4788695}, |
215 | [ADXL367_8G_RANGE] = {0, 9577391}, |
216 | }; |
217 | |
218 | static const int adxl367_range_scale_factor_tbl[] = { |
219 | [ADXL367_2G_RANGE] = 1, |
220 | [ADXL367_4G_RANGE] = 2, |
221 | [ADXL367_8G_RANGE] = 4, |
222 | }; |
223 | |
224 | enum { |
225 | ADXL367_X_CHANNEL_INDEX, |
226 | ADXL367_Y_CHANNEL_INDEX, |
227 | ADXL367_Z_CHANNEL_INDEX, |
228 | ADXL367_TEMP_CHANNEL_INDEX, |
229 | ADXL367_EX_ADC_CHANNEL_INDEX |
230 | }; |
231 | |
232 | #define ADXL367_X_CHANNEL_MASK BIT(ADXL367_X_CHANNEL_INDEX) |
233 | #define ADXL367_Y_CHANNEL_MASK BIT(ADXL367_Y_CHANNEL_INDEX) |
234 | #define ADXL367_Z_CHANNEL_MASK BIT(ADXL367_Z_CHANNEL_INDEX) |
235 | #define ADXL367_TEMP_CHANNEL_MASK BIT(ADXL367_TEMP_CHANNEL_INDEX) |
236 | #define ADXL367_EX_ADC_CHANNEL_MASK BIT(ADXL367_EX_ADC_CHANNEL_INDEX) |
237 | |
238 | static const enum adxl367_fifo_format adxl367_fifo_formats[] = { |
239 | ADXL367_FIFO_FORMAT_X, |
240 | ADXL367_FIFO_FORMAT_Y, |
241 | ADXL367_FIFO_FORMAT_Z, |
242 | ADXL367_FIFO_FORMAT_XT, |
243 | ADXL367_FIFO_FORMAT_YT, |
244 | ADXL367_FIFO_FORMAT_ZT, |
245 | ADXL367_FIFO_FORMAT_XA, |
246 | ADXL367_FIFO_FORMAT_YA, |
247 | ADXL367_FIFO_FORMAT_ZA, |
248 | ADXL367_FIFO_FORMAT_XYZ, |
249 | ADXL367_FIFO_FORMAT_XYZT, |
250 | ADXL367_FIFO_FORMAT_XYZA, |
251 | }; |
252 | |
253 | static const unsigned long adxl367_channel_masks[] = { |
254 | ADXL367_X_CHANNEL_MASK, |
255 | ADXL367_Y_CHANNEL_MASK, |
256 | ADXL367_Z_CHANNEL_MASK, |
257 | ADXL367_X_CHANNEL_MASK | ADXL367_TEMP_CHANNEL_MASK, |
258 | ADXL367_Y_CHANNEL_MASK | ADXL367_TEMP_CHANNEL_MASK, |
259 | ADXL367_Z_CHANNEL_MASK | ADXL367_TEMP_CHANNEL_MASK, |
260 | ADXL367_X_CHANNEL_MASK | ADXL367_EX_ADC_CHANNEL_MASK, |
261 | ADXL367_Y_CHANNEL_MASK | ADXL367_EX_ADC_CHANNEL_MASK, |
262 | ADXL367_Z_CHANNEL_MASK | ADXL367_EX_ADC_CHANNEL_MASK, |
263 | ADXL367_X_CHANNEL_MASK | ADXL367_Y_CHANNEL_MASK | ADXL367_Z_CHANNEL_MASK, |
264 | ADXL367_X_CHANNEL_MASK | ADXL367_Y_CHANNEL_MASK | ADXL367_Z_CHANNEL_MASK | |
265 | ADXL367_TEMP_CHANNEL_MASK, |
266 | ADXL367_X_CHANNEL_MASK | ADXL367_Y_CHANNEL_MASK | ADXL367_Z_CHANNEL_MASK | |
267 | ADXL367_EX_ADC_CHANNEL_MASK, |
268 | 0, |
269 | }; |
270 | |
271 | static int adxl367_set_measure_en(struct adxl367_state *st, bool en) |
272 | { |
273 | enum adxl367_op_mode op_mode = en ? ADXL367_OP_MEASURE |
274 | : ADXL367_OP_STANDBY; |
275 | int ret; |
276 | |
277 | ret = regmap_update_bits(map: st->regmap, ADXL367_REG_POWER_CTL, |
278 | ADXL367_POWER_CTL_MODE_MASK, |
279 | FIELD_PREP(ADXL367_POWER_CTL_MODE_MASK, |
280 | op_mode)); |
281 | if (ret) |
282 | return ret; |
283 | |
284 | /* |
285 | * Wait for acceleration output to settle after entering |
286 | * measure mode. |
287 | */ |
288 | if (en) |
289 | msleep(msecs: 100); |
290 | |
291 | return 0; |
292 | } |
293 | |
294 | static void adxl367_scale_act_thresholds(struct adxl367_state *st, |
295 | enum adxl367_range old_range, |
296 | enum adxl367_range new_range) |
297 | { |
298 | st->act_threshold = st->act_threshold |
299 | * adxl367_range_scale_factor_tbl[old_range] |
300 | / adxl367_range_scale_factor_tbl[new_range]; |
301 | st->inact_threshold = st->inact_threshold |
302 | * adxl367_range_scale_factor_tbl[old_range] |
303 | / adxl367_range_scale_factor_tbl[new_range]; |
304 | } |
305 | |
306 | static int _adxl367_set_act_threshold(struct adxl367_state *st, |
307 | enum adxl367_activity_type act, |
308 | unsigned int threshold) |
309 | { |
310 | u8 reg = adxl367_threshold_h_reg_tbl[act]; |
311 | int ret; |
312 | |
313 | if (threshold > ADXL367_THRESH_MAX) |
314 | return -EINVAL; |
315 | |
316 | st->act_threshold_buf[0] = FIELD_PREP(ADXL367_THRESH_H_MASK, |
317 | FIELD_GET(ADXL367_THRESH_VAL_H_MASK, |
318 | threshold)); |
319 | st->act_threshold_buf[1] = FIELD_PREP(ADXL367_THRESH_L_MASK, |
320 | FIELD_GET(ADXL367_THRESH_VAL_L_MASK, |
321 | threshold)); |
322 | |
323 | ret = regmap_bulk_write(map: st->regmap, reg, val: st->act_threshold_buf, |
324 | val_count: sizeof(st->act_threshold_buf)); |
325 | if (ret) |
326 | return ret; |
327 | |
328 | if (act == ADXL367_ACTIVITY) |
329 | st->act_threshold = threshold; |
330 | else |
331 | st->inact_threshold = threshold; |
332 | |
333 | return 0; |
334 | } |
335 | |
336 | static int adxl367_set_act_threshold(struct adxl367_state *st, |
337 | enum adxl367_activity_type act, |
338 | unsigned int threshold) |
339 | { |
340 | int ret; |
341 | |
342 | guard(mutex)(T: &st->lock); |
343 | |
344 | ret = adxl367_set_measure_en(st, en: false); |
345 | if (ret) |
346 | return ret; |
347 | |
348 | ret = _adxl367_set_act_threshold(st, act, threshold); |
349 | if (ret) |
350 | return ret; |
351 | |
352 | return adxl367_set_measure_en(st, en: true); |
353 | } |
354 | |
355 | static int adxl367_set_act_proc_mode(struct adxl367_state *st, |
356 | enum adxl367_act_proc_mode mode) |
357 | { |
358 | return regmap_update_bits(map: st->regmap, ADXL367_REG_ACT_INACT_CTL, |
359 | ADXL367_ACT_LINKLOOP_MASK, |
360 | FIELD_PREP(ADXL367_ACT_LINKLOOP_MASK, |
361 | mode)); |
362 | } |
363 | |
364 | static int adxl367_set_act_interrupt_en(struct adxl367_state *st, |
365 | enum adxl367_activity_type act, |
366 | bool en) |
367 | { |
368 | unsigned int mask = adxl367_act_int_mask_tbl[act]; |
369 | |
370 | return regmap_update_bits(map: st->regmap, ADXL367_REG_INT1_MAP, |
371 | mask, val: en ? mask : 0); |
372 | } |
373 | |
374 | static int adxl367_get_act_interrupt_en(struct adxl367_state *st, |
375 | enum adxl367_activity_type act, |
376 | bool *en) |
377 | { |
378 | unsigned int mask = adxl367_act_int_mask_tbl[act]; |
379 | unsigned int val; |
380 | int ret; |
381 | |
382 | ret = regmap_read(map: st->regmap, ADXL367_REG_INT1_MAP, val: &val); |
383 | if (ret) |
384 | return ret; |
385 | |
386 | *en = !!(val & mask); |
387 | |
388 | return 0; |
389 | } |
390 | |
391 | static int adxl367_set_act_en(struct adxl367_state *st, |
392 | enum adxl367_activity_type act, |
393 | enum adxl367_act_en_mode en) |
394 | { |
395 | unsigned int ctl_shift = adxl367_act_en_shift_tbl[act]; |
396 | |
397 | return regmap_update_bits(map: st->regmap, ADXL367_REG_ACT_INACT_CTL, |
398 | ADXL367_ACT_EN_MASK << ctl_shift, |
399 | val: en << ctl_shift); |
400 | } |
401 | |
402 | static int adxl367_set_fifo_watermark_interrupt_en(struct adxl367_state *st, |
403 | bool en) |
404 | { |
405 | return regmap_update_bits(map: st->regmap, ADXL367_REG_INT1_MAP, |
406 | ADXL367_INT_FIFO_WATERMARK_MASK, |
407 | val: en ? ADXL367_INT_FIFO_WATERMARK_MASK : 0); |
408 | } |
409 | |
410 | static int adxl367_get_fifo_mode(struct adxl367_state *st, |
411 | enum adxl367_fifo_mode *fifo_mode) |
412 | { |
413 | unsigned int val; |
414 | int ret; |
415 | |
416 | ret = regmap_read(map: st->regmap, ADXL367_REG_FIFO_CTL, val: &val); |
417 | if (ret) |
418 | return ret; |
419 | |
420 | *fifo_mode = FIELD_GET(ADXL367_FIFO_CTL_MODE_MASK, val); |
421 | |
422 | return 0; |
423 | } |
424 | |
425 | static int adxl367_set_fifo_mode(struct adxl367_state *st, |
426 | enum adxl367_fifo_mode fifo_mode) |
427 | { |
428 | return regmap_update_bits(map: st->regmap, ADXL367_REG_FIFO_CTL, |
429 | ADXL367_FIFO_CTL_MODE_MASK, |
430 | FIELD_PREP(ADXL367_FIFO_CTL_MODE_MASK, |
431 | fifo_mode)); |
432 | } |
433 | |
434 | static int adxl367_set_fifo_format(struct adxl367_state *st, |
435 | enum adxl367_fifo_format fifo_format) |
436 | { |
437 | return regmap_update_bits(map: st->regmap, ADXL367_REG_FIFO_CTL, |
438 | ADXL367_FIFO_CTL_FORMAT_MASK, |
439 | FIELD_PREP(ADXL367_FIFO_CTL_FORMAT_MASK, |
440 | fifo_format)); |
441 | } |
442 | |
443 | static int adxl367_set_fifo_watermark(struct adxl367_state *st, |
444 | unsigned int fifo_watermark) |
445 | { |
446 | unsigned int fifo_samples = fifo_watermark * st->fifo_set_size; |
447 | unsigned int fifo_samples_h, fifo_samples_l; |
448 | int ret; |
449 | |
450 | if (fifo_samples > ADXL367_FIFO_MAX_WATERMARK) |
451 | fifo_samples = ADXL367_FIFO_MAX_WATERMARK; |
452 | |
453 | fifo_samples /= st->fifo_set_size; |
454 | |
455 | fifo_samples_h = FIELD_PREP(ADXL367_SAMPLES_H_MASK, |
456 | FIELD_GET(ADXL367_SAMPLES_VAL_H_MASK, |
457 | fifo_samples)); |
458 | fifo_samples_l = FIELD_PREP(ADXL367_SAMPLES_L_MASK, |
459 | FIELD_GET(ADXL367_SAMPLES_VAL_L_MASK, |
460 | fifo_samples)); |
461 | |
462 | ret = regmap_update_bits(map: st->regmap, ADXL367_REG_FIFO_CTL, |
463 | ADXL367_SAMPLES_H_MASK, val: fifo_samples_h); |
464 | if (ret) |
465 | return ret; |
466 | |
467 | ret = regmap_update_bits(map: st->regmap, ADXL367_REG_FIFO_SAMPLES, |
468 | ADXL367_SAMPLES_L_MASK, val: fifo_samples_l); |
469 | if (ret) |
470 | return ret; |
471 | |
472 | st->fifo_watermark = fifo_watermark; |
473 | |
474 | return 0; |
475 | } |
476 | |
477 | static int adxl367_set_range(struct iio_dev *indio_dev, |
478 | enum adxl367_range range) |
479 | { |
480 | iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { |
481 | struct adxl367_state *st = iio_priv(indio_dev); |
482 | int ret; |
483 | |
484 | guard(mutex)(T: &st->lock); |
485 | |
486 | ret = adxl367_set_measure_en(st, en: false); |
487 | if (ret) |
488 | return ret; |
489 | |
490 | ret = regmap_update_bits(map: st->regmap, ADXL367_REG_FILTER_CTL, |
491 | ADXL367_FILTER_CTL_RANGE_MASK, |
492 | FIELD_PREP(ADXL367_FILTER_CTL_RANGE_MASK, |
493 | range)); |
494 | if (ret) |
495 | return ret; |
496 | |
497 | adxl367_scale_act_thresholds(st, old_range: st->range, new_range: range); |
498 | |
499 | /* Activity thresholds depend on range */ |
500 | ret = _adxl367_set_act_threshold(st, act: ADXL367_ACTIVITY, |
501 | threshold: st->act_threshold); |
502 | if (ret) |
503 | return ret; |
504 | |
505 | ret = _adxl367_set_act_threshold(st, act: ADXL367_INACTIVITY, |
506 | threshold: st->inact_threshold); |
507 | if (ret) |
508 | return ret; |
509 | |
510 | ret = adxl367_set_measure_en(st, en: true); |
511 | if (ret) |
512 | return ret; |
513 | |
514 | st->range = range; |
515 | |
516 | return 0; |
517 | } |
518 | unreachable(); |
519 | } |
520 | |
521 | static int adxl367_time_ms_to_samples(struct adxl367_state *st, unsigned int ms) |
522 | { |
523 | int freq_hz = adxl367_samp_freq_tbl[st->odr][0]; |
524 | int freq_microhz = adxl367_samp_freq_tbl[st->odr][1]; |
525 | /* Scale to decihertz to prevent precision loss in 12.5Hz case. */ |
526 | int freq_dhz = freq_hz * 10 + freq_microhz / 100000; |
527 | |
528 | return DIV_ROUND_CLOSEST(ms * freq_dhz, 10000); |
529 | } |
530 | |
531 | static int _adxl367_set_act_time_ms(struct adxl367_state *st, unsigned int ms) |
532 | { |
533 | unsigned int val = adxl367_time_ms_to_samples(st, ms); |
534 | int ret; |
535 | |
536 | if (val > ADXL367_TIME_ACT_MAX) |
537 | val = ADXL367_TIME_ACT_MAX; |
538 | |
539 | ret = regmap_write(map: st->regmap, ADXL367_REG_TIME_ACT, val); |
540 | if (ret) |
541 | return ret; |
542 | |
543 | st->act_time_ms = ms; |
544 | |
545 | return 0; |
546 | } |
547 | |
548 | static int _adxl367_set_inact_time_ms(struct adxl367_state *st, unsigned int ms) |
549 | { |
550 | unsigned int val = adxl367_time_ms_to_samples(st, ms); |
551 | int ret; |
552 | |
553 | if (val > ADXL367_TIME_INACT_MAX) |
554 | val = ADXL367_TIME_INACT_MAX; |
555 | |
556 | st->inact_time_buf[0] = FIELD_PREP(ADXL367_TIME_INACT_H_MASK, |
557 | FIELD_GET(ADXL367_TIME_INACT_VAL_H_MASK, |
558 | val)); |
559 | st->inact_time_buf[1] = FIELD_PREP(ADXL367_TIME_INACT_L_MASK, |
560 | FIELD_GET(ADXL367_TIME_INACT_VAL_L_MASK, |
561 | val)); |
562 | |
563 | ret = regmap_bulk_write(map: st->regmap, ADXL367_REG_TIME_INACT_H, |
564 | val: st->inact_time_buf, val_count: sizeof(st->inact_time_buf)); |
565 | if (ret) |
566 | return ret; |
567 | |
568 | st->inact_time_ms = ms; |
569 | |
570 | return 0; |
571 | } |
572 | |
573 | static int adxl367_set_act_time_ms(struct adxl367_state *st, |
574 | enum adxl367_activity_type act, |
575 | unsigned int ms) |
576 | { |
577 | int ret; |
578 | |
579 | guard(mutex)(T: &st->lock); |
580 | |
581 | ret = adxl367_set_measure_en(st, en: false); |
582 | if (ret) |
583 | return ret; |
584 | |
585 | if (act == ADXL367_ACTIVITY) |
586 | ret = _adxl367_set_act_time_ms(st, ms); |
587 | else |
588 | ret = _adxl367_set_inact_time_ms(st, ms); |
589 | |
590 | if (ret) |
591 | return ret; |
592 | |
593 | return adxl367_set_measure_en(st, en: true); |
594 | } |
595 | |
596 | static int _adxl367_set_odr(struct adxl367_state *st, enum adxl367_odr odr) |
597 | { |
598 | int ret; |
599 | |
600 | ret = regmap_update_bits(map: st->regmap, ADXL367_REG_FILTER_CTL, |
601 | ADXL367_FILTER_CTL_ODR_MASK, |
602 | FIELD_PREP(ADXL367_FILTER_CTL_ODR_MASK, |
603 | odr)); |
604 | if (ret) |
605 | return ret; |
606 | |
607 | /* Activity timers depend on ODR */ |
608 | ret = _adxl367_set_act_time_ms(st, ms: st->act_time_ms); |
609 | if (ret) |
610 | return ret; |
611 | |
612 | ret = _adxl367_set_inact_time_ms(st, ms: st->inact_time_ms); |
613 | if (ret) |
614 | return ret; |
615 | |
616 | st->odr = odr; |
617 | |
618 | return 0; |
619 | } |
620 | |
621 | static int adxl367_set_odr(struct iio_dev *indio_dev, enum adxl367_odr odr) |
622 | { |
623 | iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { |
624 | struct adxl367_state *st = iio_priv(indio_dev);; |
625 | int ret; |
626 | |
627 | guard(mutex)(T: &st->lock); |
628 | |
629 | ret = adxl367_set_measure_en(st, en: false); |
630 | if (ret) |
631 | return ret; |
632 | |
633 | ret = _adxl367_set_odr(st, odr); |
634 | if (ret) |
635 | return ret; |
636 | |
637 | return adxl367_set_measure_en(st, en: true); |
638 | } |
639 | unreachable(); |
640 | } |
641 | |
642 | static int adxl367_set_temp_adc_en(struct adxl367_state *st, unsigned int reg, |
643 | bool en) |
644 | { |
645 | return regmap_update_bits(map: st->regmap, reg, ADXL367_ADC_EN_MASK, |
646 | val: en ? ADXL367_ADC_EN_MASK : 0); |
647 | } |
648 | |
649 | static int adxl367_set_temp_adc_reg_en(struct adxl367_state *st, |
650 | unsigned int reg, bool en) |
651 | { |
652 | int ret; |
653 | |
654 | switch (reg) { |
655 | case ADXL367_REG_TEMP_DATA_H: |
656 | ret = adxl367_set_temp_adc_en(st, ADXL367_REG_TEMP_CTL, en); |
657 | break; |
658 | case ADXL367_REG_EX_ADC_DATA_H: |
659 | ret = adxl367_set_temp_adc_en(st, ADXL367_REG_ADC_CTL, en); |
660 | break; |
661 | default: |
662 | return 0; |
663 | } |
664 | |
665 | if (ret) |
666 | return ret; |
667 | |
668 | if (en) |
669 | msleep(msecs: 100); |
670 | |
671 | return 0; |
672 | } |
673 | |
674 | static int adxl367_set_temp_adc_mask_en(struct adxl367_state *st, |
675 | const unsigned long *active_scan_mask, |
676 | bool en) |
677 | { |
678 | if (*active_scan_mask & ADXL367_TEMP_CHANNEL_MASK) |
679 | return adxl367_set_temp_adc_en(st, ADXL367_REG_TEMP_CTL, en); |
680 | else if (*active_scan_mask & ADXL367_EX_ADC_CHANNEL_MASK) |
681 | return adxl367_set_temp_adc_en(st, ADXL367_REG_ADC_CTL, en); |
682 | |
683 | return 0; |
684 | } |
685 | |
686 | static int adxl367_find_odr(struct adxl367_state *st, int val, int val2, |
687 | enum adxl367_odr *odr) |
688 | { |
689 | size_t size = ARRAY_SIZE(adxl367_samp_freq_tbl); |
690 | int i; |
691 | |
692 | for (i = 0; i < size; i++) |
693 | if (val == adxl367_samp_freq_tbl[i][0] && |
694 | val2 == adxl367_samp_freq_tbl[i][1]) |
695 | break; |
696 | |
697 | if (i == size) |
698 | return -EINVAL; |
699 | |
700 | *odr = i; |
701 | |
702 | return 0; |
703 | } |
704 | |
705 | static int adxl367_find_range(struct adxl367_state *st, int val, int val2, |
706 | enum adxl367_range *range) |
707 | { |
708 | size_t size = ARRAY_SIZE(adxl367_range_scale_tbl); |
709 | int i; |
710 | |
711 | for (i = 0; i < size; i++) |
712 | if (val == adxl367_range_scale_tbl[i][0] && |
713 | val2 == adxl367_range_scale_tbl[i][1]) |
714 | break; |
715 | |
716 | if (i == size) |
717 | return -EINVAL; |
718 | |
719 | *range = i; |
720 | |
721 | return 0; |
722 | } |
723 | |
724 | static int adxl367_read_sample(struct iio_dev *indio_dev, |
725 | struct iio_chan_spec const *chan, |
726 | int *val) |
727 | { |
728 | iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { |
729 | struct adxl367_state *st = iio_priv(indio_dev); |
730 | u16 sample; |
731 | int ret; |
732 | |
733 | guard(mutex)(T: &st->lock); |
734 | |
735 | ret = adxl367_set_temp_adc_reg_en(st, reg: chan->address, en: true); |
736 | if (ret) |
737 | return ret; |
738 | |
739 | ret = regmap_bulk_read(map: st->regmap, reg: chan->address, val: &st->sample_buf, |
740 | val_count: sizeof(st->sample_buf)); |
741 | if (ret) |
742 | return ret; |
743 | |
744 | sample = FIELD_GET(ADXL367_DATA_MASK, be16_to_cpu(st->sample_buf)); |
745 | *val = sign_extend32(value: sample, index: chan->scan_type.realbits - 1); |
746 | |
747 | ret = adxl367_set_temp_adc_reg_en(st, reg: chan->address, en: false); |
748 | if (ret) |
749 | return ret; |
750 | |
751 | return IIO_VAL_INT; |
752 | } |
753 | unreachable(); |
754 | } |
755 | |
756 | static int adxl367_get_status(struct adxl367_state *st, u8 *status, |
757 | u16 *fifo_entries) |
758 | { |
759 | int ret; |
760 | |
761 | /* Read STATUS, FIFO_ENT_L and FIFO_ENT_H */ |
762 | ret = regmap_bulk_read(map: st->regmap, ADXL367_REG_STATUS, |
763 | val: st->status_buf, val_count: sizeof(st->status_buf)); |
764 | if (ret) |
765 | return ret; |
766 | |
767 | st->status_buf[2] &= ADXL367_FIFO_ENT_H_MASK; |
768 | |
769 | *status = st->status_buf[0]; |
770 | *fifo_entries = get_unaligned_le16(p: &st->status_buf[1]); |
771 | |
772 | return 0; |
773 | } |
774 | |
775 | static bool adxl367_push_event(struct iio_dev *indio_dev, u8 status) |
776 | { |
777 | unsigned int ev_dir; |
778 | |
779 | if (FIELD_GET(ADXL367_STATUS_ACT_MASK, status)) |
780 | ev_dir = IIO_EV_DIR_RISING; |
781 | else if (FIELD_GET(ADXL367_STATUS_INACT_MASK, status)) |
782 | ev_dir = IIO_EV_DIR_FALLING; |
783 | else |
784 | return false; |
785 | |
786 | iio_push_event(indio_dev, |
787 | IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z, |
788 | IIO_EV_TYPE_THRESH, ev_dir), |
789 | timestamp: iio_get_time_ns(indio_dev)); |
790 | |
791 | return true; |
792 | } |
793 | |
794 | static bool adxl367_push_fifo_data(struct iio_dev *indio_dev, u8 status, |
795 | u16 fifo_entries) |
796 | { |
797 | struct adxl367_state *st = iio_priv(indio_dev); |
798 | int ret; |
799 | int i; |
800 | |
801 | if (!FIELD_GET(ADXL367_STATUS_FIFO_FULL_MASK, status)) |
802 | return false; |
803 | |
804 | fifo_entries -= fifo_entries % st->fifo_set_size; |
805 | |
806 | ret = st->ops->read_fifo(st->context, st->fifo_buf, fifo_entries); |
807 | if (ret) { |
808 | dev_err(st->dev, "Failed to read FIFO: %d\n" , ret); |
809 | return true; |
810 | } |
811 | |
812 | for (i = 0; i < fifo_entries; i += st->fifo_set_size) |
813 | iio_push_to_buffers(indio_dev, data: &st->fifo_buf[i]); |
814 | |
815 | return true; |
816 | } |
817 | |
818 | static irqreturn_t adxl367_irq_handler(int irq, void *private) |
819 | { |
820 | struct iio_dev *indio_dev = private; |
821 | struct adxl367_state *st = iio_priv(indio_dev); |
822 | u16 fifo_entries; |
823 | bool handled; |
824 | u8 status; |
825 | int ret; |
826 | |
827 | ret = adxl367_get_status(st, status: &status, fifo_entries: &fifo_entries); |
828 | if (ret) |
829 | return IRQ_NONE; |
830 | |
831 | handled = adxl367_push_event(indio_dev, status); |
832 | handled |= adxl367_push_fifo_data(indio_dev, status, fifo_entries); |
833 | |
834 | return handled ? IRQ_HANDLED : IRQ_NONE; |
835 | } |
836 | |
837 | static int adxl367_reg_access(struct iio_dev *indio_dev, |
838 | unsigned int reg, |
839 | unsigned int writeval, |
840 | unsigned int *readval) |
841 | { |
842 | struct adxl367_state *st = iio_priv(indio_dev); |
843 | |
844 | if (readval) |
845 | return regmap_read(map: st->regmap, reg, val: readval); |
846 | else |
847 | return regmap_write(map: st->regmap, reg, val: writeval); |
848 | } |
849 | |
850 | static int adxl367_read_raw(struct iio_dev *indio_dev, |
851 | struct iio_chan_spec const *chan, |
852 | int *val, int *val2, long info) |
853 | { |
854 | struct adxl367_state *st = iio_priv(indio_dev); |
855 | |
856 | switch (info) { |
857 | case IIO_CHAN_INFO_RAW: |
858 | return adxl367_read_sample(indio_dev, chan, val); |
859 | case IIO_CHAN_INFO_SCALE: |
860 | switch (chan->type) { |
861 | case IIO_ACCEL: { |
862 | guard(mutex)(T: &st->lock); |
863 | *val = adxl367_range_scale_tbl[st->range][0]; |
864 | *val2 = adxl367_range_scale_tbl[st->range][1]; |
865 | return IIO_VAL_INT_PLUS_NANO; |
866 | } |
867 | case IIO_TEMP: |
868 | *val = 1000; |
869 | *val2 = ADXL367_TEMP_PER_C; |
870 | return IIO_VAL_FRACTIONAL; |
871 | case IIO_VOLTAGE: |
872 | *val = ADXL367_VOLTAGE_MAX_MV; |
873 | *val2 = ADXL367_VOLTAGE_MAX_RAW; |
874 | return IIO_VAL_FRACTIONAL; |
875 | default: |
876 | return -EINVAL; |
877 | } |
878 | case IIO_CHAN_INFO_OFFSET: |
879 | switch (chan->type) { |
880 | case IIO_TEMP: |
881 | *val = 25 * ADXL367_TEMP_PER_C - ADXL367_TEMP_25C; |
882 | return IIO_VAL_INT; |
883 | case IIO_VOLTAGE: |
884 | *val = ADXL367_VOLTAGE_OFFSET; |
885 | return IIO_VAL_INT; |
886 | default: |
887 | return -EINVAL; |
888 | } |
889 | case IIO_CHAN_INFO_SAMP_FREQ: { |
890 | guard(mutex)(T: &st->lock); |
891 | *val = adxl367_samp_freq_tbl[st->odr][0]; |
892 | *val2 = adxl367_samp_freq_tbl[st->odr][1]; |
893 | return IIO_VAL_INT_PLUS_MICRO; |
894 | } |
895 | default: |
896 | return -EINVAL; |
897 | } |
898 | } |
899 | |
900 | static int adxl367_write_raw(struct iio_dev *indio_dev, |
901 | struct iio_chan_spec const *chan, |
902 | int val, int val2, long info) |
903 | { |
904 | struct adxl367_state *st = iio_priv(indio_dev); |
905 | int ret; |
906 | |
907 | switch (info) { |
908 | case IIO_CHAN_INFO_SAMP_FREQ: { |
909 | enum adxl367_odr odr; |
910 | |
911 | ret = adxl367_find_odr(st, val, val2, odr: &odr); |
912 | if (ret) |
913 | return ret; |
914 | |
915 | return adxl367_set_odr(indio_dev, odr); |
916 | } |
917 | case IIO_CHAN_INFO_SCALE: { |
918 | enum adxl367_range range; |
919 | |
920 | ret = adxl367_find_range(st, val, val2, range: &range); |
921 | if (ret) |
922 | return ret; |
923 | |
924 | return adxl367_set_range(indio_dev, range); |
925 | } |
926 | default: |
927 | return -EINVAL; |
928 | } |
929 | } |
930 | |
931 | static int adxl367_write_raw_get_fmt(struct iio_dev *indio_dev, |
932 | struct iio_chan_spec const *chan, |
933 | long info) |
934 | { |
935 | switch (info) { |
936 | case IIO_CHAN_INFO_SCALE: |
937 | if (chan->type != IIO_ACCEL) |
938 | return -EINVAL; |
939 | |
940 | return IIO_VAL_INT_PLUS_NANO; |
941 | default: |
942 | return IIO_VAL_INT_PLUS_MICRO; |
943 | } |
944 | } |
945 | |
946 | static int adxl367_read_avail(struct iio_dev *indio_dev, |
947 | struct iio_chan_spec const *chan, |
948 | const int **vals, int *type, int *length, |
949 | long info) |
950 | { |
951 | switch (info) { |
952 | case IIO_CHAN_INFO_SCALE: |
953 | if (chan->type != IIO_ACCEL) |
954 | return -EINVAL; |
955 | |
956 | *vals = (int *)adxl367_range_scale_tbl; |
957 | *type = IIO_VAL_INT_PLUS_NANO; |
958 | *length = ARRAY_SIZE(adxl367_range_scale_tbl) * 2; |
959 | return IIO_AVAIL_LIST; |
960 | case IIO_CHAN_INFO_SAMP_FREQ: |
961 | *vals = (int *)adxl367_samp_freq_tbl; |
962 | *type = IIO_VAL_INT_PLUS_MICRO; |
963 | *length = ARRAY_SIZE(adxl367_samp_freq_tbl) * 2; |
964 | return IIO_AVAIL_LIST; |
965 | default: |
966 | return -EINVAL; |
967 | } |
968 | } |
969 | |
970 | static int adxl367_read_event_value(struct iio_dev *indio_dev, |
971 | const struct iio_chan_spec *chan, |
972 | enum iio_event_type type, |
973 | enum iio_event_direction dir, |
974 | enum iio_event_info info, |
975 | int *val, int *val2) |
976 | { |
977 | struct adxl367_state *st = iio_priv(indio_dev); |
978 | |
979 | guard(mutex)(T: &st->lock); |
980 | switch (info) { |
981 | case IIO_EV_INFO_VALUE: { |
982 | switch (dir) { |
983 | case IIO_EV_DIR_RISING: |
984 | *val = st->act_threshold; |
985 | return IIO_VAL_INT; |
986 | case IIO_EV_DIR_FALLING: |
987 | *val = st->inact_threshold; |
988 | return IIO_VAL_INT; |
989 | default: |
990 | return -EINVAL; |
991 | } |
992 | } |
993 | case IIO_EV_INFO_PERIOD: |
994 | switch (dir) { |
995 | case IIO_EV_DIR_RISING: |
996 | *val = st->act_time_ms; |
997 | *val2 = 1000; |
998 | return IIO_VAL_FRACTIONAL; |
999 | case IIO_EV_DIR_FALLING: |
1000 | *val = st->inact_time_ms; |
1001 | *val2 = 1000; |
1002 | return IIO_VAL_FRACTIONAL; |
1003 | default: |
1004 | return -EINVAL; |
1005 | } |
1006 | default: |
1007 | return -EINVAL; |
1008 | } |
1009 | } |
1010 | |
1011 | static int adxl367_write_event_value(struct iio_dev *indio_dev, |
1012 | const struct iio_chan_spec *chan, |
1013 | enum iio_event_type type, |
1014 | enum iio_event_direction dir, |
1015 | enum iio_event_info info, |
1016 | int val, int val2) |
1017 | { |
1018 | struct adxl367_state *st = iio_priv(indio_dev); |
1019 | |
1020 | switch (info) { |
1021 | case IIO_EV_INFO_VALUE: |
1022 | if (val < 0) |
1023 | return -EINVAL; |
1024 | |
1025 | switch (dir) { |
1026 | case IIO_EV_DIR_RISING: |
1027 | return adxl367_set_act_threshold(st, act: ADXL367_ACTIVITY, threshold: val); |
1028 | case IIO_EV_DIR_FALLING: |
1029 | return adxl367_set_act_threshold(st, act: ADXL367_INACTIVITY, threshold: val); |
1030 | default: |
1031 | return -EINVAL; |
1032 | } |
1033 | case IIO_EV_INFO_PERIOD: |
1034 | if (val < 0) |
1035 | return -EINVAL; |
1036 | |
1037 | val = val * 1000 + DIV_ROUND_UP(val2, 1000); |
1038 | switch (dir) { |
1039 | case IIO_EV_DIR_RISING: |
1040 | return adxl367_set_act_time_ms(st, act: ADXL367_ACTIVITY, ms: val); |
1041 | case IIO_EV_DIR_FALLING: |
1042 | return adxl367_set_act_time_ms(st, act: ADXL367_INACTIVITY, ms: val); |
1043 | default: |
1044 | return -EINVAL; |
1045 | } |
1046 | default: |
1047 | return -EINVAL; |
1048 | } |
1049 | } |
1050 | |
1051 | static int adxl367_read_event_config(struct iio_dev *indio_dev, |
1052 | const struct iio_chan_spec *chan, |
1053 | enum iio_event_type type, |
1054 | enum iio_event_direction dir) |
1055 | { |
1056 | struct adxl367_state *st = iio_priv(indio_dev); |
1057 | bool en; |
1058 | int ret; |
1059 | |
1060 | switch (dir) { |
1061 | case IIO_EV_DIR_RISING: |
1062 | ret = adxl367_get_act_interrupt_en(st, act: ADXL367_ACTIVITY, en: &en); |
1063 | return ret ?: en; |
1064 | case IIO_EV_DIR_FALLING: |
1065 | ret = adxl367_get_act_interrupt_en(st, act: ADXL367_INACTIVITY, en: &en); |
1066 | return ret ?: en; |
1067 | default: |
1068 | return -EINVAL; |
1069 | } |
1070 | } |
1071 | |
1072 | static int adxl367_write_event_config(struct iio_dev *indio_dev, |
1073 | const struct iio_chan_spec *chan, |
1074 | enum iio_event_type type, |
1075 | enum iio_event_direction dir, |
1076 | int state) |
1077 | { |
1078 | enum adxl367_activity_type act; |
1079 | |
1080 | switch (dir) { |
1081 | case IIO_EV_DIR_RISING: |
1082 | act = ADXL367_ACTIVITY; |
1083 | break; |
1084 | case IIO_EV_DIR_FALLING: |
1085 | act = ADXL367_INACTIVITY; |
1086 | break; |
1087 | default: |
1088 | return -EINVAL; |
1089 | } |
1090 | |
1091 | iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { |
1092 | struct adxl367_state *st = iio_priv(indio_dev); |
1093 | int ret; |
1094 | |
1095 | guard(mutex)(T: &st->lock); |
1096 | |
1097 | ret = adxl367_set_measure_en(st, en: false); |
1098 | if (ret) |
1099 | return ret; |
1100 | |
1101 | ret = adxl367_set_act_interrupt_en(st, act, en: state); |
1102 | if (ret) |
1103 | return ret; |
1104 | |
1105 | ret = adxl367_set_act_en(st, act, en: state ? ADCL367_ACT_REF_ENABLED |
1106 | : ADXL367_ACT_DISABLED); |
1107 | if (ret) |
1108 | return ret; |
1109 | |
1110 | return adxl367_set_measure_en(st, en: true); |
1111 | } |
1112 | unreachable(); |
1113 | } |
1114 | |
1115 | static ssize_t adxl367_get_fifo_enabled(struct device *dev, |
1116 | struct device_attribute *attr, |
1117 | char *buf) |
1118 | { |
1119 | struct adxl367_state *st = iio_priv(indio_dev: dev_to_iio_dev(dev)); |
1120 | enum adxl367_fifo_mode fifo_mode; |
1121 | int ret; |
1122 | |
1123 | ret = adxl367_get_fifo_mode(st, fifo_mode: &fifo_mode); |
1124 | if (ret) |
1125 | return ret; |
1126 | |
1127 | return sysfs_emit(buf, fmt: "%d\n" , fifo_mode != ADXL367_FIFO_MODE_DISABLED); |
1128 | } |
1129 | |
1130 | static ssize_t adxl367_get_fifo_watermark(struct device *dev, |
1131 | struct device_attribute *attr, |
1132 | char *buf) |
1133 | { |
1134 | struct adxl367_state *st = iio_priv(indio_dev: dev_to_iio_dev(dev)); |
1135 | unsigned int fifo_watermark; |
1136 | |
1137 | guard(mutex)(T: &st->lock); |
1138 | fifo_watermark = st->fifo_watermark; |
1139 | |
1140 | return sysfs_emit(buf, fmt: "%d\n" , fifo_watermark); |
1141 | } |
1142 | |
1143 | IIO_STATIC_CONST_DEVICE_ATTR(hwfifo_watermark_min, "1" ); |
1144 | IIO_STATIC_CONST_DEVICE_ATTR(hwfifo_watermark_max, |
1145 | __stringify(ADXL367_FIFO_MAX_WATERMARK)); |
1146 | static IIO_DEVICE_ATTR(hwfifo_watermark, 0444, |
1147 | adxl367_get_fifo_watermark, NULL, 0); |
1148 | static IIO_DEVICE_ATTR(hwfifo_enabled, 0444, |
1149 | adxl367_get_fifo_enabled, NULL, 0); |
1150 | |
1151 | static const struct iio_dev_attr *adxl367_fifo_attributes[] = { |
1152 | &iio_dev_attr_hwfifo_watermark_min, |
1153 | &iio_dev_attr_hwfifo_watermark_max, |
1154 | &iio_dev_attr_hwfifo_watermark, |
1155 | &iio_dev_attr_hwfifo_enabled, |
1156 | NULL, |
1157 | }; |
1158 | |
1159 | static int adxl367_set_watermark(struct iio_dev *indio_dev, unsigned int val) |
1160 | { |
1161 | struct adxl367_state *st = iio_priv(indio_dev); |
1162 | int ret; |
1163 | |
1164 | if (val > ADXL367_FIFO_MAX_WATERMARK) |
1165 | return -EINVAL; |
1166 | |
1167 | guard(mutex)(T: &st->lock); |
1168 | |
1169 | ret = adxl367_set_measure_en(st, en: false); |
1170 | if (ret) |
1171 | return ret; |
1172 | |
1173 | ret = adxl367_set_fifo_watermark(st, fifo_watermark: val); |
1174 | if (ret) |
1175 | return ret; |
1176 | |
1177 | return adxl367_set_measure_en(st, en: true); |
1178 | } |
1179 | |
1180 | static bool adxl367_find_mask_fifo_format(const unsigned long *scan_mask, |
1181 | enum adxl367_fifo_format *fifo_format) |
1182 | { |
1183 | size_t size = ARRAY_SIZE(adxl367_fifo_formats); |
1184 | int i; |
1185 | |
1186 | for (i = 0; i < size; i++) |
1187 | if (*scan_mask == adxl367_channel_masks[i]) |
1188 | break; |
1189 | |
1190 | if (i == size) |
1191 | return false; |
1192 | |
1193 | *fifo_format = adxl367_fifo_formats[i]; |
1194 | |
1195 | return true; |
1196 | } |
1197 | |
1198 | static int adxl367_update_scan_mode(struct iio_dev *indio_dev, |
1199 | const unsigned long *active_scan_mask) |
1200 | { |
1201 | struct adxl367_state *st = iio_priv(indio_dev); |
1202 | enum adxl367_fifo_format fifo_format; |
1203 | int ret; |
1204 | |
1205 | if (!adxl367_find_mask_fifo_format(scan_mask: active_scan_mask, fifo_format: &fifo_format)) |
1206 | return -EINVAL; |
1207 | |
1208 | guard(mutex)(T: &st->lock); |
1209 | |
1210 | ret = adxl367_set_measure_en(st, en: false); |
1211 | if (ret) |
1212 | return ret; |
1213 | |
1214 | ret = adxl367_set_fifo_format(st, fifo_format); |
1215 | if (ret) |
1216 | return ret; |
1217 | |
1218 | ret = adxl367_set_measure_en(st, en: true); |
1219 | if (ret) |
1220 | return ret; |
1221 | |
1222 | st->fifo_set_size = bitmap_weight(src: active_scan_mask, |
1223 | nbits: indio_dev->masklength); |
1224 | |
1225 | return 0; |
1226 | } |
1227 | |
1228 | static int adxl367_buffer_postenable(struct iio_dev *indio_dev) |
1229 | { |
1230 | struct adxl367_state *st = iio_priv(indio_dev); |
1231 | int ret; |
1232 | |
1233 | guard(mutex)(T: &st->lock); |
1234 | |
1235 | ret = adxl367_set_temp_adc_mask_en(st, active_scan_mask: indio_dev->active_scan_mask, |
1236 | en: true); |
1237 | if (ret) |
1238 | return ret; |
1239 | |
1240 | ret = adxl367_set_measure_en(st, en: false); |
1241 | if (ret) |
1242 | return ret; |
1243 | |
1244 | ret = adxl367_set_fifo_watermark_interrupt_en(st, en: true); |
1245 | if (ret) |
1246 | return ret; |
1247 | |
1248 | ret = adxl367_set_fifo_mode(st, fifo_mode: ADXL367_FIFO_MODE_STREAM); |
1249 | if (ret) |
1250 | return ret; |
1251 | |
1252 | return adxl367_set_measure_en(st, en: true); |
1253 | } |
1254 | |
1255 | static int adxl367_buffer_predisable(struct iio_dev *indio_dev) |
1256 | { |
1257 | struct adxl367_state *st = iio_priv(indio_dev); |
1258 | int ret; |
1259 | |
1260 | guard(mutex)(T: &st->lock); |
1261 | |
1262 | ret = adxl367_set_measure_en(st, en: false); |
1263 | if (ret) |
1264 | return ret; |
1265 | |
1266 | ret = adxl367_set_fifo_mode(st, fifo_mode: ADXL367_FIFO_MODE_DISABLED); |
1267 | if (ret) |
1268 | return ret; |
1269 | |
1270 | ret = adxl367_set_fifo_watermark_interrupt_en(st, en: false); |
1271 | if (ret) |
1272 | return ret; |
1273 | |
1274 | ret = adxl367_set_measure_en(st, en: true); |
1275 | if (ret) |
1276 | return ret; |
1277 | |
1278 | return adxl367_set_temp_adc_mask_en(st, active_scan_mask: indio_dev->active_scan_mask, |
1279 | en: false); |
1280 | } |
1281 | |
1282 | static const struct iio_buffer_setup_ops adxl367_buffer_ops = { |
1283 | .postenable = adxl367_buffer_postenable, |
1284 | .predisable = adxl367_buffer_predisable, |
1285 | }; |
1286 | |
1287 | static const struct iio_info adxl367_info = { |
1288 | .read_raw = adxl367_read_raw, |
1289 | .write_raw = adxl367_write_raw, |
1290 | .write_raw_get_fmt = adxl367_write_raw_get_fmt, |
1291 | .read_avail = adxl367_read_avail, |
1292 | .read_event_config = adxl367_read_event_config, |
1293 | .write_event_config = adxl367_write_event_config, |
1294 | .read_event_value = adxl367_read_event_value, |
1295 | .write_event_value = adxl367_write_event_value, |
1296 | .debugfs_reg_access = adxl367_reg_access, |
1297 | .hwfifo_set_watermark = adxl367_set_watermark, |
1298 | .update_scan_mode = adxl367_update_scan_mode, |
1299 | }; |
1300 | |
1301 | static const struct iio_event_spec adxl367_events[] = { |
1302 | { |
1303 | .type = IIO_EV_TYPE_MAG_REFERENCED, |
1304 | .dir = IIO_EV_DIR_RISING, |
1305 | .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) | |
1306 | BIT(IIO_EV_INFO_PERIOD) | |
1307 | BIT(IIO_EV_INFO_VALUE), |
1308 | }, |
1309 | { |
1310 | .type = IIO_EV_TYPE_MAG_REFERENCED, |
1311 | .dir = IIO_EV_DIR_FALLING, |
1312 | .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) | |
1313 | BIT(IIO_EV_INFO_PERIOD) | |
1314 | BIT(IIO_EV_INFO_VALUE), |
1315 | }, |
1316 | }; |
1317 | |
1318 | #define ADXL367_ACCEL_CHANNEL(index, reg, axis) { \ |
1319 | .type = IIO_ACCEL, \ |
1320 | .address = (reg), \ |
1321 | .modified = 1, \ |
1322 | .channel2 = IIO_MOD_##axis, \ |
1323 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ |
1324 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ |
1325 | .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE), \ |
1326 | .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ |
1327 | .info_mask_shared_by_all_available = \ |
1328 | BIT(IIO_CHAN_INFO_SAMP_FREQ), \ |
1329 | .event_spec = adxl367_events, \ |
1330 | .num_event_specs = ARRAY_SIZE(adxl367_events), \ |
1331 | .scan_index = (index), \ |
1332 | .scan_type = { \ |
1333 | .sign = 's', \ |
1334 | .realbits = 14, \ |
1335 | .storagebits = 16, \ |
1336 | .endianness = IIO_BE, \ |
1337 | }, \ |
1338 | } |
1339 | |
1340 | #define ADXL367_CHANNEL(index, reg, _type) { \ |
1341 | .type = (_type), \ |
1342 | .address = (reg), \ |
1343 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
1344 | BIT(IIO_CHAN_INFO_OFFSET) | \ |
1345 | BIT(IIO_CHAN_INFO_SCALE), \ |
1346 | .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ |
1347 | .scan_index = (index), \ |
1348 | .scan_type = { \ |
1349 | .sign = 's', \ |
1350 | .realbits = 14, \ |
1351 | .storagebits = 16, \ |
1352 | .endianness = IIO_BE, \ |
1353 | }, \ |
1354 | } |
1355 | |
1356 | static const struct iio_chan_spec adxl367_channels[] = { |
1357 | ADXL367_ACCEL_CHANNEL(ADXL367_X_CHANNEL_INDEX, ADXL367_REG_X_DATA_H, X), |
1358 | ADXL367_ACCEL_CHANNEL(ADXL367_Y_CHANNEL_INDEX, ADXL367_REG_Y_DATA_H, Y), |
1359 | ADXL367_ACCEL_CHANNEL(ADXL367_Z_CHANNEL_INDEX, ADXL367_REG_Z_DATA_H, Z), |
1360 | ADXL367_CHANNEL(ADXL367_TEMP_CHANNEL_INDEX, ADXL367_REG_TEMP_DATA_H, |
1361 | IIO_TEMP), |
1362 | ADXL367_CHANNEL(ADXL367_EX_ADC_CHANNEL_INDEX, ADXL367_REG_EX_ADC_DATA_H, |
1363 | IIO_VOLTAGE), |
1364 | }; |
1365 | |
1366 | static int adxl367_verify_devid(struct adxl367_state *st) |
1367 | { |
1368 | unsigned int val; |
1369 | int ret; |
1370 | |
1371 | ret = regmap_read(map: st->regmap, ADXL367_REG_DEVID, val: &val); |
1372 | if (ret) |
1373 | return dev_err_probe(dev: st->dev, err: ret, fmt: "Failed to read dev id\n" ); |
1374 | |
1375 | if (val != ADXL367_DEVID_AD) |
1376 | return dev_err_probe(dev: st->dev, err: -ENODEV, |
1377 | fmt: "Invalid dev id 0x%02X, expected 0x%02X\n" , |
1378 | val, ADXL367_DEVID_AD); |
1379 | |
1380 | return 0; |
1381 | } |
1382 | |
1383 | static int adxl367_setup(struct adxl367_state *st) |
1384 | { |
1385 | int ret; |
1386 | |
1387 | ret = _adxl367_set_act_threshold(st, act: ADXL367_ACTIVITY, |
1388 | ADXL367_2G_RANGE_1G); |
1389 | if (ret) |
1390 | return ret; |
1391 | |
1392 | ret = _adxl367_set_act_threshold(st, act: ADXL367_INACTIVITY, |
1393 | ADXL367_2G_RANGE_100MG); |
1394 | if (ret) |
1395 | return ret; |
1396 | |
1397 | ret = adxl367_set_act_proc_mode(st, mode: ADXL367_LOOPED); |
1398 | if (ret) |
1399 | return ret; |
1400 | |
1401 | ret = _adxl367_set_odr(st, odr: ADXL367_ODR_400HZ); |
1402 | if (ret) |
1403 | return ret; |
1404 | |
1405 | ret = _adxl367_set_act_time_ms(st, ms: 10); |
1406 | if (ret) |
1407 | return ret; |
1408 | |
1409 | ret = _adxl367_set_inact_time_ms(st, ms: 10000); |
1410 | if (ret) |
1411 | return ret; |
1412 | |
1413 | return adxl367_set_measure_en(st, en: true); |
1414 | } |
1415 | |
1416 | int adxl367_probe(struct device *dev, const struct adxl367_ops *ops, |
1417 | void *context, struct regmap *regmap, int irq) |
1418 | { |
1419 | static const char * const regulator_names[] = { "vdd" , "vddio" }; |
1420 | struct iio_dev *indio_dev; |
1421 | struct adxl367_state *st; |
1422 | int ret; |
1423 | |
1424 | indio_dev = devm_iio_device_alloc(parent: dev, sizeof_priv: sizeof(*st)); |
1425 | if (!indio_dev) |
1426 | return -ENOMEM; |
1427 | |
1428 | st = iio_priv(indio_dev); |
1429 | st->dev = dev; |
1430 | st->regmap = regmap; |
1431 | st->context = context; |
1432 | st->ops = ops; |
1433 | |
1434 | mutex_init(&st->lock); |
1435 | |
1436 | indio_dev->channels = adxl367_channels; |
1437 | indio_dev->num_channels = ARRAY_SIZE(adxl367_channels); |
1438 | indio_dev->available_scan_masks = adxl367_channel_masks; |
1439 | indio_dev->name = "adxl367" ; |
1440 | indio_dev->info = &adxl367_info; |
1441 | indio_dev->modes = INDIO_DIRECT_MODE; |
1442 | |
1443 | ret = devm_regulator_bulk_get_enable(dev: st->dev, |
1444 | ARRAY_SIZE(regulator_names), |
1445 | id: regulator_names); |
1446 | if (ret) |
1447 | return dev_err_probe(dev: st->dev, err: ret, |
1448 | fmt: "Failed to get regulators\n" ); |
1449 | |
1450 | ret = regmap_write(map: st->regmap, ADXL367_REG_RESET, ADXL367_RESET_CODE); |
1451 | if (ret) |
1452 | return ret; |
1453 | |
1454 | fsleep(usecs: 15000); |
1455 | |
1456 | ret = adxl367_verify_devid(st); |
1457 | if (ret) |
1458 | return ret; |
1459 | |
1460 | ret = adxl367_setup(st); |
1461 | if (ret) |
1462 | return ret; |
1463 | |
1464 | ret = devm_iio_kfifo_buffer_setup_ext(dev: st->dev, indio_dev, |
1465 | setup_ops: &adxl367_buffer_ops, |
1466 | buffer_attrs: adxl367_fifo_attributes); |
1467 | if (ret) |
1468 | return ret; |
1469 | |
1470 | ret = devm_request_threaded_irq(dev: st->dev, irq, NULL, |
1471 | thread_fn: adxl367_irq_handler, IRQF_ONESHOT, |
1472 | devname: indio_dev->name, dev_id: indio_dev); |
1473 | if (ret) |
1474 | return dev_err_probe(dev: st->dev, err: ret, fmt: "Failed to request irq\n" ); |
1475 | |
1476 | return devm_iio_device_register(dev, indio_dev); |
1477 | } |
1478 | EXPORT_SYMBOL_NS_GPL(adxl367_probe, IIO_ADXL367); |
1479 | |
1480 | MODULE_AUTHOR("Cosmin Tanislav <cosmin.tanislav@analog.com>" ); |
1481 | MODULE_DESCRIPTION("Analog Devices ADXL367 3-axis accelerometer driver" ); |
1482 | MODULE_LICENSE("GPL" ); |
1483 | |