1df36de13SAntoniu Miclaus // SPDX-License-Identifier: GPL-2.0+
2df36de13SAntoniu Miclaus /*
3df36de13SAntoniu Miclaus * ADXL380 3-Axis Digital Accelerometer core driver
4df36de13SAntoniu Miclaus *
5df36de13SAntoniu Miclaus * Copyright 2024 Analog Devices Inc.
6df36de13SAntoniu Miclaus */
7df36de13SAntoniu Miclaus
8df36de13SAntoniu Miclaus #include <linux/bitfield.h>
9df36de13SAntoniu Miclaus #include <linux/interrupt.h>
10df36de13SAntoniu Miclaus #include <linux/irq.h>
11df36de13SAntoniu Miclaus #include <linux/module.h>
12df36de13SAntoniu Miclaus #include <linux/property.h>
13df36de13SAntoniu Miclaus #include <linux/regmap.h>
14df36de13SAntoniu Miclaus #include <linux/units.h>
15df36de13SAntoniu Miclaus
16*5f60d5f6SAl Viro #include <linux/unaligned.h>
17df36de13SAntoniu Miclaus
18df36de13SAntoniu Miclaus #include <linux/iio/buffer.h>
19df36de13SAntoniu Miclaus #include <linux/iio/events.h>
20df36de13SAntoniu Miclaus #include <linux/iio/iio.h>
21df36de13SAntoniu Miclaus #include <linux/iio/kfifo_buf.h>
22df36de13SAntoniu Miclaus #include <linux/iio/sysfs.h>
23df36de13SAntoniu Miclaus
24df36de13SAntoniu Miclaus #include <linux/regulator/consumer.h>
25df36de13SAntoniu Miclaus
26df36de13SAntoniu Miclaus #include "adxl380.h"
27df36de13SAntoniu Miclaus
28df36de13SAntoniu Miclaus #define ADXL380_ID_VAL 380
29df36de13SAntoniu Miclaus #define ADXL382_ID_VAL 382
30df36de13SAntoniu Miclaus
31df36de13SAntoniu Miclaus #define ADXL380_DEVID_AD_REG 0x00
32df36de13SAntoniu Miclaus #define ADLX380_PART_ID_REG 0x02
33df36de13SAntoniu Miclaus
34df36de13SAntoniu Miclaus #define ADXL380_X_DATA_H_REG 0x15
35df36de13SAntoniu Miclaus #define ADXL380_Y_DATA_H_REG 0x17
36df36de13SAntoniu Miclaus #define ADXL380_Z_DATA_H_REG 0x19
37df36de13SAntoniu Miclaus #define ADXL380_T_DATA_H_REG 0x1B
38df36de13SAntoniu Miclaus
39df36de13SAntoniu Miclaus #define ADXL380_MISC_0_REG 0x20
40df36de13SAntoniu Miclaus #define ADXL380_XL382_MSK BIT(7)
41df36de13SAntoniu Miclaus
42df36de13SAntoniu Miclaus #define ADXL380_MISC_1_REG 0x21
43df36de13SAntoniu Miclaus
44df36de13SAntoniu Miclaus #define ADXL380_X_DSM_OFFSET_REG 0x4D
45df36de13SAntoniu Miclaus
46df36de13SAntoniu Miclaus #define ADXL380_ACT_INACT_CTL_REG 0x37
47df36de13SAntoniu Miclaus #define ADXL380_INACT_EN_MSK BIT(2)
48df36de13SAntoniu Miclaus #define ADXL380_ACT_EN_MSK BIT(0)
49df36de13SAntoniu Miclaus
50df36de13SAntoniu Miclaus #define ADXL380_SNSR_AXIS_EN_REG 0x38
51df36de13SAntoniu Miclaus #define ADXL380_ACT_INACT_AXIS_EN_MSK GENMASK(2, 0)
52df36de13SAntoniu Miclaus
53df36de13SAntoniu Miclaus #define ADXL380_THRESH_ACT_H_REG 0x39
54df36de13SAntoniu Miclaus #define ADXL380_TIME_ACT_H_REG 0x3B
55df36de13SAntoniu Miclaus #define ADXL380_THRESH_INACT_H_REG 0x3E
56df36de13SAntoniu Miclaus #define ADXL380_TIME_INACT_H_REG 0x40
57df36de13SAntoniu Miclaus #define ADXL380_THRESH_MAX GENMASK(12, 0)
58df36de13SAntoniu Miclaus #define ADXL380_TIME_MAX GENMASK(24, 0)
59df36de13SAntoniu Miclaus
60df36de13SAntoniu Miclaus #define ADXL380_FIFO_CONFIG_0_REG 0x30
61df36de13SAntoniu Miclaus #define ADXL380_FIFO_SAMPLES_8_MSK BIT(0)
62df36de13SAntoniu Miclaus #define ADXL380_FIFO_MODE_MSK GENMASK(5, 4)
63df36de13SAntoniu Miclaus
64df36de13SAntoniu Miclaus #define ADXL380_FIFO_DISABLED 0
65df36de13SAntoniu Miclaus #define ADXL380_FIFO_NORMAL 1
66df36de13SAntoniu Miclaus #define ADXL380_FIFO_STREAMED 2
67df36de13SAntoniu Miclaus #define ADXL380_FIFO_TRIGGERED 3
68df36de13SAntoniu Miclaus
69df36de13SAntoniu Miclaus #define ADXL380_FIFO_CONFIG_1_REG 0x31
70df36de13SAntoniu Miclaus #define ADXL380_FIFO_STATUS_0_REG 0x1E
71df36de13SAntoniu Miclaus
72df36de13SAntoniu Miclaus #define ADXL380_TAP_THRESH_REG 0x43
73df36de13SAntoniu Miclaus #define ADXL380_TAP_DUR_REG 0x44
74df36de13SAntoniu Miclaus #define ADXL380_TAP_LATENT_REG 0x45
75df36de13SAntoniu Miclaus #define ADXL380_TAP_WINDOW_REG 0x46
76df36de13SAntoniu Miclaus #define ADXL380_TAP_TIME_MAX GENMASK(7, 0)
77df36de13SAntoniu Miclaus
78df36de13SAntoniu Miclaus #define ADXL380_TAP_CFG_REG 0x47
79df36de13SAntoniu Miclaus #define ADXL380_TAP_AXIS_MSK GENMASK(1, 0)
80df36de13SAntoniu Miclaus
81df36de13SAntoniu Miclaus #define ADXL380_TRIG_CFG_REG 0x49
82df36de13SAntoniu Miclaus #define ADXL380_TRIG_CFG_DEC_2X_MSK BIT(7)
83df36de13SAntoniu Miclaus #define ADXL380_TRIG_CFG_SINC_RATE_MSK BIT(6)
84df36de13SAntoniu Miclaus
85df36de13SAntoniu Miclaus #define ADXL380_FILTER_REG 0x50
86df36de13SAntoniu Miclaus #define ADXL380_FILTER_EQ_FILT_MSK BIT(6)
87df36de13SAntoniu Miclaus #define ADXL380_FILTER_LPF_MODE_MSK GENMASK(5, 4)
88df36de13SAntoniu Miclaus #define ADXL380_FILTER_HPF_PATH_MSK BIT(3)
89df36de13SAntoniu Miclaus #define ADXL380_FILTER_HPF_CORNER_MSK GENMASK(2, 0)
90df36de13SAntoniu Miclaus
91df36de13SAntoniu Miclaus #define ADXL380_OP_MODE_REG 0x26
92df36de13SAntoniu Miclaus #define ADXL380_OP_MODE_RANGE_MSK GENMASK(7, 6)
93df36de13SAntoniu Miclaus #define ADXL380_OP_MODE_MSK GENMASK(3, 0)
94df36de13SAntoniu Miclaus #define ADXL380_OP_MODE_STANDBY 0
95df36de13SAntoniu Miclaus #define ADXL380_OP_MODE_HEART_SOUND 1
96df36de13SAntoniu Miclaus #define ADXL380_OP_MODE_ULP 2
97df36de13SAntoniu Miclaus #define ADXL380_OP_MODE_VLP 3
98df36de13SAntoniu Miclaus #define ADXL380_OP_MODE_LP 4
99df36de13SAntoniu Miclaus #define ADXL380_OP_MODE_LP_ULP 6
100df36de13SAntoniu Miclaus #define ADXL380_OP_MODE_LP_VLP 7
101df36de13SAntoniu Miclaus #define ADXL380_OP_MODE_RBW 8
102df36de13SAntoniu Miclaus #define ADXL380_OP_MODE_RBW_ULP 10
103df36de13SAntoniu Miclaus #define ADXL380_OP_MODE_RBW_VLP 11
104df36de13SAntoniu Miclaus #define ADXL380_OP_MODE_HP 12
105df36de13SAntoniu Miclaus #define ADXL380_OP_MODE_HP_ULP 14
106df36de13SAntoniu Miclaus #define ADXL380_OP_MODE_HP_VLP 15
107df36de13SAntoniu Miclaus
108df36de13SAntoniu Miclaus #define ADXL380_OP_MODE_4G_RANGE 0
109df36de13SAntoniu Miclaus #define ADXL382_OP_MODE_15G_RANGE 0
110df36de13SAntoniu Miclaus #define ADXL380_OP_MODE_8G_RANGE 1
111df36de13SAntoniu Miclaus #define ADXL382_OP_MODE_30G_RANGE 1
112df36de13SAntoniu Miclaus #define ADXL380_OP_MODE_16G_RANGE 2
113df36de13SAntoniu Miclaus #define ADXL382_OP_MODE_60G_RANGE 2
114df36de13SAntoniu Miclaus
115df36de13SAntoniu Miclaus #define ADXL380_DIG_EN_REG 0x27
116df36de13SAntoniu Miclaus #define ADXL380_CHAN_EN_MSK(chan) BIT(4 + (chan))
117df36de13SAntoniu Miclaus #define ADXL380_FIFO_EN_MSK BIT(3)
118df36de13SAntoniu Miclaus
119df36de13SAntoniu Miclaus #define ADXL380_INT0_MAP0_REG 0x2B
120df36de13SAntoniu Miclaus #define ADXL380_INT1_MAP0_REG 0x2D
121df36de13SAntoniu Miclaus #define ADXL380_INT_MAP0_INACT_INT0_MSK BIT(6)
122df36de13SAntoniu Miclaus #define ADXL380_INT_MAP0_ACT_INT0_MSK BIT(5)
123df36de13SAntoniu Miclaus #define ADXL380_INT_MAP0_FIFO_WM_INT0_MSK BIT(3)
124df36de13SAntoniu Miclaus
125df36de13SAntoniu Miclaus #define ADXL380_INT0_MAP1_REG 0x2C
126df36de13SAntoniu Miclaus #define ADXL380_INT1_MAP1_REG 0x2E
127df36de13SAntoniu Miclaus #define ADXL380_INT_MAP1_DOUBLE_TAP_INT0_MSK BIT(1)
128df36de13SAntoniu Miclaus #define ADXL380_INT_MAP1_SINGLE_TAP_INT0_MSK BIT(0)
129df36de13SAntoniu Miclaus
130df36de13SAntoniu Miclaus #define ADXL380_INT0_REG 0x5D
131df36de13SAntoniu Miclaus #define ADXL380_INT0_POL_MSK BIT(7)
132df36de13SAntoniu Miclaus
133df36de13SAntoniu Miclaus #define ADXL380_RESET_REG 0x2A
134df36de13SAntoniu Miclaus #define ADXL380_FIFO_DATA 0x1D
135df36de13SAntoniu Miclaus
136df36de13SAntoniu Miclaus #define ADXL380_DEVID_AD_VAL 0xAD
137df36de13SAntoniu Miclaus #define ADXL380_RESET_CODE 0x52
138df36de13SAntoniu Miclaus
139df36de13SAntoniu Miclaus #define ADXL380_STATUS_0_REG 0x11
140df36de13SAntoniu Miclaus #define ADXL380_STATUS_0_FIFO_FULL_MSK BIT(1)
141df36de13SAntoniu Miclaus #define ADXL380_STATUS_0_FIFO_WM_MSK BIT(3)
142df36de13SAntoniu Miclaus
143df36de13SAntoniu Miclaus #define ADXL380_STATUS_1_INACT_MSK BIT(6)
144df36de13SAntoniu Miclaus #define ADXL380_STATUS_1_ACT_MSK BIT(5)
145df36de13SAntoniu Miclaus #define ADXL380_STATUS_1_DOUBLE_TAP_MSK BIT(1)
146df36de13SAntoniu Miclaus #define ADXL380_STATUS_1_SINGLE_TAP_MSK BIT(0)
147df36de13SAntoniu Miclaus
148df36de13SAntoniu Miclaus #define ADXL380_FIFO_SAMPLES 315UL
149df36de13SAntoniu Miclaus
150df36de13SAntoniu Miclaus enum adxl380_channels {
151df36de13SAntoniu Miclaus ADXL380_ACCEL_X,
152df36de13SAntoniu Miclaus ADXL380_ACCEL_Y,
153df36de13SAntoniu Miclaus ADXL380_ACCEL_Z,
154df36de13SAntoniu Miclaus ADXL380_TEMP,
155df36de13SAntoniu Miclaus ADXL380_CH_NUM
156df36de13SAntoniu Miclaus };
157df36de13SAntoniu Miclaus
158df36de13SAntoniu Miclaus enum adxl380_axis {
159df36de13SAntoniu Miclaus ADXL380_X_AXIS,
160df36de13SAntoniu Miclaus ADXL380_Y_AXIS,
161df36de13SAntoniu Miclaus ADXL380_Z_AXIS,
162df36de13SAntoniu Miclaus };
163df36de13SAntoniu Miclaus
164df36de13SAntoniu Miclaus enum adxl380_activity_type {
165df36de13SAntoniu Miclaus ADXL380_ACTIVITY,
166df36de13SAntoniu Miclaus ADXL380_INACTIVITY,
167df36de13SAntoniu Miclaus };
168df36de13SAntoniu Miclaus
169df36de13SAntoniu Miclaus enum adxl380_tap_type {
170df36de13SAntoniu Miclaus ADXL380_SINGLE_TAP,
171df36de13SAntoniu Miclaus ADXL380_DOUBLE_TAP,
172df36de13SAntoniu Miclaus };
173df36de13SAntoniu Miclaus
174df36de13SAntoniu Miclaus enum adxl380_tap_time_type {
175df36de13SAntoniu Miclaus ADXL380_TAP_TIME_LATENT,
176df36de13SAntoniu Miclaus ADXL380_TAP_TIME_WINDOW,
177df36de13SAntoniu Miclaus };
178df36de13SAntoniu Miclaus
179df36de13SAntoniu Miclaus static const int adxl380_range_scale_factor_tbl[] = { 1, 2, 4 };
180df36de13SAntoniu Miclaus
181df36de13SAntoniu Miclaus const struct adxl380_chip_info adxl380_chip_info = {
182df36de13SAntoniu Miclaus .name = "adxl380",
183df36de13SAntoniu Miclaus .chip_id = ADXL380_ID_VAL,
184df36de13SAntoniu Miclaus .scale_tbl = {
185df36de13SAntoniu Miclaus [ADXL380_OP_MODE_4G_RANGE] = { 0, 1307226 },
186df36de13SAntoniu Miclaus [ADXL380_OP_MODE_8G_RANGE] = { 0, 2615434 },
187df36de13SAntoniu Miclaus [ADXL380_OP_MODE_16G_RANGE] = { 0, 5229886 },
188df36de13SAntoniu Miclaus },
189df36de13SAntoniu Miclaus .samp_freq_tbl = { 8000, 16000, 32000 },
190df36de13SAntoniu Miclaus /*
191df36de13SAntoniu Miclaus * The datasheet defines an intercept of 470 LSB at 25 degC
192df36de13SAntoniu Miclaus * and a sensitivity of 10.2 LSB/C.
193df36de13SAntoniu Miclaus */
194df36de13SAntoniu Miclaus .temp_offset = 25 * 102 / 10 - 470,
195df36de13SAntoniu Miclaus
196df36de13SAntoniu Miclaus };
197df36de13SAntoniu Miclaus EXPORT_SYMBOL_NS_GPL(adxl380_chip_info, IIO_ADXL380);
198df36de13SAntoniu Miclaus
199df36de13SAntoniu Miclaus const struct adxl380_chip_info adxl382_chip_info = {
200df36de13SAntoniu Miclaus .name = "adxl382",
201df36de13SAntoniu Miclaus .chip_id = ADXL382_ID_VAL,
202df36de13SAntoniu Miclaus .scale_tbl = {
203df36de13SAntoniu Miclaus [ADXL382_OP_MODE_15G_RANGE] = { 0, 4903325 },
204df36de13SAntoniu Miclaus [ADXL382_OP_MODE_30G_RANGE] = { 0, 9806650 },
205df36de13SAntoniu Miclaus [ADXL382_OP_MODE_60G_RANGE] = { 0, 19613300 },
206df36de13SAntoniu Miclaus },
207df36de13SAntoniu Miclaus .samp_freq_tbl = { 16000, 32000, 64000 },
208df36de13SAntoniu Miclaus /*
209df36de13SAntoniu Miclaus * The datasheet defines an intercept of 570 LSB at 25 degC
210df36de13SAntoniu Miclaus * and a sensitivity of 10.2 LSB/C.
211df36de13SAntoniu Miclaus */
212df36de13SAntoniu Miclaus .temp_offset = 25 * 102 / 10 - 570,
213df36de13SAntoniu Miclaus };
214df36de13SAntoniu Miclaus EXPORT_SYMBOL_NS_GPL(adxl382_chip_info, IIO_ADXL380);
215df36de13SAntoniu Miclaus
216df36de13SAntoniu Miclaus static const unsigned int adxl380_th_reg_high_addr[2] = {
217df36de13SAntoniu Miclaus [ADXL380_ACTIVITY] = ADXL380_THRESH_ACT_H_REG,
218df36de13SAntoniu Miclaus [ADXL380_INACTIVITY] = ADXL380_THRESH_INACT_H_REG,
219df36de13SAntoniu Miclaus };
220df36de13SAntoniu Miclaus
221df36de13SAntoniu Miclaus static const unsigned int adxl380_time_reg_high_addr[2] = {
222df36de13SAntoniu Miclaus [ADXL380_ACTIVITY] = ADXL380_TIME_ACT_H_REG,
223df36de13SAntoniu Miclaus [ADXL380_INACTIVITY] = ADXL380_TIME_INACT_H_REG,
224df36de13SAntoniu Miclaus };
225df36de13SAntoniu Miclaus
226df36de13SAntoniu Miclaus static const unsigned int adxl380_tap_time_reg[2] = {
227df36de13SAntoniu Miclaus [ADXL380_TAP_TIME_LATENT] = ADXL380_TAP_LATENT_REG,
228df36de13SAntoniu Miclaus [ADXL380_TAP_TIME_WINDOW] = ADXL380_TAP_WINDOW_REG,
229df36de13SAntoniu Miclaus };
230df36de13SAntoniu Miclaus
231df36de13SAntoniu Miclaus struct adxl380_state {
232df36de13SAntoniu Miclaus struct regmap *regmap;
233df36de13SAntoniu Miclaus struct device *dev;
234df36de13SAntoniu Miclaus const struct adxl380_chip_info *chip_info;
235df36de13SAntoniu Miclaus /*
236df36de13SAntoniu Miclaus * Synchronize access to members of driver state, and ensure atomicity
237df36de13SAntoniu Miclaus * of consecutive regmap operations.
238df36de13SAntoniu Miclaus */
239df36de13SAntoniu Miclaus struct mutex lock;
240df36de13SAntoniu Miclaus enum adxl380_axis tap_axis_en;
241df36de13SAntoniu Miclaus u8 range;
242df36de13SAntoniu Miclaus u8 odr;
243df36de13SAntoniu Miclaus u8 fifo_set_size;
244df36de13SAntoniu Miclaus u8 transf_buf[3];
245df36de13SAntoniu Miclaus u16 watermark;
246df36de13SAntoniu Miclaus u32 act_time_ms;
247df36de13SAntoniu Miclaus u32 act_threshold;
248df36de13SAntoniu Miclaus u32 inact_time_ms;
249df36de13SAntoniu Miclaus u32 inact_threshold;
250df36de13SAntoniu Miclaus u32 tap_latent_us;
251df36de13SAntoniu Miclaus u32 tap_window_us;
252df36de13SAntoniu Miclaus u32 tap_duration_us;
253df36de13SAntoniu Miclaus u32 tap_threshold;
254df36de13SAntoniu Miclaus int irq;
255df36de13SAntoniu Miclaus int int_map[2];
256df36de13SAntoniu Miclaus int lpf_tbl[4];
257df36de13SAntoniu Miclaus int hpf_tbl[7][2];
258df36de13SAntoniu Miclaus
259df36de13SAntoniu Miclaus __be16 fifo_buf[ADXL380_FIFO_SAMPLES] __aligned(IIO_DMA_MINALIGN);
260df36de13SAntoniu Miclaus };
261df36de13SAntoniu Miclaus
adxl380_readable_noinc_reg(struct device * dev,unsigned int reg)262df36de13SAntoniu Miclaus bool adxl380_readable_noinc_reg(struct device *dev, unsigned int reg)
263df36de13SAntoniu Miclaus {
264df36de13SAntoniu Miclaus return reg == ADXL380_FIFO_DATA;
265df36de13SAntoniu Miclaus }
266df36de13SAntoniu Miclaus EXPORT_SYMBOL_NS_GPL(adxl380_readable_noinc_reg, IIO_ADXL380);
267df36de13SAntoniu Miclaus
adxl380_set_measure_en(struct adxl380_state * st,bool en)268df36de13SAntoniu Miclaus static int adxl380_set_measure_en(struct adxl380_state *st, bool en)
269df36de13SAntoniu Miclaus {
270df36de13SAntoniu Miclaus int ret;
271df36de13SAntoniu Miclaus unsigned int act_inact_ctl;
272df36de13SAntoniu Miclaus u8 op_mode = ADXL380_OP_MODE_STANDBY;
273df36de13SAntoniu Miclaus
274df36de13SAntoniu Miclaus if (en) {
275df36de13SAntoniu Miclaus ret = regmap_read(st->regmap, ADXL380_ACT_INACT_CTL_REG, &act_inact_ctl);
276df36de13SAntoniu Miclaus if (ret)
277df36de13SAntoniu Miclaus return ret;
278df36de13SAntoniu Miclaus
279df36de13SAntoniu Miclaus /* Activity/ Inactivity detection available only in VLP/ULP mode */
280df36de13SAntoniu Miclaus if (FIELD_GET(ADXL380_ACT_EN_MSK, act_inact_ctl) ||
281df36de13SAntoniu Miclaus FIELD_GET(ADXL380_INACT_EN_MSK, act_inact_ctl))
282df36de13SAntoniu Miclaus op_mode = ADXL380_OP_MODE_VLP;
283df36de13SAntoniu Miclaus else
284df36de13SAntoniu Miclaus op_mode = ADXL380_OP_MODE_HP;
285df36de13SAntoniu Miclaus }
286df36de13SAntoniu Miclaus
287df36de13SAntoniu Miclaus return regmap_update_bits(st->regmap, ADXL380_OP_MODE_REG,
288df36de13SAntoniu Miclaus ADXL380_OP_MODE_MSK,
289df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_OP_MODE_MSK, op_mode));
290df36de13SAntoniu Miclaus }
291df36de13SAntoniu Miclaus
adxl380_scale_act_inact_thresholds(struct adxl380_state * st,u8 old_range,u8 new_range)292df36de13SAntoniu Miclaus static void adxl380_scale_act_inact_thresholds(struct adxl380_state *st,
293df36de13SAntoniu Miclaus u8 old_range,
294df36de13SAntoniu Miclaus u8 new_range)
295df36de13SAntoniu Miclaus {
296df36de13SAntoniu Miclaus st->act_threshold = mult_frac(st->act_threshold,
297df36de13SAntoniu Miclaus adxl380_range_scale_factor_tbl[old_range],
298df36de13SAntoniu Miclaus adxl380_range_scale_factor_tbl[new_range]);
299df36de13SAntoniu Miclaus st->inact_threshold = mult_frac(st->inact_threshold,
300df36de13SAntoniu Miclaus adxl380_range_scale_factor_tbl[old_range],
301df36de13SAntoniu Miclaus adxl380_range_scale_factor_tbl[new_range]);
302df36de13SAntoniu Miclaus }
303df36de13SAntoniu Miclaus
adxl380_write_act_inact_threshold(struct adxl380_state * st,enum adxl380_activity_type act,unsigned int th)304df36de13SAntoniu Miclaus static int adxl380_write_act_inact_threshold(struct adxl380_state *st,
305df36de13SAntoniu Miclaus enum adxl380_activity_type act,
306df36de13SAntoniu Miclaus unsigned int th)
307df36de13SAntoniu Miclaus {
308df36de13SAntoniu Miclaus int ret;
309df36de13SAntoniu Miclaus u8 reg = adxl380_th_reg_high_addr[act];
310df36de13SAntoniu Miclaus
311df36de13SAntoniu Miclaus if (th > ADXL380_THRESH_MAX)
312df36de13SAntoniu Miclaus return -EINVAL;
313df36de13SAntoniu Miclaus
314df36de13SAntoniu Miclaus ret = regmap_write(st->regmap, reg + 1, th & GENMASK(7, 0));
315df36de13SAntoniu Miclaus if (ret)
316df36de13SAntoniu Miclaus return ret;
317df36de13SAntoniu Miclaus
318df36de13SAntoniu Miclaus ret = regmap_update_bits(st->regmap, reg, GENMASK(2, 0), th >> 8);
319df36de13SAntoniu Miclaus if (ret)
320df36de13SAntoniu Miclaus return ret;
321df36de13SAntoniu Miclaus
322df36de13SAntoniu Miclaus if (act == ADXL380_ACTIVITY)
323df36de13SAntoniu Miclaus st->act_threshold = th;
324df36de13SAntoniu Miclaus else
325df36de13SAntoniu Miclaus st->inact_threshold = th;
326df36de13SAntoniu Miclaus
327df36de13SAntoniu Miclaus return 0;
328df36de13SAntoniu Miclaus }
329df36de13SAntoniu Miclaus
adxl380_set_act_inact_threshold(struct iio_dev * indio_dev,enum adxl380_activity_type act,u16 th)330df36de13SAntoniu Miclaus static int adxl380_set_act_inact_threshold(struct iio_dev *indio_dev,
331df36de13SAntoniu Miclaus enum adxl380_activity_type act,
332df36de13SAntoniu Miclaus u16 th)
333df36de13SAntoniu Miclaus {
334df36de13SAntoniu Miclaus struct adxl380_state *st = iio_priv(indio_dev);
335df36de13SAntoniu Miclaus int ret;
336df36de13SAntoniu Miclaus
337df36de13SAntoniu Miclaus guard(mutex)(&st->lock);
338df36de13SAntoniu Miclaus
339df36de13SAntoniu Miclaus ret = adxl380_set_measure_en(st, false);
340df36de13SAntoniu Miclaus if (ret)
341df36de13SAntoniu Miclaus return ret;
342df36de13SAntoniu Miclaus
343df36de13SAntoniu Miclaus ret = adxl380_write_act_inact_threshold(st, act, th);
344df36de13SAntoniu Miclaus if (ret)
345df36de13SAntoniu Miclaus return ret;
346df36de13SAntoniu Miclaus
347df36de13SAntoniu Miclaus return adxl380_set_measure_en(st, true);
348df36de13SAntoniu Miclaus }
349df36de13SAntoniu Miclaus
adxl380_set_tap_threshold_value(struct iio_dev * indio_dev,u8 th)350df36de13SAntoniu Miclaus static int adxl380_set_tap_threshold_value(struct iio_dev *indio_dev, u8 th)
351df36de13SAntoniu Miclaus {
352df36de13SAntoniu Miclaus int ret;
353df36de13SAntoniu Miclaus struct adxl380_state *st = iio_priv(indio_dev);
354df36de13SAntoniu Miclaus
355df36de13SAntoniu Miclaus guard(mutex)(&st->lock);
356df36de13SAntoniu Miclaus
357df36de13SAntoniu Miclaus ret = adxl380_set_measure_en(st, false);
358df36de13SAntoniu Miclaus if (ret)
359df36de13SAntoniu Miclaus return ret;
360df36de13SAntoniu Miclaus
361df36de13SAntoniu Miclaus ret = regmap_write(st->regmap, ADXL380_TAP_THRESH_REG, th);
362df36de13SAntoniu Miclaus if (ret)
363df36de13SAntoniu Miclaus return ret;
364df36de13SAntoniu Miclaus
365df36de13SAntoniu Miclaus st->tap_threshold = th;
366df36de13SAntoniu Miclaus
367df36de13SAntoniu Miclaus return adxl380_set_measure_en(st, true);
368df36de13SAntoniu Miclaus }
369df36de13SAntoniu Miclaus
_adxl380_write_tap_time_us(struct adxl380_state * st,enum adxl380_tap_time_type tap_time_type,u32 us)370df36de13SAntoniu Miclaus static int _adxl380_write_tap_time_us(struct adxl380_state *st,
371df36de13SAntoniu Miclaus enum adxl380_tap_time_type tap_time_type,
372df36de13SAntoniu Miclaus u32 us)
373df36de13SAntoniu Miclaus {
374df36de13SAntoniu Miclaus u8 reg = adxl380_tap_time_reg[tap_time_type];
375df36de13SAntoniu Miclaus unsigned int reg_val;
376df36de13SAntoniu Miclaus int ret;
377df36de13SAntoniu Miclaus
378df36de13SAntoniu Miclaus /* scale factor for tap window is 1250us / LSB */
379df36de13SAntoniu Miclaus reg_val = DIV_ROUND_CLOSEST(us, 1250);
380df36de13SAntoniu Miclaus if (reg_val > ADXL380_TAP_TIME_MAX)
381df36de13SAntoniu Miclaus reg_val = ADXL380_TAP_TIME_MAX;
382df36de13SAntoniu Miclaus
383df36de13SAntoniu Miclaus ret = regmap_write(st->regmap, reg, reg_val);
384df36de13SAntoniu Miclaus if (ret)
385df36de13SAntoniu Miclaus return ret;
386df36de13SAntoniu Miclaus
387df36de13SAntoniu Miclaus if (tap_time_type == ADXL380_TAP_TIME_WINDOW)
388df36de13SAntoniu Miclaus st->tap_window_us = us;
389df36de13SAntoniu Miclaus else
390df36de13SAntoniu Miclaus st->tap_latent_us = us;
391df36de13SAntoniu Miclaus
392df36de13SAntoniu Miclaus return 0;
393df36de13SAntoniu Miclaus }
394df36de13SAntoniu Miclaus
adxl380_write_tap_time_us(struct adxl380_state * st,enum adxl380_tap_time_type tap_time_type,u32 us)395df36de13SAntoniu Miclaus static int adxl380_write_tap_time_us(struct adxl380_state *st,
396df36de13SAntoniu Miclaus enum adxl380_tap_time_type tap_time_type, u32 us)
397df36de13SAntoniu Miclaus {
398df36de13SAntoniu Miclaus int ret;
399df36de13SAntoniu Miclaus
400df36de13SAntoniu Miclaus guard(mutex)(&st->lock);
401df36de13SAntoniu Miclaus
402df36de13SAntoniu Miclaus ret = adxl380_set_measure_en(st, false);
403df36de13SAntoniu Miclaus if (ret)
404df36de13SAntoniu Miclaus return ret;
405df36de13SAntoniu Miclaus
406df36de13SAntoniu Miclaus ret = _adxl380_write_tap_time_us(st, tap_time_type, us);
407df36de13SAntoniu Miclaus if (ret)
408df36de13SAntoniu Miclaus return ret;
409df36de13SAntoniu Miclaus
410df36de13SAntoniu Miclaus return adxl380_set_measure_en(st, true);
411df36de13SAntoniu Miclaus }
412df36de13SAntoniu Miclaus
adxl380_write_tap_dur_us(struct iio_dev * indio_dev,u32 us)413df36de13SAntoniu Miclaus static int adxl380_write_tap_dur_us(struct iio_dev *indio_dev, u32 us)
414df36de13SAntoniu Miclaus {
415df36de13SAntoniu Miclaus int ret;
416df36de13SAntoniu Miclaus unsigned int reg_val;
417df36de13SAntoniu Miclaus struct adxl380_state *st = iio_priv(indio_dev);
418df36de13SAntoniu Miclaus
419df36de13SAntoniu Miclaus /* 625us per code is the scale factor of TAP_DUR register */
420df36de13SAntoniu Miclaus reg_val = DIV_ROUND_CLOSEST(us, 625);
421df36de13SAntoniu Miclaus
422df36de13SAntoniu Miclaus ret = adxl380_set_measure_en(st, false);
423df36de13SAntoniu Miclaus if (ret)
424df36de13SAntoniu Miclaus return ret;
425df36de13SAntoniu Miclaus
426df36de13SAntoniu Miclaus ret = regmap_write(st->regmap, ADXL380_TAP_DUR_REG, reg_val);
427df36de13SAntoniu Miclaus if (ret)
428df36de13SAntoniu Miclaus return ret;
429df36de13SAntoniu Miclaus
430df36de13SAntoniu Miclaus return adxl380_set_measure_en(st, true);
431df36de13SAntoniu Miclaus }
432df36de13SAntoniu Miclaus
adxl380_read_chn(struct adxl380_state * st,u8 addr)433df36de13SAntoniu Miclaus static int adxl380_read_chn(struct adxl380_state *st, u8 addr)
434df36de13SAntoniu Miclaus {
435df36de13SAntoniu Miclaus int ret;
436df36de13SAntoniu Miclaus
437df36de13SAntoniu Miclaus guard(mutex)(&st->lock);
438df36de13SAntoniu Miclaus
439df36de13SAntoniu Miclaus ret = regmap_bulk_read(st->regmap, addr, &st->transf_buf, 2);
440df36de13SAntoniu Miclaus if (ret)
441df36de13SAntoniu Miclaus return ret;
442df36de13SAntoniu Miclaus
443df36de13SAntoniu Miclaus return get_unaligned_be16(st->transf_buf);
444df36de13SAntoniu Miclaus }
445df36de13SAntoniu Miclaus
adxl380_get_odr(struct adxl380_state * st,int * odr)446df36de13SAntoniu Miclaus static int adxl380_get_odr(struct adxl380_state *st, int *odr)
447df36de13SAntoniu Miclaus {
448df36de13SAntoniu Miclaus int ret;
449df36de13SAntoniu Miclaus unsigned int trig_cfg, odr_idx;
450df36de13SAntoniu Miclaus
451df36de13SAntoniu Miclaus ret = regmap_read(st->regmap, ADXL380_TRIG_CFG_REG, &trig_cfg);
452df36de13SAntoniu Miclaus if (ret)
453df36de13SAntoniu Miclaus return ret;
454df36de13SAntoniu Miclaus
455df36de13SAntoniu Miclaus odr_idx = (FIELD_GET(ADXL380_TRIG_CFG_SINC_RATE_MSK, trig_cfg) << 1) |
456df36de13SAntoniu Miclaus (FIELD_GET(ADXL380_TRIG_CFG_DEC_2X_MSK, trig_cfg) & 1);
457df36de13SAntoniu Miclaus
458df36de13SAntoniu Miclaus *odr = st->chip_info->samp_freq_tbl[odr_idx];
459df36de13SAntoniu Miclaus
460df36de13SAntoniu Miclaus return 0;
461df36de13SAntoniu Miclaus }
462df36de13SAntoniu Miclaus
463df36de13SAntoniu Miclaus static const int adxl380_lpf_div[] = {
464df36de13SAntoniu Miclaus 1, 4, 8, 16,
465df36de13SAntoniu Miclaus };
466df36de13SAntoniu Miclaus
adxl380_fill_lpf_tbl(struct adxl380_state * st)467df36de13SAntoniu Miclaus static int adxl380_fill_lpf_tbl(struct adxl380_state *st)
468df36de13SAntoniu Miclaus {
469df36de13SAntoniu Miclaus int ret, i;
470df36de13SAntoniu Miclaus int odr;
471df36de13SAntoniu Miclaus
472df36de13SAntoniu Miclaus ret = adxl380_get_odr(st, &odr);
473df36de13SAntoniu Miclaus if (ret)
474df36de13SAntoniu Miclaus return ret;
475df36de13SAntoniu Miclaus
476df36de13SAntoniu Miclaus for (i = 0; i < ARRAY_SIZE(st->lpf_tbl); i++)
477df36de13SAntoniu Miclaus st->lpf_tbl[i] = DIV_ROUND_CLOSEST(odr, adxl380_lpf_div[i]);
478df36de13SAntoniu Miclaus
479df36de13SAntoniu Miclaus return 0;
480df36de13SAntoniu Miclaus }
481df36de13SAntoniu Miclaus
482df36de13SAntoniu Miclaus static const int adxl380_hpf_mul[] = {
483df36de13SAntoniu Miclaus 0, 247000, 62084, 15545, 3862, 954, 238,
484df36de13SAntoniu Miclaus };
485df36de13SAntoniu Miclaus
adxl380_fill_hpf_tbl(struct adxl380_state * st)486df36de13SAntoniu Miclaus static int adxl380_fill_hpf_tbl(struct adxl380_state *st)
487df36de13SAntoniu Miclaus {
488df36de13SAntoniu Miclaus int i, ret, odr_hz;
489df36de13SAntoniu Miclaus u32 multiplier;
490df36de13SAntoniu Miclaus u64 div, rem, odr;
491df36de13SAntoniu Miclaus
492df36de13SAntoniu Miclaus ret = adxl380_get_odr(st, &odr_hz);
493df36de13SAntoniu Miclaus if (ret)
494df36de13SAntoniu Miclaus return ret;
495df36de13SAntoniu Miclaus
496df36de13SAntoniu Miclaus for (i = 0; i < ARRAY_SIZE(adxl380_hpf_mul); i++) {
497df36de13SAntoniu Miclaus odr = mul_u64_u32_shr(odr_hz, MEGA, 0);
498df36de13SAntoniu Miclaus multiplier = adxl380_hpf_mul[i];
499df36de13SAntoniu Miclaus div = div64_u64_rem(mul_u64_u32_shr(odr, multiplier, 0),
500df36de13SAntoniu Miclaus TERA * 100, &rem);
501df36de13SAntoniu Miclaus
502df36de13SAntoniu Miclaus st->hpf_tbl[i][0] = div;
503df36de13SAntoniu Miclaus st->hpf_tbl[i][1] = div_u64(rem, MEGA * 100);
504df36de13SAntoniu Miclaus }
505df36de13SAntoniu Miclaus
506df36de13SAntoniu Miclaus return 0;
507df36de13SAntoniu Miclaus }
508df36de13SAntoniu Miclaus
adxl380_set_odr(struct adxl380_state * st,u8 odr)509df36de13SAntoniu Miclaus static int adxl380_set_odr(struct adxl380_state *st, u8 odr)
510df36de13SAntoniu Miclaus {
511df36de13SAntoniu Miclaus int ret;
512df36de13SAntoniu Miclaus
513df36de13SAntoniu Miclaus guard(mutex)(&st->lock);
514df36de13SAntoniu Miclaus
515df36de13SAntoniu Miclaus ret = adxl380_set_measure_en(st, false);
516df36de13SAntoniu Miclaus if (ret)
517df36de13SAntoniu Miclaus return ret;
518df36de13SAntoniu Miclaus
519df36de13SAntoniu Miclaus ret = regmap_update_bits(st->regmap, ADXL380_TRIG_CFG_REG,
520df36de13SAntoniu Miclaus ADXL380_TRIG_CFG_DEC_2X_MSK,
521df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_TRIG_CFG_DEC_2X_MSK, odr & 1));
522df36de13SAntoniu Miclaus if (ret)
523df36de13SAntoniu Miclaus return ret;
524df36de13SAntoniu Miclaus
525df36de13SAntoniu Miclaus ret = regmap_update_bits(st->regmap, ADXL380_TRIG_CFG_REG,
526df36de13SAntoniu Miclaus ADXL380_TRIG_CFG_SINC_RATE_MSK,
527df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_TRIG_CFG_SINC_RATE_MSK, odr >> 1));
528df36de13SAntoniu Miclaus if (ret)
529df36de13SAntoniu Miclaus return ret;
530df36de13SAntoniu Miclaus
531df36de13SAntoniu Miclaus ret = adxl380_set_measure_en(st, true);
532df36de13SAntoniu Miclaus if (ret)
533df36de13SAntoniu Miclaus return ret;
534df36de13SAntoniu Miclaus
535df36de13SAntoniu Miclaus ret = adxl380_fill_lpf_tbl(st);
536df36de13SAntoniu Miclaus if (ret)
537df36de13SAntoniu Miclaus return ret;
538df36de13SAntoniu Miclaus
539df36de13SAntoniu Miclaus return adxl380_fill_hpf_tbl(st);
540df36de13SAntoniu Miclaus }
541df36de13SAntoniu Miclaus
adxl380_find_match_1d_tbl(const int * array,unsigned int size,int val)542df36de13SAntoniu Miclaus static int adxl380_find_match_1d_tbl(const int *array, unsigned int size,
543df36de13SAntoniu Miclaus int val)
544df36de13SAntoniu Miclaus {
545df36de13SAntoniu Miclaus int i;
546df36de13SAntoniu Miclaus
547df36de13SAntoniu Miclaus for (i = 0; i < size; i++) {
548df36de13SAntoniu Miclaus if (val == array[i])
549df36de13SAntoniu Miclaus return i;
550df36de13SAntoniu Miclaus }
551df36de13SAntoniu Miclaus
552df36de13SAntoniu Miclaus return size - 1;
553df36de13SAntoniu Miclaus }
554df36de13SAntoniu Miclaus
adxl380_find_match_2d_tbl(const int (* freq_tbl)[2],int n,int val,int val2)555df36de13SAntoniu Miclaus static int adxl380_find_match_2d_tbl(const int (*freq_tbl)[2], int n, int val, int val2)
556df36de13SAntoniu Miclaus {
557df36de13SAntoniu Miclaus int i;
558df36de13SAntoniu Miclaus
559df36de13SAntoniu Miclaus for (i = 0; i < n; i++) {
560df36de13SAntoniu Miclaus if (freq_tbl[i][0] == val && freq_tbl[i][1] == val2)
561df36de13SAntoniu Miclaus return i;
562df36de13SAntoniu Miclaus }
563df36de13SAntoniu Miclaus
564df36de13SAntoniu Miclaus return -EINVAL;
565df36de13SAntoniu Miclaus }
566df36de13SAntoniu Miclaus
adxl380_get_lpf(struct adxl380_state * st,int * lpf)567df36de13SAntoniu Miclaus static int adxl380_get_lpf(struct adxl380_state *st, int *lpf)
568df36de13SAntoniu Miclaus {
569df36de13SAntoniu Miclaus int ret;
570df36de13SAntoniu Miclaus unsigned int trig_cfg, lpf_idx;
571df36de13SAntoniu Miclaus
572df36de13SAntoniu Miclaus guard(mutex)(&st->lock);
573df36de13SAntoniu Miclaus
574df36de13SAntoniu Miclaus ret = regmap_read(st->regmap, ADXL380_FILTER_REG, &trig_cfg);
575df36de13SAntoniu Miclaus if (ret)
576df36de13SAntoniu Miclaus return ret;
577df36de13SAntoniu Miclaus
578df36de13SAntoniu Miclaus lpf_idx = FIELD_GET(ADXL380_FILTER_LPF_MODE_MSK, trig_cfg);
579df36de13SAntoniu Miclaus
580df36de13SAntoniu Miclaus *lpf = st->lpf_tbl[lpf_idx];
581df36de13SAntoniu Miclaus
582df36de13SAntoniu Miclaus return 0;
583df36de13SAntoniu Miclaus }
584df36de13SAntoniu Miclaus
adxl380_set_lpf(struct adxl380_state * st,u8 lpf)585df36de13SAntoniu Miclaus static int adxl380_set_lpf(struct adxl380_state *st, u8 lpf)
586df36de13SAntoniu Miclaus {
587df36de13SAntoniu Miclaus int ret;
588df36de13SAntoniu Miclaus u8 eq_bypass = 0;
589df36de13SAntoniu Miclaus
590df36de13SAntoniu Miclaus guard(mutex)(&st->lock);
591df36de13SAntoniu Miclaus
592df36de13SAntoniu Miclaus ret = adxl380_set_measure_en(st, false);
593df36de13SAntoniu Miclaus if (ret)
594df36de13SAntoniu Miclaus return ret;
595df36de13SAntoniu Miclaus
596df36de13SAntoniu Miclaus if (lpf)
597df36de13SAntoniu Miclaus eq_bypass = 1;
598df36de13SAntoniu Miclaus
599df36de13SAntoniu Miclaus ret = regmap_update_bits(st->regmap, ADXL380_FILTER_REG,
600df36de13SAntoniu Miclaus ADXL380_FILTER_EQ_FILT_MSK,
601df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_FILTER_EQ_FILT_MSK, eq_bypass));
602df36de13SAntoniu Miclaus if (ret)
603df36de13SAntoniu Miclaus return ret;
604df36de13SAntoniu Miclaus
605df36de13SAntoniu Miclaus ret = regmap_update_bits(st->regmap, ADXL380_FILTER_REG,
606df36de13SAntoniu Miclaus ADXL380_FILTER_LPF_MODE_MSK,
607df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_FILTER_LPF_MODE_MSK, lpf));
608df36de13SAntoniu Miclaus if (ret)
609df36de13SAntoniu Miclaus return ret;
610df36de13SAntoniu Miclaus
611df36de13SAntoniu Miclaus return adxl380_set_measure_en(st, true);
612df36de13SAntoniu Miclaus }
613df36de13SAntoniu Miclaus
adxl380_get_hpf(struct adxl380_state * st,int * hpf_int,int * hpf_frac)614df36de13SAntoniu Miclaus static int adxl380_get_hpf(struct adxl380_state *st, int *hpf_int, int *hpf_frac)
615df36de13SAntoniu Miclaus {
616df36de13SAntoniu Miclaus int ret;
617df36de13SAntoniu Miclaus unsigned int trig_cfg, hpf_idx;
618df36de13SAntoniu Miclaus
619df36de13SAntoniu Miclaus guard(mutex)(&st->lock);
620df36de13SAntoniu Miclaus
621df36de13SAntoniu Miclaus ret = regmap_read(st->regmap, ADXL380_FILTER_REG, &trig_cfg);
622df36de13SAntoniu Miclaus if (ret)
623df36de13SAntoniu Miclaus return ret;
624df36de13SAntoniu Miclaus
625df36de13SAntoniu Miclaus hpf_idx = FIELD_GET(ADXL380_FILTER_HPF_CORNER_MSK, trig_cfg);
626df36de13SAntoniu Miclaus
627df36de13SAntoniu Miclaus *hpf_int = st->hpf_tbl[hpf_idx][0];
628df36de13SAntoniu Miclaus *hpf_frac = st->hpf_tbl[hpf_idx][1];
629df36de13SAntoniu Miclaus
630df36de13SAntoniu Miclaus return 0;
631df36de13SAntoniu Miclaus }
632df36de13SAntoniu Miclaus
adxl380_set_hpf(struct adxl380_state * st,u8 hpf)633df36de13SAntoniu Miclaus static int adxl380_set_hpf(struct adxl380_state *st, u8 hpf)
634df36de13SAntoniu Miclaus {
635df36de13SAntoniu Miclaus int ret;
636df36de13SAntoniu Miclaus u8 hpf_path = 0;
637df36de13SAntoniu Miclaus
638df36de13SAntoniu Miclaus guard(mutex)(&st->lock);
639df36de13SAntoniu Miclaus
640df36de13SAntoniu Miclaus ret = adxl380_set_measure_en(st, false);
641df36de13SAntoniu Miclaus if (ret)
642df36de13SAntoniu Miclaus return ret;
643df36de13SAntoniu Miclaus
644df36de13SAntoniu Miclaus if (hpf)
645df36de13SAntoniu Miclaus hpf_path = 1;
646df36de13SAntoniu Miclaus
647df36de13SAntoniu Miclaus ret = regmap_update_bits(st->regmap, ADXL380_FILTER_REG,
648df36de13SAntoniu Miclaus ADXL380_FILTER_HPF_PATH_MSK,
649df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_FILTER_HPF_PATH_MSK, hpf_path));
650df36de13SAntoniu Miclaus if (ret)
651df36de13SAntoniu Miclaus return ret;
652df36de13SAntoniu Miclaus
653df36de13SAntoniu Miclaus ret = regmap_update_bits(st->regmap, ADXL380_FILTER_REG,
654df36de13SAntoniu Miclaus ADXL380_FILTER_HPF_CORNER_MSK,
655df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_FILTER_HPF_CORNER_MSK, hpf));
656df36de13SAntoniu Miclaus if (ret)
657df36de13SAntoniu Miclaus return ret;
658df36de13SAntoniu Miclaus
659df36de13SAntoniu Miclaus return adxl380_set_measure_en(st, true);
660df36de13SAntoniu Miclaus }
661df36de13SAntoniu Miclaus
_adxl380_set_act_inact_time_ms(struct adxl380_state * st,enum adxl380_activity_type act,u32 ms)662df36de13SAntoniu Miclaus static int _adxl380_set_act_inact_time_ms(struct adxl380_state *st,
663df36de13SAntoniu Miclaus enum adxl380_activity_type act,
664df36de13SAntoniu Miclaus u32 ms)
665df36de13SAntoniu Miclaus {
666df36de13SAntoniu Miclaus u8 reg = adxl380_time_reg_high_addr[act];
667df36de13SAntoniu Miclaus unsigned int reg_val;
668df36de13SAntoniu Miclaus int ret;
669df36de13SAntoniu Miclaus
670df36de13SAntoniu Miclaus /* 500us per code is the scale factor of TIME_ACT / TIME_INACT registers */
671df36de13SAntoniu Miclaus reg_val = min(DIV_ROUND_CLOSEST(ms * 1000, 500), ADXL380_TIME_MAX);
672df36de13SAntoniu Miclaus
673df36de13SAntoniu Miclaus put_unaligned_be24(reg_val, &st->transf_buf[0]);
674df36de13SAntoniu Miclaus
675df36de13SAntoniu Miclaus ret = regmap_bulk_write(st->regmap, reg, st->transf_buf, sizeof(st->transf_buf));
676df36de13SAntoniu Miclaus if (ret)
677df36de13SAntoniu Miclaus return ret;
678df36de13SAntoniu Miclaus
679df36de13SAntoniu Miclaus if (act == ADXL380_ACTIVITY)
680df36de13SAntoniu Miclaus st->act_time_ms = ms;
681df36de13SAntoniu Miclaus else
682df36de13SAntoniu Miclaus st->inact_time_ms = ms;
683df36de13SAntoniu Miclaus
684df36de13SAntoniu Miclaus return 0;
685df36de13SAntoniu Miclaus }
686df36de13SAntoniu Miclaus
adxl380_set_act_inact_time_ms(struct adxl380_state * st,enum adxl380_activity_type act,u32 ms)687df36de13SAntoniu Miclaus static int adxl380_set_act_inact_time_ms(struct adxl380_state *st,
688df36de13SAntoniu Miclaus enum adxl380_activity_type act,
689df36de13SAntoniu Miclaus u32 ms)
690df36de13SAntoniu Miclaus {
691df36de13SAntoniu Miclaus int ret;
692df36de13SAntoniu Miclaus
693df36de13SAntoniu Miclaus guard(mutex)(&st->lock);
694df36de13SAntoniu Miclaus
695df36de13SAntoniu Miclaus ret = adxl380_set_measure_en(st, false);
696df36de13SAntoniu Miclaus if (ret)
697df36de13SAntoniu Miclaus return ret;
698df36de13SAntoniu Miclaus
699df36de13SAntoniu Miclaus ret = _adxl380_set_act_inact_time_ms(st, act, ms);
700df36de13SAntoniu Miclaus if (ret)
701df36de13SAntoniu Miclaus return ret;
702df36de13SAntoniu Miclaus
703df36de13SAntoniu Miclaus return adxl380_set_measure_en(st, true);
704df36de13SAntoniu Miclaus }
705df36de13SAntoniu Miclaus
adxl380_set_range(struct adxl380_state * st,u8 range)706df36de13SAntoniu Miclaus static int adxl380_set_range(struct adxl380_state *st, u8 range)
707df36de13SAntoniu Miclaus {
708df36de13SAntoniu Miclaus int ret;
709df36de13SAntoniu Miclaus
710df36de13SAntoniu Miclaus guard(mutex)(&st->lock);
711df36de13SAntoniu Miclaus
712df36de13SAntoniu Miclaus ret = adxl380_set_measure_en(st, false);
713df36de13SAntoniu Miclaus if (ret)
714df36de13SAntoniu Miclaus return ret;
715df36de13SAntoniu Miclaus
716df36de13SAntoniu Miclaus ret = regmap_update_bits(st->regmap, ADXL380_OP_MODE_REG,
717df36de13SAntoniu Miclaus ADXL380_OP_MODE_RANGE_MSK,
718df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_OP_MODE_RANGE_MSK, range));
719df36de13SAntoniu Miclaus
720df36de13SAntoniu Miclaus if (ret)
721df36de13SAntoniu Miclaus return ret;
722df36de13SAntoniu Miclaus
723df36de13SAntoniu Miclaus adxl380_scale_act_inact_thresholds(st, st->range, range);
724df36de13SAntoniu Miclaus
725df36de13SAntoniu Miclaus /* Activity thresholds depend on range */
726df36de13SAntoniu Miclaus ret = adxl380_write_act_inact_threshold(st, ADXL380_ACTIVITY,
727df36de13SAntoniu Miclaus st->act_threshold);
728df36de13SAntoniu Miclaus if (ret)
729df36de13SAntoniu Miclaus return ret;
730df36de13SAntoniu Miclaus
731df36de13SAntoniu Miclaus ret = adxl380_write_act_inact_threshold(st, ADXL380_INACTIVITY,
732df36de13SAntoniu Miclaus st->inact_threshold);
733df36de13SAntoniu Miclaus if (ret)
734df36de13SAntoniu Miclaus return ret;
735df36de13SAntoniu Miclaus
736df36de13SAntoniu Miclaus st->range = range;
737df36de13SAntoniu Miclaus
738df36de13SAntoniu Miclaus return adxl380_set_measure_en(st, true);
739df36de13SAntoniu Miclaus }
740df36de13SAntoniu Miclaus
adxl380_write_act_inact_en(struct adxl380_state * st,enum adxl380_activity_type type,bool en)741df36de13SAntoniu Miclaus static int adxl380_write_act_inact_en(struct adxl380_state *st,
742df36de13SAntoniu Miclaus enum adxl380_activity_type type,
743df36de13SAntoniu Miclaus bool en)
744df36de13SAntoniu Miclaus {
745df36de13SAntoniu Miclaus if (type == ADXL380_ACTIVITY)
746df36de13SAntoniu Miclaus return regmap_update_bits(st->regmap, ADXL380_ACT_INACT_CTL_REG,
747df36de13SAntoniu Miclaus ADXL380_ACT_EN_MSK,
748df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_ACT_EN_MSK, en));
749df36de13SAntoniu Miclaus
750df36de13SAntoniu Miclaus return regmap_update_bits(st->regmap, ADXL380_ACT_INACT_CTL_REG,
751df36de13SAntoniu Miclaus ADXL380_INACT_EN_MSK,
752df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_INACT_EN_MSK, en));
753df36de13SAntoniu Miclaus }
754df36de13SAntoniu Miclaus
adxl380_read_act_inact_int(struct adxl380_state * st,enum adxl380_activity_type type,bool * en)755df36de13SAntoniu Miclaus static int adxl380_read_act_inact_int(struct adxl380_state *st,
756df36de13SAntoniu Miclaus enum adxl380_activity_type type,
757df36de13SAntoniu Miclaus bool *en)
758df36de13SAntoniu Miclaus {
759df36de13SAntoniu Miclaus int ret;
760df36de13SAntoniu Miclaus unsigned int reg_val;
761df36de13SAntoniu Miclaus
762df36de13SAntoniu Miclaus guard(mutex)(&st->lock);
763df36de13SAntoniu Miclaus
764df36de13SAntoniu Miclaus ret = regmap_read(st->regmap, st->int_map[0], ®_val);
765df36de13SAntoniu Miclaus if (ret)
766df36de13SAntoniu Miclaus return ret;
767df36de13SAntoniu Miclaus
768df36de13SAntoniu Miclaus if (type == ADXL380_ACTIVITY)
769df36de13SAntoniu Miclaus *en = FIELD_GET(ADXL380_INT_MAP0_ACT_INT0_MSK, reg_val);
770df36de13SAntoniu Miclaus else
771df36de13SAntoniu Miclaus *en = FIELD_GET(ADXL380_INT_MAP0_INACT_INT0_MSK, reg_val);
772df36de13SAntoniu Miclaus
773df36de13SAntoniu Miclaus return 0;
774df36de13SAntoniu Miclaus }
775df36de13SAntoniu Miclaus
adxl380_write_act_inact_int(struct adxl380_state * st,enum adxl380_activity_type act,bool en)776df36de13SAntoniu Miclaus static int adxl380_write_act_inact_int(struct adxl380_state *st,
777df36de13SAntoniu Miclaus enum adxl380_activity_type act,
778df36de13SAntoniu Miclaus bool en)
779df36de13SAntoniu Miclaus {
780df36de13SAntoniu Miclaus if (act == ADXL380_ACTIVITY)
781df36de13SAntoniu Miclaus return regmap_update_bits(st->regmap, st->int_map[0],
782df36de13SAntoniu Miclaus ADXL380_INT_MAP0_ACT_INT0_MSK,
783df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_INT_MAP0_ACT_INT0_MSK, en));
784df36de13SAntoniu Miclaus
785df36de13SAntoniu Miclaus return regmap_update_bits(st->regmap, st->int_map[0],
786df36de13SAntoniu Miclaus ADXL380_INT_MAP0_INACT_INT0_MSK,
787df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_INT_MAP0_INACT_INT0_MSK, en));
788df36de13SAntoniu Miclaus }
789df36de13SAntoniu Miclaus
adxl380_act_inact_config(struct adxl380_state * st,enum adxl380_activity_type type,bool en)790df36de13SAntoniu Miclaus static int adxl380_act_inact_config(struct adxl380_state *st,
791df36de13SAntoniu Miclaus enum adxl380_activity_type type,
792df36de13SAntoniu Miclaus bool en)
793df36de13SAntoniu Miclaus {
794df36de13SAntoniu Miclaus int ret;
795df36de13SAntoniu Miclaus
796df36de13SAntoniu Miclaus guard(mutex)(&st->lock);
797df36de13SAntoniu Miclaus
798df36de13SAntoniu Miclaus ret = adxl380_set_measure_en(st, false);
799df36de13SAntoniu Miclaus if (ret)
800df36de13SAntoniu Miclaus return ret;
801df36de13SAntoniu Miclaus
802df36de13SAntoniu Miclaus ret = adxl380_write_act_inact_en(st, type, en);
803df36de13SAntoniu Miclaus if (ret)
804df36de13SAntoniu Miclaus return ret;
805df36de13SAntoniu Miclaus
806df36de13SAntoniu Miclaus ret = adxl380_write_act_inact_int(st, type, en);
807df36de13SAntoniu Miclaus if (ret)
808df36de13SAntoniu Miclaus return ret;
809df36de13SAntoniu Miclaus
810df36de13SAntoniu Miclaus return adxl380_set_measure_en(st, true);
811df36de13SAntoniu Miclaus }
812df36de13SAntoniu Miclaus
adxl380_write_tap_axis(struct adxl380_state * st,enum adxl380_axis axis)813df36de13SAntoniu Miclaus static int adxl380_write_tap_axis(struct adxl380_state *st,
814df36de13SAntoniu Miclaus enum adxl380_axis axis)
815df36de13SAntoniu Miclaus {
816df36de13SAntoniu Miclaus int ret;
817df36de13SAntoniu Miclaus
818df36de13SAntoniu Miclaus ret = regmap_update_bits(st->regmap, ADXL380_TAP_CFG_REG,
819df36de13SAntoniu Miclaus ADXL380_TAP_AXIS_MSK,
820df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_TAP_AXIS_MSK, axis));
821df36de13SAntoniu Miclaus
822df36de13SAntoniu Miclaus if (ret)
823df36de13SAntoniu Miclaus return ret;
824df36de13SAntoniu Miclaus
825df36de13SAntoniu Miclaus st->tap_axis_en = axis;
826df36de13SAntoniu Miclaus
827df36de13SAntoniu Miclaus return 0;
828df36de13SAntoniu Miclaus }
829df36de13SAntoniu Miclaus
adxl380_read_tap_int(struct adxl380_state * st,enum adxl380_tap_type type,bool * en)830df36de13SAntoniu Miclaus static int adxl380_read_tap_int(struct adxl380_state *st, enum adxl380_tap_type type, bool *en)
831df36de13SAntoniu Miclaus {
832df36de13SAntoniu Miclaus int ret;
833df36de13SAntoniu Miclaus unsigned int reg_val;
834df36de13SAntoniu Miclaus
835df36de13SAntoniu Miclaus ret = regmap_read(st->regmap, st->int_map[1], ®_val);
836df36de13SAntoniu Miclaus if (ret)
837df36de13SAntoniu Miclaus return ret;
838df36de13SAntoniu Miclaus
839df36de13SAntoniu Miclaus if (type == ADXL380_SINGLE_TAP)
840df36de13SAntoniu Miclaus *en = FIELD_GET(ADXL380_INT_MAP1_SINGLE_TAP_INT0_MSK, reg_val);
841df36de13SAntoniu Miclaus else
842df36de13SAntoniu Miclaus *en = FIELD_GET(ADXL380_INT_MAP1_DOUBLE_TAP_INT0_MSK, reg_val);
843df36de13SAntoniu Miclaus
844df36de13SAntoniu Miclaus return 0;
845df36de13SAntoniu Miclaus }
846df36de13SAntoniu Miclaus
adxl380_write_tap_int(struct adxl380_state * st,enum adxl380_tap_type type,bool en)847df36de13SAntoniu Miclaus static int adxl380_write_tap_int(struct adxl380_state *st, enum adxl380_tap_type type, bool en)
848df36de13SAntoniu Miclaus {
849df36de13SAntoniu Miclaus if (type == ADXL380_SINGLE_TAP)
850df36de13SAntoniu Miclaus return regmap_update_bits(st->regmap, st->int_map[1],
851df36de13SAntoniu Miclaus ADXL380_INT_MAP1_SINGLE_TAP_INT0_MSK,
852df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_INT_MAP1_SINGLE_TAP_INT0_MSK, en));
853df36de13SAntoniu Miclaus
854df36de13SAntoniu Miclaus return regmap_update_bits(st->regmap, st->int_map[1],
855df36de13SAntoniu Miclaus ADXL380_INT_MAP1_DOUBLE_TAP_INT0_MSK,
856df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_INT_MAP1_DOUBLE_TAP_INT0_MSK, en));
857df36de13SAntoniu Miclaus }
858df36de13SAntoniu Miclaus
adxl380_tap_config(struct adxl380_state * st,enum adxl380_axis axis,enum adxl380_tap_type type,bool en)859df36de13SAntoniu Miclaus static int adxl380_tap_config(struct adxl380_state *st,
860df36de13SAntoniu Miclaus enum adxl380_axis axis,
861df36de13SAntoniu Miclaus enum adxl380_tap_type type,
862df36de13SAntoniu Miclaus bool en)
863df36de13SAntoniu Miclaus {
864df36de13SAntoniu Miclaus int ret;
865df36de13SAntoniu Miclaus
866df36de13SAntoniu Miclaus guard(mutex)(&st->lock);
867df36de13SAntoniu Miclaus
868df36de13SAntoniu Miclaus ret = adxl380_set_measure_en(st, false);
869df36de13SAntoniu Miclaus if (ret)
870df36de13SAntoniu Miclaus return ret;
871df36de13SAntoniu Miclaus
872df36de13SAntoniu Miclaus ret = adxl380_write_tap_axis(st, axis);
873df36de13SAntoniu Miclaus if (ret)
874df36de13SAntoniu Miclaus return ret;
875df36de13SAntoniu Miclaus
876df36de13SAntoniu Miclaus ret = adxl380_write_tap_int(st, type, en);
877df36de13SAntoniu Miclaus if (ret)
878df36de13SAntoniu Miclaus return ret;
879df36de13SAntoniu Miclaus
880df36de13SAntoniu Miclaus return adxl380_set_measure_en(st, true);
881df36de13SAntoniu Miclaus }
882df36de13SAntoniu Miclaus
adxl380_set_fifo_samples(struct adxl380_state * st)883df36de13SAntoniu Miclaus static int adxl380_set_fifo_samples(struct adxl380_state *st)
884df36de13SAntoniu Miclaus {
885df36de13SAntoniu Miclaus int ret;
886df36de13SAntoniu Miclaus u16 fifo_samples = st->watermark * st->fifo_set_size;
887df36de13SAntoniu Miclaus
888df36de13SAntoniu Miclaus ret = regmap_update_bits(st->regmap, ADXL380_FIFO_CONFIG_0_REG,
889df36de13SAntoniu Miclaus ADXL380_FIFO_SAMPLES_8_MSK,
890df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_FIFO_SAMPLES_8_MSK,
891df36de13SAntoniu Miclaus (fifo_samples & BIT(8))));
892df36de13SAntoniu Miclaus if (ret)
893df36de13SAntoniu Miclaus return ret;
894df36de13SAntoniu Miclaus
895df36de13SAntoniu Miclaus return regmap_write(st->regmap, ADXL380_FIFO_CONFIG_1_REG,
896df36de13SAntoniu Miclaus fifo_samples & 0xFF);
897df36de13SAntoniu Miclaus }
898df36de13SAntoniu Miclaus
adxl380_get_status(struct adxl380_state * st,u8 * status0,u8 * status1)899df36de13SAntoniu Miclaus static int adxl380_get_status(struct adxl380_state *st, u8 *status0, u8 *status1)
900df36de13SAntoniu Miclaus {
901df36de13SAntoniu Miclaus int ret;
902df36de13SAntoniu Miclaus
903df36de13SAntoniu Miclaus /* STATUS0, STATUS1 are adjacent regs */
904df36de13SAntoniu Miclaus ret = regmap_bulk_read(st->regmap, ADXL380_STATUS_0_REG,
905df36de13SAntoniu Miclaus &st->transf_buf, 2);
906df36de13SAntoniu Miclaus if (ret)
907df36de13SAntoniu Miclaus return ret;
908df36de13SAntoniu Miclaus
909df36de13SAntoniu Miclaus *status0 = st->transf_buf[0];
910df36de13SAntoniu Miclaus *status1 = st->transf_buf[1];
911df36de13SAntoniu Miclaus
912df36de13SAntoniu Miclaus return 0;
913df36de13SAntoniu Miclaus }
914df36de13SAntoniu Miclaus
adxl380_get_fifo_entries(struct adxl380_state * st,u16 * fifo_entries)915df36de13SAntoniu Miclaus static int adxl380_get_fifo_entries(struct adxl380_state *st, u16 *fifo_entries)
916df36de13SAntoniu Miclaus {
917df36de13SAntoniu Miclaus int ret;
918df36de13SAntoniu Miclaus
919df36de13SAntoniu Miclaus ret = regmap_bulk_read(st->regmap, ADXL380_FIFO_STATUS_0_REG,
920df36de13SAntoniu Miclaus &st->transf_buf, 2);
921df36de13SAntoniu Miclaus if (ret)
922df36de13SAntoniu Miclaus return ret;
923df36de13SAntoniu Miclaus
924df36de13SAntoniu Miclaus *fifo_entries = st->transf_buf[0] | ((BIT(0) & st->transf_buf[1]) << 8);
925df36de13SAntoniu Miclaus
926df36de13SAntoniu Miclaus return 0;
927df36de13SAntoniu Miclaus }
928df36de13SAntoniu Miclaus
adxl380_push_event(struct iio_dev * indio_dev,s64 timestamp,u8 status1)929df36de13SAntoniu Miclaus static void adxl380_push_event(struct iio_dev *indio_dev, s64 timestamp,
930df36de13SAntoniu Miclaus u8 status1)
931df36de13SAntoniu Miclaus {
932df36de13SAntoniu Miclaus if (FIELD_GET(ADXL380_STATUS_1_ACT_MSK, status1))
933df36de13SAntoniu Miclaus iio_push_event(indio_dev,
934df36de13SAntoniu Miclaus IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z,
935df36de13SAntoniu Miclaus IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),
936df36de13SAntoniu Miclaus timestamp);
937df36de13SAntoniu Miclaus
938df36de13SAntoniu Miclaus if (FIELD_GET(ADXL380_STATUS_1_INACT_MSK, status1))
939df36de13SAntoniu Miclaus iio_push_event(indio_dev,
940df36de13SAntoniu Miclaus IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z,
941df36de13SAntoniu Miclaus IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING),
942df36de13SAntoniu Miclaus timestamp);
943df36de13SAntoniu Miclaus if (FIELD_GET(ADXL380_STATUS_1_SINGLE_TAP_MSK, status1))
944df36de13SAntoniu Miclaus iio_push_event(indio_dev,
945df36de13SAntoniu Miclaus IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z,
946df36de13SAntoniu Miclaus IIO_EV_TYPE_GESTURE, IIO_EV_DIR_SINGLETAP),
947df36de13SAntoniu Miclaus timestamp);
948df36de13SAntoniu Miclaus
949df36de13SAntoniu Miclaus if (FIELD_GET(ADXL380_STATUS_1_DOUBLE_TAP_MSK, status1))
950df36de13SAntoniu Miclaus iio_push_event(indio_dev,
951df36de13SAntoniu Miclaus IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z,
952df36de13SAntoniu Miclaus IIO_EV_TYPE_GESTURE, IIO_EV_DIR_DOUBLETAP),
953df36de13SAntoniu Miclaus timestamp);
954df36de13SAntoniu Miclaus }
955df36de13SAntoniu Miclaus
adxl380_irq_handler(int irq,void * p)956df36de13SAntoniu Miclaus static irqreturn_t adxl380_irq_handler(int irq, void *p)
957df36de13SAntoniu Miclaus {
958df36de13SAntoniu Miclaus struct iio_dev *indio_dev = p;
959df36de13SAntoniu Miclaus struct adxl380_state *st = iio_priv(indio_dev);
960df36de13SAntoniu Miclaus u8 status0, status1;
961df36de13SAntoniu Miclaus u16 fifo_entries;
962df36de13SAntoniu Miclaus int i;
963df36de13SAntoniu Miclaus int ret;
964df36de13SAntoniu Miclaus
965df36de13SAntoniu Miclaus guard(mutex)(&st->lock);
966df36de13SAntoniu Miclaus
967df36de13SAntoniu Miclaus ret = adxl380_get_status(st, &status0, &status1);
968df36de13SAntoniu Miclaus if (ret)
969df36de13SAntoniu Miclaus return IRQ_HANDLED;
970df36de13SAntoniu Miclaus
971df36de13SAntoniu Miclaus adxl380_push_event(indio_dev, iio_get_time_ns(indio_dev), status1);
972df36de13SAntoniu Miclaus
973df36de13SAntoniu Miclaus if (!FIELD_GET(ADXL380_STATUS_0_FIFO_WM_MSK, status0))
974df36de13SAntoniu Miclaus return IRQ_HANDLED;
975df36de13SAntoniu Miclaus
976df36de13SAntoniu Miclaus ret = adxl380_get_fifo_entries(st, &fifo_entries);
977df36de13SAntoniu Miclaus if (ret)
978df36de13SAntoniu Miclaus return IRQ_HANDLED;
979df36de13SAntoniu Miclaus
980df36de13SAntoniu Miclaus for (i = 0; i < fifo_entries; i += st->fifo_set_size) {
981df36de13SAntoniu Miclaus ret = regmap_noinc_read(st->regmap, ADXL380_FIFO_DATA,
982df36de13SAntoniu Miclaus &st->fifo_buf[i],
983df36de13SAntoniu Miclaus 2 * st->fifo_set_size);
984df36de13SAntoniu Miclaus if (ret)
985df36de13SAntoniu Miclaus return IRQ_HANDLED;
986df36de13SAntoniu Miclaus iio_push_to_buffers(indio_dev, &st->fifo_buf[i]);
987df36de13SAntoniu Miclaus }
988df36de13SAntoniu Miclaus
989df36de13SAntoniu Miclaus return IRQ_HANDLED;
990df36de13SAntoniu Miclaus }
991df36de13SAntoniu Miclaus
adxl380_write_calibbias_value(struct adxl380_state * st,unsigned long chan_addr,s8 calibbias)992df36de13SAntoniu Miclaus static int adxl380_write_calibbias_value(struct adxl380_state *st,
993df36de13SAntoniu Miclaus unsigned long chan_addr,
994df36de13SAntoniu Miclaus s8 calibbias)
995df36de13SAntoniu Miclaus {
996df36de13SAntoniu Miclaus int ret;
997df36de13SAntoniu Miclaus
998df36de13SAntoniu Miclaus guard(mutex)(&st->lock);
999df36de13SAntoniu Miclaus
1000df36de13SAntoniu Miclaus ret = adxl380_set_measure_en(st, false);
1001df36de13SAntoniu Miclaus if (ret)
1002df36de13SAntoniu Miclaus return ret;
1003df36de13SAntoniu Miclaus
1004df36de13SAntoniu Miclaus ret = regmap_write(st->regmap, ADXL380_X_DSM_OFFSET_REG + chan_addr, calibbias);
1005df36de13SAntoniu Miclaus if (ret)
1006df36de13SAntoniu Miclaus return ret;
1007df36de13SAntoniu Miclaus
1008df36de13SAntoniu Miclaus return adxl380_set_measure_en(st, true);
1009df36de13SAntoniu Miclaus }
1010df36de13SAntoniu Miclaus
adxl380_read_calibbias_value(struct adxl380_state * st,unsigned long chan_addr,int * calibbias)1011df36de13SAntoniu Miclaus static int adxl380_read_calibbias_value(struct adxl380_state *st,
1012df36de13SAntoniu Miclaus unsigned long chan_addr,
1013df36de13SAntoniu Miclaus int *calibbias)
1014df36de13SAntoniu Miclaus {
1015df36de13SAntoniu Miclaus int ret;
1016df36de13SAntoniu Miclaus unsigned int reg_val;
1017df36de13SAntoniu Miclaus
1018df36de13SAntoniu Miclaus guard(mutex)(&st->lock);
1019df36de13SAntoniu Miclaus
1020df36de13SAntoniu Miclaus ret = regmap_read(st->regmap, ADXL380_X_DSM_OFFSET_REG + chan_addr, ®_val);
1021df36de13SAntoniu Miclaus if (ret)
1022df36de13SAntoniu Miclaus return ret;
1023df36de13SAntoniu Miclaus
1024df36de13SAntoniu Miclaus *calibbias = sign_extend32(reg_val, 7);
1025df36de13SAntoniu Miclaus
1026df36de13SAntoniu Miclaus return 0;
1027df36de13SAntoniu Miclaus }
1028df36de13SAntoniu Miclaus
hwfifo_watermark_min_show(struct device * dev,struct device_attribute * attr,char * buf)1029df36de13SAntoniu Miclaus static ssize_t hwfifo_watermark_min_show(struct device *dev,
1030df36de13SAntoniu Miclaus struct device_attribute *attr,
1031df36de13SAntoniu Miclaus char *buf)
1032df36de13SAntoniu Miclaus {
1033df36de13SAntoniu Miclaus return sysfs_emit(buf, "1\n");
1034df36de13SAntoniu Miclaus }
1035df36de13SAntoniu Miclaus
hwfifo_watermark_max_show(struct device * dev,struct device_attribute * attr,char * buf)1036df36de13SAntoniu Miclaus static ssize_t hwfifo_watermark_max_show(struct device *dev,
1037df36de13SAntoniu Miclaus struct device_attribute *attr,
1038df36de13SAntoniu Miclaus char *buf)
1039df36de13SAntoniu Miclaus {
1040df36de13SAntoniu Miclaus return sysfs_emit(buf, "%lu\n", ADXL380_FIFO_SAMPLES);
1041df36de13SAntoniu Miclaus }
1042df36de13SAntoniu Miclaus
adxl380_get_fifo_watermark(struct device * dev,struct device_attribute * attr,char * buf)1043df36de13SAntoniu Miclaus static ssize_t adxl380_get_fifo_watermark(struct device *dev,
1044df36de13SAntoniu Miclaus struct device_attribute *attr,
1045df36de13SAntoniu Miclaus char *buf)
1046df36de13SAntoniu Miclaus {
1047df36de13SAntoniu Miclaus struct iio_dev *indio_dev = dev_to_iio_dev(dev);
1048df36de13SAntoniu Miclaus struct adxl380_state *st = iio_priv(indio_dev);
1049df36de13SAntoniu Miclaus
1050df36de13SAntoniu Miclaus return sysfs_emit(buf, "%d\n", st->watermark);
1051df36de13SAntoniu Miclaus }
1052df36de13SAntoniu Miclaus
adxl380_get_fifo_enabled(struct device * dev,struct device_attribute * attr,char * buf)1053df36de13SAntoniu Miclaus static ssize_t adxl380_get_fifo_enabled(struct device *dev,
1054df36de13SAntoniu Miclaus struct device_attribute *attr,
1055df36de13SAntoniu Miclaus char *buf)
1056df36de13SAntoniu Miclaus {
1057df36de13SAntoniu Miclaus struct iio_dev *indio_dev = dev_to_iio_dev(dev);
1058df36de13SAntoniu Miclaus struct adxl380_state *st = iio_priv(indio_dev);
1059df36de13SAntoniu Miclaus int ret;
1060df36de13SAntoniu Miclaus unsigned int reg_val;
1061df36de13SAntoniu Miclaus
1062df36de13SAntoniu Miclaus ret = regmap_read(st->regmap, ADXL380_DIG_EN_REG, ®_val);
1063df36de13SAntoniu Miclaus if (ret)
1064df36de13SAntoniu Miclaus return ret;
1065df36de13SAntoniu Miclaus
1066df36de13SAntoniu Miclaus return sysfs_emit(buf, "%lu\n",
1067df36de13SAntoniu Miclaus FIELD_GET(ADXL380_FIFO_EN_MSK, reg_val));
1068df36de13SAntoniu Miclaus }
1069df36de13SAntoniu Miclaus
1070df36de13SAntoniu Miclaus static IIO_DEVICE_ATTR_RO(hwfifo_watermark_min, 0);
1071df36de13SAntoniu Miclaus static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0);
1072df36de13SAntoniu Miclaus static IIO_DEVICE_ATTR(hwfifo_watermark, 0444,
1073df36de13SAntoniu Miclaus adxl380_get_fifo_watermark, NULL, 0);
1074df36de13SAntoniu Miclaus static IIO_DEVICE_ATTR(hwfifo_enabled, 0444,
1075df36de13SAntoniu Miclaus adxl380_get_fifo_enabled, NULL, 0);
1076df36de13SAntoniu Miclaus
1077df36de13SAntoniu Miclaus static const struct iio_dev_attr *adxl380_fifo_attributes[] = {
1078df36de13SAntoniu Miclaus &iio_dev_attr_hwfifo_watermark_min,
1079df36de13SAntoniu Miclaus &iio_dev_attr_hwfifo_watermark_max,
1080df36de13SAntoniu Miclaus &iio_dev_attr_hwfifo_watermark,
1081df36de13SAntoniu Miclaus &iio_dev_attr_hwfifo_enabled,
1082df36de13SAntoniu Miclaus NULL
1083df36de13SAntoniu Miclaus };
1084df36de13SAntoniu Miclaus
adxl380_buffer_postenable(struct iio_dev * indio_dev)1085df36de13SAntoniu Miclaus static int adxl380_buffer_postenable(struct iio_dev *indio_dev)
1086df36de13SAntoniu Miclaus {
1087df36de13SAntoniu Miclaus struct adxl380_state *st = iio_priv(indio_dev);
1088df36de13SAntoniu Miclaus int i;
1089df36de13SAntoniu Miclaus int ret;
1090df36de13SAntoniu Miclaus
1091df36de13SAntoniu Miclaus guard(mutex)(&st->lock);
1092df36de13SAntoniu Miclaus
1093df36de13SAntoniu Miclaus ret = adxl380_set_measure_en(st, false);
1094df36de13SAntoniu Miclaus if (ret)
1095df36de13SAntoniu Miclaus return ret;
1096df36de13SAntoniu Miclaus
1097df36de13SAntoniu Miclaus ret = regmap_update_bits(st->regmap,
1098df36de13SAntoniu Miclaus st->int_map[0],
1099df36de13SAntoniu Miclaus ADXL380_INT_MAP0_FIFO_WM_INT0_MSK,
1100df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_INT_MAP0_FIFO_WM_INT0_MSK, 1));
1101df36de13SAntoniu Miclaus if (ret)
1102df36de13SAntoniu Miclaus return ret;
1103df36de13SAntoniu Miclaus
1104df36de13SAntoniu Miclaus for_each_clear_bit(i, indio_dev->active_scan_mask, ADXL380_CH_NUM) {
1105df36de13SAntoniu Miclaus ret = regmap_update_bits(st->regmap, ADXL380_DIG_EN_REG,
1106df36de13SAntoniu Miclaus ADXL380_CHAN_EN_MSK(i),
1107df36de13SAntoniu Miclaus 0 << (4 + i));
1108df36de13SAntoniu Miclaus if (ret)
1109df36de13SAntoniu Miclaus return ret;
1110df36de13SAntoniu Miclaus }
1111df36de13SAntoniu Miclaus
1112df36de13SAntoniu Miclaus st->fifo_set_size = bitmap_weight(indio_dev->active_scan_mask,
1113c6e4112cSNuno Sa iio_get_masklength(indio_dev));
1114df36de13SAntoniu Miclaus
1115df36de13SAntoniu Miclaus if ((st->watermark * st->fifo_set_size) > ADXL380_FIFO_SAMPLES)
1116df36de13SAntoniu Miclaus st->watermark = (ADXL380_FIFO_SAMPLES / st->fifo_set_size);
1117df36de13SAntoniu Miclaus
1118df36de13SAntoniu Miclaus ret = adxl380_set_fifo_samples(st);
1119df36de13SAntoniu Miclaus if (ret)
1120df36de13SAntoniu Miclaus return ret;
1121df36de13SAntoniu Miclaus
1122df36de13SAntoniu Miclaus ret = regmap_update_bits(st->regmap, ADXL380_DIG_EN_REG, ADXL380_FIFO_EN_MSK,
1123df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_FIFO_EN_MSK, 1));
1124df36de13SAntoniu Miclaus if (ret)
1125df36de13SAntoniu Miclaus return ret;
1126df36de13SAntoniu Miclaus
1127df36de13SAntoniu Miclaus return adxl380_set_measure_en(st, true);
1128df36de13SAntoniu Miclaus }
1129df36de13SAntoniu Miclaus
adxl380_buffer_predisable(struct iio_dev * indio_dev)1130df36de13SAntoniu Miclaus static int adxl380_buffer_predisable(struct iio_dev *indio_dev)
1131df36de13SAntoniu Miclaus {
1132df36de13SAntoniu Miclaus struct adxl380_state *st = iio_priv(indio_dev);
1133df36de13SAntoniu Miclaus int ret, i;
1134df36de13SAntoniu Miclaus
1135df36de13SAntoniu Miclaus guard(mutex)(&st->lock);
1136df36de13SAntoniu Miclaus
1137df36de13SAntoniu Miclaus ret = adxl380_set_measure_en(st, false);
1138df36de13SAntoniu Miclaus if (ret)
1139df36de13SAntoniu Miclaus return ret;
1140df36de13SAntoniu Miclaus
1141df36de13SAntoniu Miclaus ret = regmap_update_bits(st->regmap,
1142df36de13SAntoniu Miclaus st->int_map[0],
1143df36de13SAntoniu Miclaus ADXL380_INT_MAP0_FIFO_WM_INT0_MSK,
1144df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_INT_MAP0_FIFO_WM_INT0_MSK, 0));
1145df36de13SAntoniu Miclaus if (ret)
1146df36de13SAntoniu Miclaus return ret;
1147df36de13SAntoniu Miclaus
1148df36de13SAntoniu Miclaus for (i = 0; i < indio_dev->num_channels; i++) {
1149df36de13SAntoniu Miclaus ret = regmap_update_bits(st->regmap, ADXL380_DIG_EN_REG,
1150df36de13SAntoniu Miclaus ADXL380_CHAN_EN_MSK(i),
1151df36de13SAntoniu Miclaus 1 << (4 + i));
1152df36de13SAntoniu Miclaus if (ret)
1153df36de13SAntoniu Miclaus return ret;
1154df36de13SAntoniu Miclaus }
1155df36de13SAntoniu Miclaus
1156df36de13SAntoniu Miclaus ret = regmap_update_bits(st->regmap, ADXL380_DIG_EN_REG, ADXL380_FIFO_EN_MSK,
1157df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_FIFO_EN_MSK, 0));
1158df36de13SAntoniu Miclaus if (ret)
1159df36de13SAntoniu Miclaus return ret;
1160df36de13SAntoniu Miclaus
1161df36de13SAntoniu Miclaus return adxl380_set_measure_en(st, true);
1162df36de13SAntoniu Miclaus }
1163df36de13SAntoniu Miclaus
1164df36de13SAntoniu Miclaus static const struct iio_buffer_setup_ops adxl380_buffer_ops = {
1165df36de13SAntoniu Miclaus .postenable = adxl380_buffer_postenable,
1166df36de13SAntoniu Miclaus .predisable = adxl380_buffer_predisable,
1167df36de13SAntoniu Miclaus };
1168df36de13SAntoniu Miclaus
adxl380_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long info)1169df36de13SAntoniu Miclaus static int adxl380_read_raw(struct iio_dev *indio_dev,
1170df36de13SAntoniu Miclaus struct iio_chan_spec const *chan,
1171df36de13SAntoniu Miclaus int *val, int *val2, long info)
1172df36de13SAntoniu Miclaus {
1173df36de13SAntoniu Miclaus struct adxl380_state *st = iio_priv(indio_dev);
1174df36de13SAntoniu Miclaus int ret;
1175df36de13SAntoniu Miclaus
1176df36de13SAntoniu Miclaus switch (info) {
1177df36de13SAntoniu Miclaus case IIO_CHAN_INFO_RAW:
1178df36de13SAntoniu Miclaus ret = iio_device_claim_direct_mode(indio_dev);
1179df36de13SAntoniu Miclaus if (ret)
1180df36de13SAntoniu Miclaus return ret;
1181df36de13SAntoniu Miclaus
1182df36de13SAntoniu Miclaus ret = adxl380_read_chn(st, chan->address);
1183df36de13SAntoniu Miclaus iio_device_release_direct_mode(indio_dev);
1184df36de13SAntoniu Miclaus if (ret)
1185df36de13SAntoniu Miclaus return ret;
1186df36de13SAntoniu Miclaus
1187df36de13SAntoniu Miclaus *val = sign_extend32(ret >> chan->scan_type.shift,
1188df36de13SAntoniu Miclaus chan->scan_type.realbits - 1);
1189df36de13SAntoniu Miclaus return IIO_VAL_INT;
1190df36de13SAntoniu Miclaus case IIO_CHAN_INFO_SCALE:
1191df36de13SAntoniu Miclaus switch (chan->type) {
1192df36de13SAntoniu Miclaus case IIO_ACCEL:
1193df36de13SAntoniu Miclaus scoped_guard(mutex, &st->lock) {
1194df36de13SAntoniu Miclaus *val = st->chip_info->scale_tbl[st->range][0];
1195df36de13SAntoniu Miclaus *val2 = st->chip_info->scale_tbl[st->range][1];
1196df36de13SAntoniu Miclaus }
1197df36de13SAntoniu Miclaus return IIO_VAL_INT_PLUS_NANO;
1198df36de13SAntoniu Miclaus case IIO_TEMP:
1199df36de13SAntoniu Miclaus /* 10.2 LSB / Degree Celsius */
1200df36de13SAntoniu Miclaus *val = 10000;
1201df36de13SAntoniu Miclaus *val2 = 102;
1202df36de13SAntoniu Miclaus return IIO_VAL_FRACTIONAL;
1203df36de13SAntoniu Miclaus default:
1204df36de13SAntoniu Miclaus return -EINVAL;
1205df36de13SAntoniu Miclaus }
1206df36de13SAntoniu Miclaus case IIO_CHAN_INFO_OFFSET:
1207df36de13SAntoniu Miclaus switch (chan->type) {
1208df36de13SAntoniu Miclaus case IIO_TEMP:
1209df36de13SAntoniu Miclaus *val = st->chip_info->temp_offset;
1210df36de13SAntoniu Miclaus return IIO_VAL_INT;
1211df36de13SAntoniu Miclaus default:
1212df36de13SAntoniu Miclaus return -EINVAL;
1213df36de13SAntoniu Miclaus }
1214df36de13SAntoniu Miclaus case IIO_CHAN_INFO_CALIBBIAS:
1215df36de13SAntoniu Miclaus switch (chan->type) {
1216df36de13SAntoniu Miclaus case IIO_ACCEL:
1217df36de13SAntoniu Miclaus ret = adxl380_read_calibbias_value(st, chan->scan_index, val);
1218df36de13SAntoniu Miclaus if (ret)
1219df36de13SAntoniu Miclaus return ret;
1220df36de13SAntoniu Miclaus return IIO_VAL_INT;
1221df36de13SAntoniu Miclaus default:
1222df36de13SAntoniu Miclaus return -EINVAL;
1223df36de13SAntoniu Miclaus }
1224df36de13SAntoniu Miclaus case IIO_CHAN_INFO_SAMP_FREQ:
1225df36de13SAntoniu Miclaus ret = adxl380_get_odr(st, val);
1226df36de13SAntoniu Miclaus if (ret)
1227df36de13SAntoniu Miclaus return ret;
1228df36de13SAntoniu Miclaus return IIO_VAL_INT;
1229df36de13SAntoniu Miclaus case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
1230df36de13SAntoniu Miclaus ret = adxl380_get_lpf(st, val);
1231df36de13SAntoniu Miclaus if (ret)
1232df36de13SAntoniu Miclaus return ret;
1233df36de13SAntoniu Miclaus return IIO_VAL_INT;
1234df36de13SAntoniu Miclaus case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
1235df36de13SAntoniu Miclaus ret = adxl380_get_hpf(st, val, val2);
1236df36de13SAntoniu Miclaus if (ret)
1237df36de13SAntoniu Miclaus return ret;
1238df36de13SAntoniu Miclaus return IIO_VAL_INT_PLUS_MICRO;
1239df36de13SAntoniu Miclaus }
1240df36de13SAntoniu Miclaus
1241df36de13SAntoniu Miclaus return -EINVAL;
1242df36de13SAntoniu Miclaus }
1243df36de13SAntoniu Miclaus
adxl380_read_avail(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,const int ** vals,int * type,int * length,long mask)1244df36de13SAntoniu Miclaus static int adxl380_read_avail(struct iio_dev *indio_dev,
1245df36de13SAntoniu Miclaus struct iio_chan_spec const *chan,
1246df36de13SAntoniu Miclaus const int **vals, int *type, int *length,
1247df36de13SAntoniu Miclaus long mask)
1248df36de13SAntoniu Miclaus {
1249df36de13SAntoniu Miclaus struct adxl380_state *st = iio_priv(indio_dev);
1250df36de13SAntoniu Miclaus
1251df36de13SAntoniu Miclaus if (chan->type != IIO_ACCEL)
1252df36de13SAntoniu Miclaus return -EINVAL;
1253df36de13SAntoniu Miclaus
1254df36de13SAntoniu Miclaus switch (mask) {
1255df36de13SAntoniu Miclaus case IIO_CHAN_INFO_SCALE:
1256df36de13SAntoniu Miclaus *vals = (const int *)st->chip_info->scale_tbl;
1257df36de13SAntoniu Miclaus *type = IIO_VAL_INT_PLUS_NANO;
1258df36de13SAntoniu Miclaus *length = ARRAY_SIZE(st->chip_info->scale_tbl) * 2;
1259df36de13SAntoniu Miclaus return IIO_AVAIL_LIST;
1260df36de13SAntoniu Miclaus case IIO_CHAN_INFO_SAMP_FREQ:
1261df36de13SAntoniu Miclaus *vals = (const int *)st->chip_info->samp_freq_tbl;
1262df36de13SAntoniu Miclaus *type = IIO_VAL_INT;
1263df36de13SAntoniu Miclaus *length = ARRAY_SIZE(st->chip_info->samp_freq_tbl);
1264df36de13SAntoniu Miclaus return IIO_AVAIL_LIST;
1265df36de13SAntoniu Miclaus case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
1266df36de13SAntoniu Miclaus *vals = (const int *)st->lpf_tbl;
1267df36de13SAntoniu Miclaus *type = IIO_VAL_INT;
1268df36de13SAntoniu Miclaus *length = ARRAY_SIZE(st->lpf_tbl);
1269df36de13SAntoniu Miclaus return IIO_AVAIL_LIST;
1270df36de13SAntoniu Miclaus case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
1271df36de13SAntoniu Miclaus *vals = (const int *)st->hpf_tbl;
1272df36de13SAntoniu Miclaus *type = IIO_VAL_INT_PLUS_MICRO;
1273df36de13SAntoniu Miclaus /* Values are stored in a 2D matrix */
1274df36de13SAntoniu Miclaus *length = ARRAY_SIZE(st->hpf_tbl) * 2;
1275df36de13SAntoniu Miclaus return IIO_AVAIL_LIST;
1276df36de13SAntoniu Miclaus default:
1277df36de13SAntoniu Miclaus return -EINVAL;
1278df36de13SAntoniu Miclaus }
1279df36de13SAntoniu Miclaus }
1280df36de13SAntoniu Miclaus
adxl380_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long info)1281df36de13SAntoniu Miclaus static int adxl380_write_raw(struct iio_dev *indio_dev,
1282df36de13SAntoniu Miclaus struct iio_chan_spec const *chan,
1283df36de13SAntoniu Miclaus int val, int val2, long info)
1284df36de13SAntoniu Miclaus {
1285df36de13SAntoniu Miclaus struct adxl380_state *st = iio_priv(indio_dev);
1286df36de13SAntoniu Miclaus int odr_index, lpf_index, hpf_index, range_index;
1287df36de13SAntoniu Miclaus
1288df36de13SAntoniu Miclaus switch (info) {
1289df36de13SAntoniu Miclaus case IIO_CHAN_INFO_SAMP_FREQ:
1290df36de13SAntoniu Miclaus odr_index = adxl380_find_match_1d_tbl(st->chip_info->samp_freq_tbl,
1291df36de13SAntoniu Miclaus ARRAY_SIZE(st->chip_info->samp_freq_tbl),
1292df36de13SAntoniu Miclaus val);
1293df36de13SAntoniu Miclaus return adxl380_set_odr(st, odr_index);
1294df36de13SAntoniu Miclaus case IIO_CHAN_INFO_CALIBBIAS:
1295df36de13SAntoniu Miclaus return adxl380_write_calibbias_value(st, chan->scan_index, val);
1296df36de13SAntoniu Miclaus case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
1297df36de13SAntoniu Miclaus lpf_index = adxl380_find_match_1d_tbl(st->lpf_tbl,
1298df36de13SAntoniu Miclaus ARRAY_SIZE(st->lpf_tbl),
1299df36de13SAntoniu Miclaus val);
1300df36de13SAntoniu Miclaus return adxl380_set_lpf(st, lpf_index);
1301df36de13SAntoniu Miclaus case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
1302df36de13SAntoniu Miclaus hpf_index = adxl380_find_match_2d_tbl(st->hpf_tbl,
1303df36de13SAntoniu Miclaus ARRAY_SIZE(st->hpf_tbl),
1304df36de13SAntoniu Miclaus val, val2);
1305df36de13SAntoniu Miclaus if (hpf_index < 0)
1306df36de13SAntoniu Miclaus return hpf_index;
1307df36de13SAntoniu Miclaus return adxl380_set_hpf(st, hpf_index);
1308df36de13SAntoniu Miclaus case IIO_CHAN_INFO_SCALE:
1309df36de13SAntoniu Miclaus range_index = adxl380_find_match_2d_tbl(st->chip_info->scale_tbl,
1310df36de13SAntoniu Miclaus ARRAY_SIZE(st->chip_info->scale_tbl),
1311df36de13SAntoniu Miclaus val, val2);
1312df36de13SAntoniu Miclaus if (range_index < 0)
1313df36de13SAntoniu Miclaus return range_index;
1314df36de13SAntoniu Miclaus return adxl380_set_range(st, range_index);
1315df36de13SAntoniu Miclaus default:
1316df36de13SAntoniu Miclaus return -EINVAL;
1317df36de13SAntoniu Miclaus }
1318df36de13SAntoniu Miclaus }
1319df36de13SAntoniu Miclaus
adxl380_write_raw_get_fmt(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,long info)1320df36de13SAntoniu Miclaus static int adxl380_write_raw_get_fmt(struct iio_dev *indio_dev,
1321df36de13SAntoniu Miclaus struct iio_chan_spec const *chan,
1322df36de13SAntoniu Miclaus long info)
1323df36de13SAntoniu Miclaus {
1324df36de13SAntoniu Miclaus switch (info) {
1325df36de13SAntoniu Miclaus case IIO_CHAN_INFO_SCALE:
1326df36de13SAntoniu Miclaus if (chan->type != IIO_ACCEL)
1327df36de13SAntoniu Miclaus return -EINVAL;
1328df36de13SAntoniu Miclaus
1329df36de13SAntoniu Miclaus return IIO_VAL_INT_PLUS_NANO;
1330df36de13SAntoniu Miclaus default:
1331df36de13SAntoniu Miclaus return IIO_VAL_INT_PLUS_MICRO;
1332df36de13SAntoniu Miclaus }
1333df36de13SAntoniu Miclaus }
1334df36de13SAntoniu Miclaus
adxl380_read_event_config(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir)1335df36de13SAntoniu Miclaus static int adxl380_read_event_config(struct iio_dev *indio_dev,
1336df36de13SAntoniu Miclaus const struct iio_chan_spec *chan,
1337df36de13SAntoniu Miclaus enum iio_event_type type,
1338df36de13SAntoniu Miclaus enum iio_event_direction dir)
1339df36de13SAntoniu Miclaus {
1340df36de13SAntoniu Miclaus struct adxl380_state *st = iio_priv(indio_dev);
1341df36de13SAntoniu Miclaus int ret;
1342df36de13SAntoniu Miclaus bool int_en;
1343df36de13SAntoniu Miclaus bool tap_axis_en = false;
1344df36de13SAntoniu Miclaus
1345df36de13SAntoniu Miclaus switch (chan->channel2) {
1346df36de13SAntoniu Miclaus case IIO_MOD_X:
1347df36de13SAntoniu Miclaus tap_axis_en = st->tap_axis_en == ADXL380_X_AXIS;
1348df36de13SAntoniu Miclaus break;
1349df36de13SAntoniu Miclaus case IIO_MOD_Y:
1350df36de13SAntoniu Miclaus tap_axis_en = st->tap_axis_en == ADXL380_Y_AXIS;
1351df36de13SAntoniu Miclaus break;
1352df36de13SAntoniu Miclaus case IIO_MOD_Z:
1353df36de13SAntoniu Miclaus tap_axis_en = st->tap_axis_en == ADXL380_Z_AXIS;
1354df36de13SAntoniu Miclaus break;
1355df36de13SAntoniu Miclaus default:
1356df36de13SAntoniu Miclaus return -EINVAL;
1357df36de13SAntoniu Miclaus }
1358df36de13SAntoniu Miclaus
1359df36de13SAntoniu Miclaus switch (dir) {
1360df36de13SAntoniu Miclaus case IIO_EV_DIR_RISING:
1361df36de13SAntoniu Miclaus ret = adxl380_read_act_inact_int(st, ADXL380_ACTIVITY, &int_en);
1362df36de13SAntoniu Miclaus if (ret)
1363df36de13SAntoniu Miclaus return ret;
1364df36de13SAntoniu Miclaus return int_en;
1365df36de13SAntoniu Miclaus case IIO_EV_DIR_FALLING:
1366df36de13SAntoniu Miclaus ret = adxl380_read_act_inact_int(st, ADXL380_INACTIVITY, &int_en);
1367df36de13SAntoniu Miclaus if (ret)
1368df36de13SAntoniu Miclaus return ret;
1369df36de13SAntoniu Miclaus return int_en;
1370df36de13SAntoniu Miclaus case IIO_EV_DIR_SINGLETAP:
1371df36de13SAntoniu Miclaus ret = adxl380_read_tap_int(st, ADXL380_SINGLE_TAP, &int_en);
1372df36de13SAntoniu Miclaus if (ret)
1373df36de13SAntoniu Miclaus return ret;
1374df36de13SAntoniu Miclaus return int_en && tap_axis_en;
1375df36de13SAntoniu Miclaus case IIO_EV_DIR_DOUBLETAP:
1376df36de13SAntoniu Miclaus ret = adxl380_read_tap_int(st, ADXL380_DOUBLE_TAP, &int_en);
1377df36de13SAntoniu Miclaus if (ret)
1378df36de13SAntoniu Miclaus return ret;
1379df36de13SAntoniu Miclaus return int_en && tap_axis_en;
1380df36de13SAntoniu Miclaus default:
1381df36de13SAntoniu Miclaus return -EINVAL;
1382df36de13SAntoniu Miclaus }
1383df36de13SAntoniu Miclaus }
1384df36de13SAntoniu Miclaus
adxl380_write_event_config(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,int state)1385df36de13SAntoniu Miclaus static int adxl380_write_event_config(struct iio_dev *indio_dev,
1386df36de13SAntoniu Miclaus const struct iio_chan_spec *chan,
1387df36de13SAntoniu Miclaus enum iio_event_type type,
1388df36de13SAntoniu Miclaus enum iio_event_direction dir,
1389df36de13SAntoniu Miclaus int state)
1390df36de13SAntoniu Miclaus {
1391df36de13SAntoniu Miclaus struct adxl380_state *st = iio_priv(indio_dev);
1392df36de13SAntoniu Miclaus enum adxl380_axis axis;
1393df36de13SAntoniu Miclaus
1394df36de13SAntoniu Miclaus switch (chan->channel2) {
1395df36de13SAntoniu Miclaus case IIO_MOD_X:
1396df36de13SAntoniu Miclaus axis = ADXL380_X_AXIS;
1397df36de13SAntoniu Miclaus break;
1398df36de13SAntoniu Miclaus case IIO_MOD_Y:
1399df36de13SAntoniu Miclaus axis = ADXL380_Y_AXIS;
1400df36de13SAntoniu Miclaus break;
1401df36de13SAntoniu Miclaus case IIO_MOD_Z:
1402df36de13SAntoniu Miclaus axis = ADXL380_Z_AXIS;
1403df36de13SAntoniu Miclaus break;
1404df36de13SAntoniu Miclaus default:
1405df36de13SAntoniu Miclaus return -EINVAL;
1406df36de13SAntoniu Miclaus }
1407df36de13SAntoniu Miclaus
1408df36de13SAntoniu Miclaus switch (dir) {
1409df36de13SAntoniu Miclaus case IIO_EV_DIR_RISING:
1410df36de13SAntoniu Miclaus return adxl380_act_inact_config(st, ADXL380_ACTIVITY, state);
1411df36de13SAntoniu Miclaus case IIO_EV_DIR_FALLING:
1412df36de13SAntoniu Miclaus return adxl380_act_inact_config(st, ADXL380_INACTIVITY, state);
1413df36de13SAntoniu Miclaus case IIO_EV_DIR_SINGLETAP:
1414df36de13SAntoniu Miclaus return adxl380_tap_config(st, axis, ADXL380_SINGLE_TAP, state);
1415df36de13SAntoniu Miclaus case IIO_EV_DIR_DOUBLETAP:
1416df36de13SAntoniu Miclaus return adxl380_tap_config(st, axis, ADXL380_DOUBLE_TAP, state);
1417df36de13SAntoniu Miclaus default:
1418df36de13SAntoniu Miclaus return -EINVAL;
1419df36de13SAntoniu Miclaus }
1420df36de13SAntoniu Miclaus }
1421df36de13SAntoniu Miclaus
adxl380_read_event_value(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,enum iio_event_info info,int * val,int * val2)1422df36de13SAntoniu Miclaus static int adxl380_read_event_value(struct iio_dev *indio_dev,
1423df36de13SAntoniu Miclaus const struct iio_chan_spec *chan,
1424df36de13SAntoniu Miclaus enum iio_event_type type,
1425df36de13SAntoniu Miclaus enum iio_event_direction dir,
1426df36de13SAntoniu Miclaus enum iio_event_info info,
1427df36de13SAntoniu Miclaus int *val, int *val2)
1428df36de13SAntoniu Miclaus {
1429df36de13SAntoniu Miclaus struct adxl380_state *st = iio_priv(indio_dev);
1430df36de13SAntoniu Miclaus
1431df36de13SAntoniu Miclaus guard(mutex)(&st->lock);
1432df36de13SAntoniu Miclaus
1433df36de13SAntoniu Miclaus switch (type) {
1434df36de13SAntoniu Miclaus case IIO_EV_TYPE_THRESH:
1435df36de13SAntoniu Miclaus switch (info) {
1436df36de13SAntoniu Miclaus case IIO_EV_INFO_VALUE: {
1437df36de13SAntoniu Miclaus switch (dir) {
1438df36de13SAntoniu Miclaus case IIO_EV_DIR_RISING:
1439df36de13SAntoniu Miclaus *val = st->act_threshold;
1440df36de13SAntoniu Miclaus return IIO_VAL_INT;
1441df36de13SAntoniu Miclaus case IIO_EV_DIR_FALLING:
1442df36de13SAntoniu Miclaus *val = st->inact_threshold;
1443df36de13SAntoniu Miclaus return IIO_VAL_INT;
1444df36de13SAntoniu Miclaus default:
1445df36de13SAntoniu Miclaus return -EINVAL;
1446df36de13SAntoniu Miclaus }
1447df36de13SAntoniu Miclaus }
1448df36de13SAntoniu Miclaus case IIO_EV_INFO_PERIOD:
1449df36de13SAntoniu Miclaus switch (dir) {
1450df36de13SAntoniu Miclaus case IIO_EV_DIR_RISING:
1451df36de13SAntoniu Miclaus *val = st->act_time_ms;
1452df36de13SAntoniu Miclaus *val2 = 1000;
1453df36de13SAntoniu Miclaus return IIO_VAL_FRACTIONAL;
1454df36de13SAntoniu Miclaus case IIO_EV_DIR_FALLING:
1455df36de13SAntoniu Miclaus *val = st->inact_time_ms;
1456df36de13SAntoniu Miclaus *val2 = 1000;
1457df36de13SAntoniu Miclaus return IIO_VAL_FRACTIONAL;
1458df36de13SAntoniu Miclaus default:
1459df36de13SAntoniu Miclaus return -EINVAL;
1460df36de13SAntoniu Miclaus }
1461df36de13SAntoniu Miclaus default:
1462df36de13SAntoniu Miclaus return -EINVAL;
1463df36de13SAntoniu Miclaus }
1464df36de13SAntoniu Miclaus case IIO_EV_TYPE_GESTURE:
1465df36de13SAntoniu Miclaus switch (info) {
1466df36de13SAntoniu Miclaus case IIO_EV_INFO_VALUE:
1467df36de13SAntoniu Miclaus *val = st->tap_threshold;
1468df36de13SAntoniu Miclaus return IIO_VAL_INT;
1469df36de13SAntoniu Miclaus case IIO_EV_INFO_RESET_TIMEOUT:
1470df36de13SAntoniu Miclaus *val = st->tap_window_us;
1471df36de13SAntoniu Miclaus *val2 = 1000000;
1472df36de13SAntoniu Miclaus return IIO_VAL_FRACTIONAL;
1473df36de13SAntoniu Miclaus case IIO_EV_INFO_TAP2_MIN_DELAY:
1474df36de13SAntoniu Miclaus *val = st->tap_latent_us;
1475df36de13SAntoniu Miclaus *val2 = 1000000;
1476df36de13SAntoniu Miclaus return IIO_VAL_FRACTIONAL;
1477df36de13SAntoniu Miclaus default:
1478df36de13SAntoniu Miclaus return -EINVAL;
1479df36de13SAntoniu Miclaus }
1480df36de13SAntoniu Miclaus default:
1481df36de13SAntoniu Miclaus return -EINVAL;
1482df36de13SAntoniu Miclaus }
1483df36de13SAntoniu Miclaus }
1484df36de13SAntoniu Miclaus
adxl380_write_event_value(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir,enum iio_event_info info,int val,int val2)1485df36de13SAntoniu Miclaus static int adxl380_write_event_value(struct iio_dev *indio_dev,
1486df36de13SAntoniu Miclaus const struct iio_chan_spec *chan,
1487df36de13SAntoniu Miclaus enum iio_event_type type, enum iio_event_direction dir,
1488df36de13SAntoniu Miclaus enum iio_event_info info, int val, int val2)
1489df36de13SAntoniu Miclaus {
1490df36de13SAntoniu Miclaus struct adxl380_state *st = iio_priv(indio_dev);
1491df36de13SAntoniu Miclaus u32 val_ms, val_us;
1492df36de13SAntoniu Miclaus
1493df36de13SAntoniu Miclaus if (chan->type != IIO_ACCEL)
1494df36de13SAntoniu Miclaus return -EINVAL;
1495df36de13SAntoniu Miclaus
1496df36de13SAntoniu Miclaus switch (type) {
1497df36de13SAntoniu Miclaus case IIO_EV_TYPE_THRESH:
1498df36de13SAntoniu Miclaus switch (info) {
1499df36de13SAntoniu Miclaus case IIO_EV_INFO_VALUE:
1500df36de13SAntoniu Miclaus switch (dir) {
1501df36de13SAntoniu Miclaus case IIO_EV_DIR_RISING:
1502df36de13SAntoniu Miclaus return adxl380_set_act_inact_threshold(indio_dev,
1503df36de13SAntoniu Miclaus ADXL380_ACTIVITY, val);
1504df36de13SAntoniu Miclaus case IIO_EV_DIR_FALLING:
1505df36de13SAntoniu Miclaus return adxl380_set_act_inact_threshold(indio_dev,
1506df36de13SAntoniu Miclaus ADXL380_INACTIVITY, val);
1507df36de13SAntoniu Miclaus default:
1508df36de13SAntoniu Miclaus return -EINVAL;
1509df36de13SAntoniu Miclaus }
1510df36de13SAntoniu Miclaus case IIO_EV_INFO_PERIOD:
1511df36de13SAntoniu Miclaus val_ms = val * 1000 + DIV_ROUND_UP(val2, 1000);
1512df36de13SAntoniu Miclaus switch (dir) {
1513df36de13SAntoniu Miclaus case IIO_EV_DIR_RISING:
1514df36de13SAntoniu Miclaus return adxl380_set_act_inact_time_ms(st,
1515df36de13SAntoniu Miclaus ADXL380_ACTIVITY, val_ms);
1516df36de13SAntoniu Miclaus case IIO_EV_DIR_FALLING:
1517df36de13SAntoniu Miclaus return adxl380_set_act_inact_time_ms(st,
1518df36de13SAntoniu Miclaus ADXL380_INACTIVITY, val_ms);
1519df36de13SAntoniu Miclaus default:
1520df36de13SAntoniu Miclaus return -EINVAL;
1521df36de13SAntoniu Miclaus }
1522df36de13SAntoniu Miclaus
1523df36de13SAntoniu Miclaus default:
1524df36de13SAntoniu Miclaus return -EINVAL;
1525df36de13SAntoniu Miclaus }
1526df36de13SAntoniu Miclaus case IIO_EV_TYPE_GESTURE:
1527df36de13SAntoniu Miclaus switch (info) {
1528df36de13SAntoniu Miclaus case IIO_EV_INFO_VALUE:
1529df36de13SAntoniu Miclaus return adxl380_set_tap_threshold_value(indio_dev, val);
1530df36de13SAntoniu Miclaus case IIO_EV_INFO_RESET_TIMEOUT:
1531df36de13SAntoniu Miclaus val_us = val * 1000000 + val2;
1532df36de13SAntoniu Miclaus return adxl380_write_tap_time_us(st,
1533df36de13SAntoniu Miclaus ADXL380_TAP_TIME_WINDOW,
1534df36de13SAntoniu Miclaus val_us);
1535df36de13SAntoniu Miclaus case IIO_EV_INFO_TAP2_MIN_DELAY:
1536df36de13SAntoniu Miclaus val_us = val * 1000000 + val2;
1537df36de13SAntoniu Miclaus return adxl380_write_tap_time_us(st,
1538df36de13SAntoniu Miclaus ADXL380_TAP_TIME_LATENT,
1539df36de13SAntoniu Miclaus val_us);
1540df36de13SAntoniu Miclaus default:
1541df36de13SAntoniu Miclaus return -EINVAL;
1542df36de13SAntoniu Miclaus }
1543df36de13SAntoniu Miclaus default:
1544df36de13SAntoniu Miclaus return -EINVAL;
1545df36de13SAntoniu Miclaus }
1546df36de13SAntoniu Miclaus }
1547df36de13SAntoniu Miclaus
in_accel_gesture_tap_maxtomin_time_show(struct device * dev,struct device_attribute * attr,char * buf)1548df36de13SAntoniu Miclaus static ssize_t in_accel_gesture_tap_maxtomin_time_show(struct device *dev,
1549df36de13SAntoniu Miclaus struct device_attribute *attr,
1550df36de13SAntoniu Miclaus char *buf)
1551df36de13SAntoniu Miclaus {
1552df36de13SAntoniu Miclaus int vals[2];
1553df36de13SAntoniu Miclaus struct iio_dev *indio_dev = dev_to_iio_dev(dev);
1554df36de13SAntoniu Miclaus struct adxl380_state *st = iio_priv(indio_dev);
1555df36de13SAntoniu Miclaus
1556df36de13SAntoniu Miclaus guard(mutex)(&st->lock);
1557df36de13SAntoniu Miclaus
1558df36de13SAntoniu Miclaus vals[0] = st->tap_duration_us;
1559df36de13SAntoniu Miclaus vals[1] = MICRO;
1560df36de13SAntoniu Miclaus
1561df36de13SAntoniu Miclaus return iio_format_value(buf, IIO_VAL_FRACTIONAL, 2, vals);
1562df36de13SAntoniu Miclaus }
1563df36de13SAntoniu Miclaus
in_accel_gesture_tap_maxtomin_time_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)1564df36de13SAntoniu Miclaus static ssize_t in_accel_gesture_tap_maxtomin_time_store(struct device *dev,
1565df36de13SAntoniu Miclaus struct device_attribute *attr,
1566df36de13SAntoniu Miclaus const char *buf, size_t len)
1567df36de13SAntoniu Miclaus {
1568df36de13SAntoniu Miclaus struct iio_dev *indio_dev = dev_to_iio_dev(dev);
1569df36de13SAntoniu Miclaus struct adxl380_state *st = iio_priv(indio_dev);
1570df36de13SAntoniu Miclaus int ret, val_int, val_fract_us;
1571df36de13SAntoniu Miclaus
1572df36de13SAntoniu Miclaus guard(mutex)(&st->lock);
1573df36de13SAntoniu Miclaus
1574df36de13SAntoniu Miclaus ret = iio_str_to_fixpoint(buf, 100000, &val_int, &val_fract_us);
1575df36de13SAntoniu Miclaus if (ret)
1576df36de13SAntoniu Miclaus return ret;
1577df36de13SAntoniu Miclaus
1578df36de13SAntoniu Miclaus /* maximum value is 255 * 625 us = 0.159375 seconds */
1579df36de13SAntoniu Miclaus if (val_int || val_fract_us > 159375 || val_fract_us < 0)
1580df36de13SAntoniu Miclaus return -EINVAL;
1581df36de13SAntoniu Miclaus
1582df36de13SAntoniu Miclaus ret = adxl380_write_tap_dur_us(indio_dev, val_fract_us);
1583df36de13SAntoniu Miclaus if (ret)
1584df36de13SAntoniu Miclaus return ret;
1585df36de13SAntoniu Miclaus
1586df36de13SAntoniu Miclaus return len;
1587df36de13SAntoniu Miclaus }
1588df36de13SAntoniu Miclaus
1589df36de13SAntoniu Miclaus static IIO_DEVICE_ATTR_RW(in_accel_gesture_tap_maxtomin_time, 0);
1590df36de13SAntoniu Miclaus
1591df36de13SAntoniu Miclaus static struct attribute *adxl380_event_attributes[] = {
1592df36de13SAntoniu Miclaus &iio_dev_attr_in_accel_gesture_tap_maxtomin_time.dev_attr.attr,
1593df36de13SAntoniu Miclaus NULL
1594df36de13SAntoniu Miclaus };
1595df36de13SAntoniu Miclaus
1596df36de13SAntoniu Miclaus static const struct attribute_group adxl380_event_attribute_group = {
1597df36de13SAntoniu Miclaus .attrs = adxl380_event_attributes,
1598df36de13SAntoniu Miclaus };
1599df36de13SAntoniu Miclaus
adxl380_reg_access(struct iio_dev * indio_dev,unsigned int reg,unsigned int writeval,unsigned int * readval)1600df36de13SAntoniu Miclaus static int adxl380_reg_access(struct iio_dev *indio_dev,
1601df36de13SAntoniu Miclaus unsigned int reg,
1602df36de13SAntoniu Miclaus unsigned int writeval,
1603df36de13SAntoniu Miclaus unsigned int *readval)
1604df36de13SAntoniu Miclaus {
1605df36de13SAntoniu Miclaus struct adxl380_state *st = iio_priv(indio_dev);
1606df36de13SAntoniu Miclaus
1607df36de13SAntoniu Miclaus if (readval)
1608df36de13SAntoniu Miclaus return regmap_read(st->regmap, reg, readval);
1609df36de13SAntoniu Miclaus
1610df36de13SAntoniu Miclaus return regmap_write(st->regmap, reg, writeval);
1611df36de13SAntoniu Miclaus }
1612df36de13SAntoniu Miclaus
adxl380_set_watermark(struct iio_dev * indio_dev,unsigned int val)1613df36de13SAntoniu Miclaus static int adxl380_set_watermark(struct iio_dev *indio_dev, unsigned int val)
1614df36de13SAntoniu Miclaus {
1615df36de13SAntoniu Miclaus struct adxl380_state *st = iio_priv(indio_dev);
1616df36de13SAntoniu Miclaus
1617df36de13SAntoniu Miclaus st->watermark = min(val, ADXL380_FIFO_SAMPLES);
1618df36de13SAntoniu Miclaus
1619df36de13SAntoniu Miclaus return 0;
1620df36de13SAntoniu Miclaus }
1621df36de13SAntoniu Miclaus
1622df36de13SAntoniu Miclaus static const struct iio_info adxl380_info = {
1623df36de13SAntoniu Miclaus .read_raw = adxl380_read_raw,
1624df36de13SAntoniu Miclaus .read_avail = &adxl380_read_avail,
1625df36de13SAntoniu Miclaus .write_raw = adxl380_write_raw,
1626df36de13SAntoniu Miclaus .write_raw_get_fmt = adxl380_write_raw_get_fmt,
1627df36de13SAntoniu Miclaus .read_event_config = adxl380_read_event_config,
1628df36de13SAntoniu Miclaus .write_event_config = adxl380_write_event_config,
1629df36de13SAntoniu Miclaus .read_event_value = adxl380_read_event_value,
1630df36de13SAntoniu Miclaus .write_event_value = adxl380_write_event_value,
1631df36de13SAntoniu Miclaus .event_attrs = &adxl380_event_attribute_group,
1632df36de13SAntoniu Miclaus .debugfs_reg_access = &adxl380_reg_access,
1633df36de13SAntoniu Miclaus .hwfifo_set_watermark = adxl380_set_watermark,
1634df36de13SAntoniu Miclaus };
1635df36de13SAntoniu Miclaus
1636df36de13SAntoniu Miclaus static const struct iio_event_spec adxl380_events[] = {
1637df36de13SAntoniu Miclaus {
1638df36de13SAntoniu Miclaus .type = IIO_EV_TYPE_THRESH,
1639df36de13SAntoniu Miclaus .dir = IIO_EV_DIR_RISING,
1640df36de13SAntoniu Miclaus .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) |
1641df36de13SAntoniu Miclaus BIT(IIO_EV_INFO_VALUE) |
1642df36de13SAntoniu Miclaus BIT(IIO_EV_INFO_PERIOD),
1643df36de13SAntoniu Miclaus },
1644df36de13SAntoniu Miclaus {
1645df36de13SAntoniu Miclaus .type = IIO_EV_TYPE_THRESH,
1646df36de13SAntoniu Miclaus .dir = IIO_EV_DIR_FALLING,
1647df36de13SAntoniu Miclaus .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) |
1648df36de13SAntoniu Miclaus BIT(IIO_EV_INFO_VALUE) |
1649df36de13SAntoniu Miclaus BIT(IIO_EV_INFO_PERIOD),
1650df36de13SAntoniu Miclaus },
1651df36de13SAntoniu Miclaus {
1652df36de13SAntoniu Miclaus .type = IIO_EV_TYPE_GESTURE,
1653df36de13SAntoniu Miclaus .dir = IIO_EV_DIR_SINGLETAP,
1654df36de13SAntoniu Miclaus .mask_separate = BIT(IIO_EV_INFO_ENABLE),
1655df36de13SAntoniu Miclaus .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
1656df36de13SAntoniu Miclaus BIT(IIO_EV_INFO_RESET_TIMEOUT),
1657df36de13SAntoniu Miclaus },
1658df36de13SAntoniu Miclaus {
1659df36de13SAntoniu Miclaus .type = IIO_EV_TYPE_GESTURE,
1660df36de13SAntoniu Miclaus .dir = IIO_EV_DIR_DOUBLETAP,
1661df36de13SAntoniu Miclaus .mask_separate = BIT(IIO_EV_INFO_ENABLE),
1662df36de13SAntoniu Miclaus .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
1663df36de13SAntoniu Miclaus BIT(IIO_EV_INFO_RESET_TIMEOUT) |
1664df36de13SAntoniu Miclaus BIT(IIO_EV_INFO_TAP2_MIN_DELAY),
1665df36de13SAntoniu Miclaus },
1666df36de13SAntoniu Miclaus };
1667df36de13SAntoniu Miclaus
1668df36de13SAntoniu Miclaus #define ADXL380_ACCEL_CHANNEL(index, reg, axis) { \
1669df36de13SAntoniu Miclaus .type = IIO_ACCEL, \
1670df36de13SAntoniu Miclaus .address = reg, \
1671df36de13SAntoniu Miclaus .modified = 1, \
1672df36de13SAntoniu Miclaus .channel2 = IIO_MOD_##axis, \
1673df36de13SAntoniu Miclaus .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
1674df36de13SAntoniu Miclaus BIT(IIO_CHAN_INFO_CALIBBIAS), \
1675df36de13SAntoniu Miclaus .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
1676df36de13SAntoniu Miclaus .info_mask_shared_by_all_available = \
1677df36de13SAntoniu Miclaus BIT(IIO_CHAN_INFO_SAMP_FREQ), \
1678df36de13SAntoniu Miclaus .info_mask_shared_by_type = \
1679df36de13SAntoniu Miclaus BIT(IIO_CHAN_INFO_SCALE) | \
1680df36de13SAntoniu Miclaus BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \
1681df36de13SAntoniu Miclaus BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \
1682df36de13SAntoniu Miclaus .info_mask_shared_by_type_available = \
1683df36de13SAntoniu Miclaus BIT(IIO_CHAN_INFO_SCALE) | \
1684df36de13SAntoniu Miclaus BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \
1685df36de13SAntoniu Miclaus BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \
1686df36de13SAntoniu Miclaus .scan_index = index, \
1687df36de13SAntoniu Miclaus .scan_type = { \
1688df36de13SAntoniu Miclaus .sign = 's', \
1689df36de13SAntoniu Miclaus .realbits = 16, \
1690df36de13SAntoniu Miclaus .storagebits = 16, \
1691df36de13SAntoniu Miclaus .endianness = IIO_BE, \
1692df36de13SAntoniu Miclaus }, \
1693df36de13SAntoniu Miclaus .event_spec = adxl380_events, \
1694df36de13SAntoniu Miclaus .num_event_specs = ARRAY_SIZE(adxl380_events) \
1695df36de13SAntoniu Miclaus }
1696df36de13SAntoniu Miclaus
1697df36de13SAntoniu Miclaus static const struct iio_chan_spec adxl380_channels[] = {
1698df36de13SAntoniu Miclaus ADXL380_ACCEL_CHANNEL(0, ADXL380_X_DATA_H_REG, X),
1699df36de13SAntoniu Miclaus ADXL380_ACCEL_CHANNEL(1, ADXL380_Y_DATA_H_REG, Y),
1700df36de13SAntoniu Miclaus ADXL380_ACCEL_CHANNEL(2, ADXL380_Z_DATA_H_REG, Z),
1701df36de13SAntoniu Miclaus {
1702df36de13SAntoniu Miclaus .type = IIO_TEMP,
1703df36de13SAntoniu Miclaus .address = ADXL380_T_DATA_H_REG,
1704df36de13SAntoniu Miclaus .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
1705df36de13SAntoniu Miclaus BIT(IIO_CHAN_INFO_SCALE) |
1706df36de13SAntoniu Miclaus BIT(IIO_CHAN_INFO_OFFSET),
1707df36de13SAntoniu Miclaus .scan_index = 3,
1708df36de13SAntoniu Miclaus .scan_type = {
1709df36de13SAntoniu Miclaus .sign = 's',
1710df36de13SAntoniu Miclaus .realbits = 12,
1711df36de13SAntoniu Miclaus .storagebits = 16,
1712df36de13SAntoniu Miclaus .shift = 4,
1713df36de13SAntoniu Miclaus .endianness = IIO_BE,
1714df36de13SAntoniu Miclaus },
1715df36de13SAntoniu Miclaus },
1716df36de13SAntoniu Miclaus };
1717df36de13SAntoniu Miclaus
adxl380_config_irq(struct iio_dev * indio_dev)1718df36de13SAntoniu Miclaus static int adxl380_config_irq(struct iio_dev *indio_dev)
1719df36de13SAntoniu Miclaus {
1720df36de13SAntoniu Miclaus struct adxl380_state *st = iio_priv(indio_dev);
1721df36de13SAntoniu Miclaus unsigned long irq_flag;
1722df36de13SAntoniu Miclaus struct irq_data *desc;
1723df36de13SAntoniu Miclaus u32 irq_type;
1724df36de13SAntoniu Miclaus u8 polarity;
1725df36de13SAntoniu Miclaus int ret;
1726df36de13SAntoniu Miclaus
1727df36de13SAntoniu Miclaus st->irq = fwnode_irq_get_byname(dev_fwnode(st->dev), "INT0");
1728df36de13SAntoniu Miclaus if (st->irq > 0) {
1729df36de13SAntoniu Miclaus st->int_map[0] = ADXL380_INT0_MAP0_REG;
1730df36de13SAntoniu Miclaus st->int_map[1] = ADXL380_INT0_MAP1_REG;
1731df36de13SAntoniu Miclaus } else {
1732df36de13SAntoniu Miclaus st->irq = fwnode_irq_get_byname(dev_fwnode(st->dev), "INT1");
1733df36de13SAntoniu Miclaus if (st->irq > 0)
1734df36de13SAntoniu Miclaus return dev_err_probe(st->dev, -ENODEV,
1735df36de13SAntoniu Miclaus "no interrupt name specified");
1736df36de13SAntoniu Miclaus st->int_map[0] = ADXL380_INT1_MAP0_REG;
1737df36de13SAntoniu Miclaus st->int_map[1] = ADXL380_INT1_MAP1_REG;
1738df36de13SAntoniu Miclaus }
1739df36de13SAntoniu Miclaus
1740df36de13SAntoniu Miclaus desc = irq_get_irq_data(st->irq);
1741df36de13SAntoniu Miclaus if (!desc)
1742df36de13SAntoniu Miclaus return dev_err_probe(st->dev, -EINVAL, "Could not find IRQ %d\n", st->irq);
1743df36de13SAntoniu Miclaus
1744df36de13SAntoniu Miclaus irq_type = irqd_get_trigger_type(desc);
1745df36de13SAntoniu Miclaus if (irq_type == IRQ_TYPE_LEVEL_HIGH) {
1746df36de13SAntoniu Miclaus polarity = 0;
1747df36de13SAntoniu Miclaus irq_flag = IRQF_TRIGGER_HIGH | IRQF_ONESHOT;
1748df36de13SAntoniu Miclaus } else if (irq_type == IRQ_TYPE_LEVEL_LOW) {
1749df36de13SAntoniu Miclaus polarity = 1;
1750df36de13SAntoniu Miclaus irq_flag = IRQF_TRIGGER_LOW | IRQF_ONESHOT;
1751df36de13SAntoniu Miclaus } else {
1752df36de13SAntoniu Miclaus return dev_err_probe(st->dev, -EINVAL,
1753df36de13SAntoniu Miclaus "Invalid interrupt 0x%x. Only level interrupts supported\n",
1754df36de13SAntoniu Miclaus irq_type);
1755df36de13SAntoniu Miclaus }
1756df36de13SAntoniu Miclaus
1757df36de13SAntoniu Miclaus ret = regmap_update_bits(st->regmap, ADXL380_INT0_REG,
1758df36de13SAntoniu Miclaus ADXL380_INT0_POL_MSK,
1759df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_INT0_POL_MSK, polarity));
1760df36de13SAntoniu Miclaus if (ret)
1761df36de13SAntoniu Miclaus return ret;
1762df36de13SAntoniu Miclaus
1763df36de13SAntoniu Miclaus return devm_request_threaded_irq(st->dev, st->irq, NULL,
1764df36de13SAntoniu Miclaus adxl380_irq_handler, irq_flag,
1765df36de13SAntoniu Miclaus indio_dev->name, indio_dev);
1766df36de13SAntoniu Miclaus }
1767df36de13SAntoniu Miclaus
adxl380_setup(struct iio_dev * indio_dev)1768df36de13SAntoniu Miclaus static int adxl380_setup(struct iio_dev *indio_dev)
1769df36de13SAntoniu Miclaus {
1770df36de13SAntoniu Miclaus unsigned int reg_val;
1771df36de13SAntoniu Miclaus u16 part_id, chip_id;
1772df36de13SAntoniu Miclaus int ret, i;
1773df36de13SAntoniu Miclaus struct adxl380_state *st = iio_priv(indio_dev);
1774df36de13SAntoniu Miclaus
1775df36de13SAntoniu Miclaus ret = regmap_read(st->regmap, ADXL380_DEVID_AD_REG, ®_val);
1776df36de13SAntoniu Miclaus if (ret)
1777df36de13SAntoniu Miclaus return ret;
1778df36de13SAntoniu Miclaus
1779df36de13SAntoniu Miclaus if (reg_val != ADXL380_DEVID_AD_VAL)
1780df36de13SAntoniu Miclaus dev_warn(st->dev, "Unknown chip id %x\n", reg_val);
1781df36de13SAntoniu Miclaus
1782df36de13SAntoniu Miclaus ret = regmap_bulk_read(st->regmap, ADLX380_PART_ID_REG,
1783df36de13SAntoniu Miclaus &st->transf_buf, 2);
1784df36de13SAntoniu Miclaus if (ret)
1785df36de13SAntoniu Miclaus return ret;
1786df36de13SAntoniu Miclaus
1787df36de13SAntoniu Miclaus part_id = get_unaligned_be16(st->transf_buf);
1788df36de13SAntoniu Miclaus part_id >>= 4;
1789df36de13SAntoniu Miclaus
1790df36de13SAntoniu Miclaus if (part_id != ADXL380_ID_VAL)
1791df36de13SAntoniu Miclaus dev_warn(st->dev, "Unknown part id %x\n", part_id);
1792df36de13SAntoniu Miclaus
1793df36de13SAntoniu Miclaus ret = regmap_read(st->regmap, ADXL380_MISC_0_REG, ®_val);
1794df36de13SAntoniu Miclaus if (ret)
1795df36de13SAntoniu Miclaus return ret;
1796df36de13SAntoniu Miclaus
1797df36de13SAntoniu Miclaus /* Bit to differentiate between ADXL380/382. */
1798df36de13SAntoniu Miclaus if (reg_val & ADXL380_XL382_MSK)
1799df36de13SAntoniu Miclaus chip_id = ADXL382_ID_VAL;
1800df36de13SAntoniu Miclaus else
1801df36de13SAntoniu Miclaus chip_id = ADXL380_ID_VAL;
1802df36de13SAntoniu Miclaus
1803df36de13SAntoniu Miclaus if (chip_id != st->chip_info->chip_id)
1804df36de13SAntoniu Miclaus dev_warn(st->dev, "Unknown chip id %x\n", chip_id);
1805df36de13SAntoniu Miclaus
1806df36de13SAntoniu Miclaus ret = regmap_write(st->regmap, ADXL380_RESET_REG, ADXL380_RESET_CODE);
1807df36de13SAntoniu Miclaus if (ret)
1808df36de13SAntoniu Miclaus return ret;
1809df36de13SAntoniu Miclaus
1810df36de13SAntoniu Miclaus /*
1811df36de13SAntoniu Miclaus * A latency of approximately 0.5 ms is required after soft reset.
1812df36de13SAntoniu Miclaus * Stated in the register REG_RESET description.
1813df36de13SAntoniu Miclaus */
1814df36de13SAntoniu Miclaus fsleep(500);
1815df36de13SAntoniu Miclaus
1816df36de13SAntoniu Miclaus for (i = 0; i < indio_dev->num_channels; i++) {
1817df36de13SAntoniu Miclaus ret = regmap_update_bits(st->regmap, ADXL380_DIG_EN_REG,
1818df36de13SAntoniu Miclaus ADXL380_CHAN_EN_MSK(i),
1819df36de13SAntoniu Miclaus 1 << (4 + i));
1820df36de13SAntoniu Miclaus if (ret)
1821df36de13SAntoniu Miclaus return ret;
1822df36de13SAntoniu Miclaus }
1823df36de13SAntoniu Miclaus
1824df36de13SAntoniu Miclaus ret = regmap_update_bits(st->regmap, ADXL380_FIFO_CONFIG_0_REG,
1825df36de13SAntoniu Miclaus ADXL380_FIFO_MODE_MSK,
1826df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_FIFO_MODE_MSK, ADXL380_FIFO_STREAMED));
1827df36de13SAntoniu Miclaus if (ret)
1828df36de13SAntoniu Miclaus return ret;
1829df36de13SAntoniu Miclaus
1830df36de13SAntoniu Miclaus /* Select all 3 axis for act/inact detection. */
1831df36de13SAntoniu Miclaus ret = regmap_update_bits(st->regmap, ADXL380_SNSR_AXIS_EN_REG,
1832df36de13SAntoniu Miclaus ADXL380_ACT_INACT_AXIS_EN_MSK,
1833df36de13SAntoniu Miclaus FIELD_PREP(ADXL380_ACT_INACT_AXIS_EN_MSK,
1834df36de13SAntoniu Miclaus ADXL380_ACT_INACT_AXIS_EN_MSK));
1835df36de13SAntoniu Miclaus if (ret)
1836df36de13SAntoniu Miclaus return ret;
1837df36de13SAntoniu Miclaus
1838df36de13SAntoniu Miclaus ret = adxl380_config_irq(indio_dev);
1839df36de13SAntoniu Miclaus if (ret)
1840df36de13SAntoniu Miclaus return ret;
1841df36de13SAntoniu Miclaus
1842df36de13SAntoniu Miclaus ret = adxl380_fill_lpf_tbl(st);
1843df36de13SAntoniu Miclaus if (ret)
1844df36de13SAntoniu Miclaus return ret;
1845df36de13SAntoniu Miclaus
1846df36de13SAntoniu Miclaus ret = adxl380_fill_hpf_tbl(st);
1847df36de13SAntoniu Miclaus if (ret)
1848df36de13SAntoniu Miclaus return ret;
1849df36de13SAntoniu Miclaus
1850df36de13SAntoniu Miclaus return adxl380_set_measure_en(st, true);
1851df36de13SAntoniu Miclaus }
1852df36de13SAntoniu Miclaus
adxl380_probe(struct device * dev,struct regmap * regmap,const struct adxl380_chip_info * chip_info)1853df36de13SAntoniu Miclaus int adxl380_probe(struct device *dev, struct regmap *regmap,
1854df36de13SAntoniu Miclaus const struct adxl380_chip_info *chip_info)
1855df36de13SAntoniu Miclaus {
1856df36de13SAntoniu Miclaus struct iio_dev *indio_dev;
1857df36de13SAntoniu Miclaus struct adxl380_state *st;
1858df36de13SAntoniu Miclaus int ret;
1859df36de13SAntoniu Miclaus
1860df36de13SAntoniu Miclaus indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
1861df36de13SAntoniu Miclaus if (!indio_dev)
1862df36de13SAntoniu Miclaus return -ENOMEM;
1863df36de13SAntoniu Miclaus
1864df36de13SAntoniu Miclaus st = iio_priv(indio_dev);
1865df36de13SAntoniu Miclaus
1866df36de13SAntoniu Miclaus st->dev = dev;
1867df36de13SAntoniu Miclaus st->regmap = regmap;
1868df36de13SAntoniu Miclaus st->chip_info = chip_info;
1869df36de13SAntoniu Miclaus
1870df36de13SAntoniu Miclaus mutex_init(&st->lock);
1871df36de13SAntoniu Miclaus
1872df36de13SAntoniu Miclaus indio_dev->channels = adxl380_channels;
1873df36de13SAntoniu Miclaus indio_dev->num_channels = ARRAY_SIZE(adxl380_channels);
1874df36de13SAntoniu Miclaus indio_dev->name = chip_info->name;
1875df36de13SAntoniu Miclaus indio_dev->info = &adxl380_info;
1876df36de13SAntoniu Miclaus indio_dev->modes = INDIO_DIRECT_MODE;
1877df36de13SAntoniu Miclaus
1878df36de13SAntoniu Miclaus ret = devm_regulator_get_enable(dev, "vddio");
1879df36de13SAntoniu Miclaus if (ret)
1880df36de13SAntoniu Miclaus return dev_err_probe(st->dev, ret,
1881df36de13SAntoniu Miclaus "Failed to get vddio regulator\n");
1882df36de13SAntoniu Miclaus
1883df36de13SAntoniu Miclaus ret = devm_regulator_get_enable(st->dev, "vsupply");
1884df36de13SAntoniu Miclaus if (ret)
1885df36de13SAntoniu Miclaus return dev_err_probe(st->dev, ret,
1886df36de13SAntoniu Miclaus "Failed to get vsupply regulator\n");
1887df36de13SAntoniu Miclaus
1888df36de13SAntoniu Miclaus ret = adxl380_setup(indio_dev);
1889df36de13SAntoniu Miclaus if (ret)
1890df36de13SAntoniu Miclaus return ret;
1891df36de13SAntoniu Miclaus
1892df36de13SAntoniu Miclaus ret = devm_iio_kfifo_buffer_setup_ext(st->dev, indio_dev,
1893df36de13SAntoniu Miclaus &adxl380_buffer_ops,
1894df36de13SAntoniu Miclaus adxl380_fifo_attributes);
1895df36de13SAntoniu Miclaus if (ret)
1896df36de13SAntoniu Miclaus return ret;
1897df36de13SAntoniu Miclaus
1898df36de13SAntoniu Miclaus return devm_iio_device_register(dev, indio_dev);
1899df36de13SAntoniu Miclaus }
1900df36de13SAntoniu Miclaus EXPORT_SYMBOL_NS_GPL(adxl380_probe, IIO_ADXL380);
1901df36de13SAntoniu Miclaus
1902df36de13SAntoniu Miclaus MODULE_AUTHOR("Ramona Gradinariu <ramona.gradinariu@analog.com>");
1903df36de13SAntoniu Miclaus MODULE_AUTHOR("Antoniu Miclaus <antoniu.miclaus@analog.com>");
1904df36de13SAntoniu Miclaus MODULE_DESCRIPTION("Analog Devices ADXL380 3-axis accelerometer driver");
1905df36de13SAntoniu Miclaus MODULE_LICENSE("GPL");
1906