1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2d62e5feeSJonathan Cameron /*
3d62e5feeSJonathan Cameron * sca3000_core.c -- support VTI sca3000 series accelerometers via SPI
4d62e5feeSJonathan Cameron *
5d62e5feeSJonathan Cameron * Copyright (c) 2009 Jonathan Cameron <jic23@kernel.org>
6d62e5feeSJonathan Cameron *
7d62e5feeSJonathan Cameron * See industrialio/accels/sca3000.h for comments.
8d62e5feeSJonathan Cameron */
9d62e5feeSJonathan Cameron
10d62e5feeSJonathan Cameron #include <linux/interrupt.h>
11d62e5feeSJonathan Cameron #include <linux/fs.h>
12d62e5feeSJonathan Cameron #include <linux/device.h>
13d62e5feeSJonathan Cameron #include <linux/slab.h>
14d62e5feeSJonathan Cameron #include <linux/kernel.h>
15d62e5feeSJonathan Cameron #include <linux/spi/spi.h>
16d62e5feeSJonathan Cameron #include <linux/sysfs.h>
17d62e5feeSJonathan Cameron #include <linux/module.h>
18d62e5feeSJonathan Cameron #include <linux/uaccess.h>
19d62e5feeSJonathan Cameron #include <linux/iio/iio.h>
20d62e5feeSJonathan Cameron #include <linux/iio/sysfs.h>
21d62e5feeSJonathan Cameron #include <linux/iio/events.h>
22d62e5feeSJonathan Cameron #include <linux/iio/buffer.h>
23d62e5feeSJonathan Cameron #include <linux/iio/kfifo_buf.h>
24d62e5feeSJonathan Cameron
25d62e5feeSJonathan Cameron #define SCA3000_WRITE_REG(a) (((a) << 2) | 0x02)
26d62e5feeSJonathan Cameron #define SCA3000_READ_REG(a) ((a) << 2)
27d62e5feeSJonathan Cameron
28d62e5feeSJonathan Cameron #define SCA3000_REG_REVID_ADDR 0x00
29d62e5feeSJonathan Cameron #define SCA3000_REG_REVID_MAJOR_MASK GENMASK(8, 4)
30d62e5feeSJonathan Cameron #define SCA3000_REG_REVID_MINOR_MASK GENMASK(3, 0)
31d62e5feeSJonathan Cameron
32d62e5feeSJonathan Cameron #define SCA3000_REG_STATUS_ADDR 0x02
33d62e5feeSJonathan Cameron #define SCA3000_LOCKED BIT(5)
34d62e5feeSJonathan Cameron #define SCA3000_EEPROM_CS_ERROR BIT(1)
35d62e5feeSJonathan Cameron #define SCA3000_SPI_FRAME_ERROR BIT(0)
36d62e5feeSJonathan Cameron
37d62e5feeSJonathan Cameron /* All reads done using register decrement so no need to directly access LSBs */
38d62e5feeSJonathan Cameron #define SCA3000_REG_X_MSB_ADDR 0x05
39d62e5feeSJonathan Cameron #define SCA3000_REG_Y_MSB_ADDR 0x07
40d62e5feeSJonathan Cameron #define SCA3000_REG_Z_MSB_ADDR 0x09
41d62e5feeSJonathan Cameron
42d62e5feeSJonathan Cameron #define SCA3000_REG_RING_OUT_ADDR 0x0f
43d62e5feeSJonathan Cameron
44d62e5feeSJonathan Cameron /* Temp read untested - the e05 doesn't have the sensor */
45d62e5feeSJonathan Cameron #define SCA3000_REG_TEMP_MSB_ADDR 0x13
46d62e5feeSJonathan Cameron
47d62e5feeSJonathan Cameron #define SCA3000_REG_MODE_ADDR 0x14
48d62e5feeSJonathan Cameron #define SCA3000_MODE_PROT_MASK 0x28
49d62e5feeSJonathan Cameron #define SCA3000_REG_MODE_RING_BUF_ENABLE BIT(7)
50d62e5feeSJonathan Cameron #define SCA3000_REG_MODE_RING_BUF_8BIT BIT(6)
51d62e5feeSJonathan Cameron
52d62e5feeSJonathan Cameron /*
53d62e5feeSJonathan Cameron * Free fall detection triggers an interrupt if the acceleration
54d62e5feeSJonathan Cameron * is below a threshold for equivalent of 25cm drop
55d62e5feeSJonathan Cameron */
56d62e5feeSJonathan Cameron #define SCA3000_REG_MODE_FREE_FALL_DETECT BIT(4)
57d62e5feeSJonathan Cameron #define SCA3000_REG_MODE_MEAS_MODE_NORMAL 0x00
58d62e5feeSJonathan Cameron #define SCA3000_REG_MODE_MEAS_MODE_OP_1 0x01
59d62e5feeSJonathan Cameron #define SCA3000_REG_MODE_MEAS_MODE_OP_2 0x02
60d62e5feeSJonathan Cameron
61d62e5feeSJonathan Cameron /*
62d62e5feeSJonathan Cameron * In motion detection mode the accelerations are band pass filtered
63d62e5feeSJonathan Cameron * (approx 1 - 25Hz) and then a programmable threshold used to trigger
64d62e5feeSJonathan Cameron * and interrupt.
65d62e5feeSJonathan Cameron */
66d62e5feeSJonathan Cameron #define SCA3000_REG_MODE_MEAS_MODE_MOT_DET 0x03
67d62e5feeSJonathan Cameron #define SCA3000_REG_MODE_MODE_MASK 0x03
68d62e5feeSJonathan Cameron
69d62e5feeSJonathan Cameron #define SCA3000_REG_BUF_COUNT_ADDR 0x15
70d62e5feeSJonathan Cameron
71d62e5feeSJonathan Cameron #define SCA3000_REG_INT_STATUS_ADDR 0x16
72d62e5feeSJonathan Cameron #define SCA3000_REG_INT_STATUS_THREE_QUARTERS BIT(7)
73d62e5feeSJonathan Cameron #define SCA3000_REG_INT_STATUS_HALF BIT(6)
74d62e5feeSJonathan Cameron
75d62e5feeSJonathan Cameron #define SCA3000_INT_STATUS_FREE_FALL BIT(3)
76d62e5feeSJonathan Cameron #define SCA3000_INT_STATUS_Y_TRIGGER BIT(2)
77d62e5feeSJonathan Cameron #define SCA3000_INT_STATUS_X_TRIGGER BIT(1)
78d62e5feeSJonathan Cameron #define SCA3000_INT_STATUS_Z_TRIGGER BIT(0)
79d62e5feeSJonathan Cameron
80d62e5feeSJonathan Cameron /* Used to allow access to multiplexed registers */
81d62e5feeSJonathan Cameron #define SCA3000_REG_CTRL_SEL_ADDR 0x18
82d62e5feeSJonathan Cameron /* Only available for SCA3000-D03 and SCA3000-D01 */
83d62e5feeSJonathan Cameron #define SCA3000_REG_CTRL_SEL_I2C_DISABLE 0x01
84d62e5feeSJonathan Cameron #define SCA3000_REG_CTRL_SEL_MD_CTRL 0x02
85d62e5feeSJonathan Cameron #define SCA3000_REG_CTRL_SEL_MD_Y_TH 0x03
86d62e5feeSJonathan Cameron #define SCA3000_REG_CTRL_SEL_MD_X_TH 0x04
87d62e5feeSJonathan Cameron #define SCA3000_REG_CTRL_SEL_MD_Z_TH 0x05
88d62e5feeSJonathan Cameron /*
89d62e5feeSJonathan Cameron * BE VERY CAREFUL WITH THIS, IF 3 BITS ARE NOT SET the device
90d62e5feeSJonathan Cameron * will not function
91d62e5feeSJonathan Cameron */
92d62e5feeSJonathan Cameron #define SCA3000_REG_CTRL_SEL_OUT_CTRL 0x0B
93d62e5feeSJonathan Cameron
94d62e5feeSJonathan Cameron #define SCA3000_REG_OUT_CTRL_PROT_MASK 0xE0
95d62e5feeSJonathan Cameron #define SCA3000_REG_OUT_CTRL_BUF_X_EN 0x10
96d62e5feeSJonathan Cameron #define SCA3000_REG_OUT_CTRL_BUF_Y_EN 0x08
97d62e5feeSJonathan Cameron #define SCA3000_REG_OUT_CTRL_BUF_Z_EN 0x04
98d62e5feeSJonathan Cameron #define SCA3000_REG_OUT_CTRL_BUF_DIV_MASK 0x03
99d62e5feeSJonathan Cameron #define SCA3000_REG_OUT_CTRL_BUF_DIV_4 0x02
100d62e5feeSJonathan Cameron #define SCA3000_REG_OUT_CTRL_BUF_DIV_2 0x01
101d62e5feeSJonathan Cameron
102d62e5feeSJonathan Cameron
103d62e5feeSJonathan Cameron /*
104d62e5feeSJonathan Cameron * Control which motion detector interrupts are on.
105d62e5feeSJonathan Cameron * For now only OR combinations are supported.
106d62e5feeSJonathan Cameron */
107d62e5feeSJonathan Cameron #define SCA3000_MD_CTRL_PROT_MASK 0xC0
108d62e5feeSJonathan Cameron #define SCA3000_MD_CTRL_OR_Y BIT(0)
109d62e5feeSJonathan Cameron #define SCA3000_MD_CTRL_OR_X BIT(1)
110d62e5feeSJonathan Cameron #define SCA3000_MD_CTRL_OR_Z BIT(2)
111d62e5feeSJonathan Cameron /* Currently unsupported */
112d62e5feeSJonathan Cameron #define SCA3000_MD_CTRL_AND_Y BIT(3)
113d62e5feeSJonathan Cameron #define SCA3000_MD_CTRL_AND_X BIT(4)
11480343f5bSChristophe JAILLET #define SCA3000_MD_CTRL_AND_Z BIT(5)
115d62e5feeSJonathan Cameron
116d62e5feeSJonathan Cameron /*
117d62e5feeSJonathan Cameron * Some control registers of complex access methods requiring this register to
118d62e5feeSJonathan Cameron * be used to remove a lock.
119d62e5feeSJonathan Cameron */
120d62e5feeSJonathan Cameron #define SCA3000_REG_UNLOCK_ADDR 0x1e
121d62e5feeSJonathan Cameron
122d62e5feeSJonathan Cameron #define SCA3000_REG_INT_MASK_ADDR 0x21
123d62e5feeSJonathan Cameron #define SCA3000_REG_INT_MASK_PROT_MASK 0x1C
124d62e5feeSJonathan Cameron
125d62e5feeSJonathan Cameron #define SCA3000_REG_INT_MASK_RING_THREE_QUARTER BIT(7)
126d62e5feeSJonathan Cameron #define SCA3000_REG_INT_MASK_RING_HALF BIT(6)
127d62e5feeSJonathan Cameron
128d62e5feeSJonathan Cameron #define SCA3000_REG_INT_MASK_ALL_INTS 0x02
129d62e5feeSJonathan Cameron #define SCA3000_REG_INT_MASK_ACTIVE_HIGH 0x01
130d62e5feeSJonathan Cameron #define SCA3000_REG_INT_MASK_ACTIVE_LOW 0x00
131d62e5feeSJonathan Cameron /* Values of multiplexed registers (write to ctrl_data after select) */
132d62e5feeSJonathan Cameron #define SCA3000_REG_CTRL_DATA_ADDR 0x22
133d62e5feeSJonathan Cameron
134d62e5feeSJonathan Cameron /*
135d62e5feeSJonathan Cameron * Measurement modes available on some sca3000 series chips. Code assumes others
136d62e5feeSJonathan Cameron * may become available in the future.
137d62e5feeSJonathan Cameron *
138d62e5feeSJonathan Cameron * Bypass - Bypass the low-pass filter in the signal channel so as to increase
139d62e5feeSJonathan Cameron * signal bandwidth.
140d62e5feeSJonathan Cameron *
141d62e5feeSJonathan Cameron * Narrow - Narrow low-pass filtering of the signal channel and half output
142d62e5feeSJonathan Cameron * data rate by decimation.
143d62e5feeSJonathan Cameron *
144d62e5feeSJonathan Cameron * Wide - Widen low-pass filtering of signal channel to increase bandwidth
145d62e5feeSJonathan Cameron */
146d62e5feeSJonathan Cameron #define SCA3000_OP_MODE_BYPASS 0x01
147d62e5feeSJonathan Cameron #define SCA3000_OP_MODE_NARROW 0x02
148d62e5feeSJonathan Cameron #define SCA3000_OP_MODE_WIDE 0x04
149d62e5feeSJonathan Cameron #define SCA3000_MAX_TX 6
150d62e5feeSJonathan Cameron #define SCA3000_MAX_RX 2
151d62e5feeSJonathan Cameron
152d62e5feeSJonathan Cameron /**
153d62e5feeSJonathan Cameron * struct sca3000_state - device instance state information
154d62e5feeSJonathan Cameron * @us: the associated spi device
155d62e5feeSJonathan Cameron * @info: chip variant information
156d62e5feeSJonathan Cameron * @last_timestamp: the timestamp of the last event
157d62e5feeSJonathan Cameron * @mo_det_use_count: reference counter for the motion detection unit
158d62e5feeSJonathan Cameron * @lock: lock used to protect elements of sca3000_state
159d62e5feeSJonathan Cameron * and the underlying device state.
160d62e5feeSJonathan Cameron * @tx: dma-able transmit buffer
161d62e5feeSJonathan Cameron * @rx: dma-able receive buffer
162d62e5feeSJonathan Cameron **/
163d62e5feeSJonathan Cameron struct sca3000_state {
164d62e5feeSJonathan Cameron struct spi_device *us;
165d62e5feeSJonathan Cameron const struct sca3000_chip_info *info;
166d62e5feeSJonathan Cameron s64 last_timestamp;
167d62e5feeSJonathan Cameron int mo_det_use_count;
168d62e5feeSJonathan Cameron struct mutex lock;
169d62e5feeSJonathan Cameron /* Can these share a cacheline ? */
170*a263456fSJonathan Cameron u8 rx[384] __aligned(IIO_DMA_MINALIGN);
171*a263456fSJonathan Cameron u8 tx[6] __aligned(IIO_DMA_MINALIGN);
172d62e5feeSJonathan Cameron };
173d62e5feeSJonathan Cameron
174d62e5feeSJonathan Cameron /**
175d62e5feeSJonathan Cameron * struct sca3000_chip_info - model dependent parameters
176d62e5feeSJonathan Cameron * @scale: scale * 10^-6
177d62e5feeSJonathan Cameron * @temp_output: some devices have temperature sensors.
178d62e5feeSJonathan Cameron * @measurement_mode_freq: normal mode sampling frequency
179d62e5feeSJonathan Cameron * @measurement_mode_3db_freq: 3db cutoff frequency of the low pass filter for
180d62e5feeSJonathan Cameron * the normal measurement mode.
181d62e5feeSJonathan Cameron * @option_mode_1: first optional mode. Not all models have one
182d62e5feeSJonathan Cameron * @option_mode_1_freq: option mode 1 sampling frequency
183d62e5feeSJonathan Cameron * @option_mode_1_3db_freq: 3db cutoff frequency of the low pass filter for
184d62e5feeSJonathan Cameron * the first option mode.
185d62e5feeSJonathan Cameron * @option_mode_2: second optional mode. Not all chips have one
186d62e5feeSJonathan Cameron * @option_mode_2_freq: option mode 2 sampling frequency
187d62e5feeSJonathan Cameron * @option_mode_2_3db_freq: 3db cutoff frequency of the low pass filter for
188d62e5feeSJonathan Cameron * the second option mode.
189fb37b5f8SLee Jones * @mot_det_mult_xz: Bit wise multipliers to calculate the threshold
190d62e5feeSJonathan Cameron * for motion detection in the x and z axis.
191fb37b5f8SLee Jones * @mot_det_mult_y: Bit wise multipliers to calculate the threshold
192d62e5feeSJonathan Cameron * for motion detection in the y axis.
193d62e5feeSJonathan Cameron *
194d62e5feeSJonathan Cameron * This structure is used to hold information about the functionality of a given
195d62e5feeSJonathan Cameron * sca3000 variant.
196d62e5feeSJonathan Cameron **/
197d62e5feeSJonathan Cameron struct sca3000_chip_info {
198d62e5feeSJonathan Cameron unsigned int scale;
199d62e5feeSJonathan Cameron bool temp_output;
200d62e5feeSJonathan Cameron int measurement_mode_freq;
201d62e5feeSJonathan Cameron int measurement_mode_3db_freq;
202d62e5feeSJonathan Cameron int option_mode_1;
203d62e5feeSJonathan Cameron int option_mode_1_freq;
204d62e5feeSJonathan Cameron int option_mode_1_3db_freq;
205d62e5feeSJonathan Cameron int option_mode_2;
206d62e5feeSJonathan Cameron int option_mode_2_freq;
207d62e5feeSJonathan Cameron int option_mode_2_3db_freq;
208d62e5feeSJonathan Cameron int mot_det_mult_xz[6];
209d62e5feeSJonathan Cameron int mot_det_mult_y[7];
210d62e5feeSJonathan Cameron };
211d62e5feeSJonathan Cameron
212d62e5feeSJonathan Cameron enum sca3000_variant {
213d62e5feeSJonathan Cameron d01,
214d62e5feeSJonathan Cameron e02,
215d62e5feeSJonathan Cameron e04,
216d62e5feeSJonathan Cameron e05,
217d62e5feeSJonathan Cameron };
218d62e5feeSJonathan Cameron
219d62e5feeSJonathan Cameron /*
220d62e5feeSJonathan Cameron * Note where option modes are not defined, the chip simply does not
221d62e5feeSJonathan Cameron * support any.
222d62e5feeSJonathan Cameron * Other chips in the sca3000 series use i2c and are not included here.
223d62e5feeSJonathan Cameron *
224d62e5feeSJonathan Cameron * Some of these devices are only listed in the family data sheet and
225d62e5feeSJonathan Cameron * do not actually appear to be available.
226d62e5feeSJonathan Cameron */
227d62e5feeSJonathan Cameron static const struct sca3000_chip_info sca3000_spi_chip_info_tbl[] = {
228d62e5feeSJonathan Cameron [d01] = {
229d62e5feeSJonathan Cameron .scale = 7357,
230d62e5feeSJonathan Cameron .temp_output = true,
231d62e5feeSJonathan Cameron .measurement_mode_freq = 250,
232d62e5feeSJonathan Cameron .measurement_mode_3db_freq = 45,
233d62e5feeSJonathan Cameron .option_mode_1 = SCA3000_OP_MODE_BYPASS,
234d62e5feeSJonathan Cameron .option_mode_1_freq = 250,
235d62e5feeSJonathan Cameron .option_mode_1_3db_freq = 70,
236d62e5feeSJonathan Cameron .mot_det_mult_xz = {50, 100, 200, 350, 650, 1300},
237d62e5feeSJonathan Cameron .mot_det_mult_y = {50, 100, 150, 250, 450, 850, 1750},
238d62e5feeSJonathan Cameron },
239d62e5feeSJonathan Cameron [e02] = {
240d62e5feeSJonathan Cameron .scale = 9810,
241d62e5feeSJonathan Cameron .measurement_mode_freq = 125,
242d62e5feeSJonathan Cameron .measurement_mode_3db_freq = 40,
243d62e5feeSJonathan Cameron .option_mode_1 = SCA3000_OP_MODE_NARROW,
244d62e5feeSJonathan Cameron .option_mode_1_freq = 63,
245d62e5feeSJonathan Cameron .option_mode_1_3db_freq = 11,
246d62e5feeSJonathan Cameron .mot_det_mult_xz = {100, 150, 300, 550, 1050, 2050},
247d62e5feeSJonathan Cameron .mot_det_mult_y = {50, 100, 200, 350, 700, 1350, 2700},
248d62e5feeSJonathan Cameron },
249d62e5feeSJonathan Cameron [e04] = {
250d62e5feeSJonathan Cameron .scale = 19620,
251d62e5feeSJonathan Cameron .measurement_mode_freq = 100,
252d62e5feeSJonathan Cameron .measurement_mode_3db_freq = 38,
253d62e5feeSJonathan Cameron .option_mode_1 = SCA3000_OP_MODE_NARROW,
254d62e5feeSJonathan Cameron .option_mode_1_freq = 50,
255d62e5feeSJonathan Cameron .option_mode_1_3db_freq = 9,
256d62e5feeSJonathan Cameron .option_mode_2 = SCA3000_OP_MODE_WIDE,
257d62e5feeSJonathan Cameron .option_mode_2_freq = 400,
258d62e5feeSJonathan Cameron .option_mode_2_3db_freq = 70,
259d62e5feeSJonathan Cameron .mot_det_mult_xz = {200, 300, 600, 1100, 2100, 4100},
260d62e5feeSJonathan Cameron .mot_det_mult_y = {100, 200, 400, 7000, 1400, 2700, 54000},
261d62e5feeSJonathan Cameron },
262d62e5feeSJonathan Cameron [e05] = {
263d62e5feeSJonathan Cameron .scale = 61313,
264d62e5feeSJonathan Cameron .measurement_mode_freq = 200,
265d62e5feeSJonathan Cameron .measurement_mode_3db_freq = 60,
266d62e5feeSJonathan Cameron .option_mode_1 = SCA3000_OP_MODE_NARROW,
267d62e5feeSJonathan Cameron .option_mode_1_freq = 50,
268d62e5feeSJonathan Cameron .option_mode_1_3db_freq = 9,
269d62e5feeSJonathan Cameron .option_mode_2 = SCA3000_OP_MODE_WIDE,
270d62e5feeSJonathan Cameron .option_mode_2_freq = 400,
271d62e5feeSJonathan Cameron .option_mode_2_3db_freq = 75,
272d62e5feeSJonathan Cameron .mot_det_mult_xz = {600, 900, 1700, 3200, 6100, 11900},
273d62e5feeSJonathan Cameron .mot_det_mult_y = {300, 600, 1200, 2000, 4100, 7800, 15600},
274d62e5feeSJonathan Cameron },
275d62e5feeSJonathan Cameron };
276d62e5feeSJonathan Cameron
sca3000_write_reg(struct sca3000_state * st,u8 address,u8 val)277d62e5feeSJonathan Cameron static int sca3000_write_reg(struct sca3000_state *st, u8 address, u8 val)
278d62e5feeSJonathan Cameron {
279d62e5feeSJonathan Cameron st->tx[0] = SCA3000_WRITE_REG(address);
280d62e5feeSJonathan Cameron st->tx[1] = val;
281d62e5feeSJonathan Cameron return spi_write(st->us, st->tx, 2);
282d62e5feeSJonathan Cameron }
283d62e5feeSJonathan Cameron
sca3000_read_data_short(struct sca3000_state * st,u8 reg_address_high,int len)284d62e5feeSJonathan Cameron static int sca3000_read_data_short(struct sca3000_state *st,
285d62e5feeSJonathan Cameron u8 reg_address_high,
286d62e5feeSJonathan Cameron int len)
287d62e5feeSJonathan Cameron {
288d62e5feeSJonathan Cameron struct spi_transfer xfer[2] = {
289d62e5feeSJonathan Cameron {
290d62e5feeSJonathan Cameron .len = 1,
291d62e5feeSJonathan Cameron .tx_buf = st->tx,
292d62e5feeSJonathan Cameron }, {
293d62e5feeSJonathan Cameron .len = len,
294d62e5feeSJonathan Cameron .rx_buf = st->rx,
295d62e5feeSJonathan Cameron }
296d62e5feeSJonathan Cameron };
297d62e5feeSJonathan Cameron st->tx[0] = SCA3000_READ_REG(reg_address_high);
298d62e5feeSJonathan Cameron
299d62e5feeSJonathan Cameron return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer));
300d62e5feeSJonathan Cameron }
301d62e5feeSJonathan Cameron
302d62e5feeSJonathan Cameron /**
303d62e5feeSJonathan Cameron * sca3000_reg_lock_on() - test if the ctrl register lock is on
304d62e5feeSJonathan Cameron * @st: Driver specific device instance data.
305d62e5feeSJonathan Cameron *
306d62e5feeSJonathan Cameron * Lock must be held.
307d62e5feeSJonathan Cameron **/
sca3000_reg_lock_on(struct sca3000_state * st)308d62e5feeSJonathan Cameron static int sca3000_reg_lock_on(struct sca3000_state *st)
309d62e5feeSJonathan Cameron {
310d62e5feeSJonathan Cameron int ret;
311d62e5feeSJonathan Cameron
312d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_STATUS_ADDR, 1);
313d62e5feeSJonathan Cameron if (ret < 0)
314d62e5feeSJonathan Cameron return ret;
315d62e5feeSJonathan Cameron
316d62e5feeSJonathan Cameron return !(st->rx[0] & SCA3000_LOCKED);
317d62e5feeSJonathan Cameron }
318d62e5feeSJonathan Cameron
319d62e5feeSJonathan Cameron /**
320d62e5feeSJonathan Cameron * __sca3000_unlock_reg_lock() - unlock the control registers
321d62e5feeSJonathan Cameron * @st: Driver specific device instance data.
322d62e5feeSJonathan Cameron *
323d62e5feeSJonathan Cameron * Note the device does not appear to support doing this in a single transfer.
324d62e5feeSJonathan Cameron * This should only ever be used as part of ctrl reg read.
325d62e5feeSJonathan Cameron * Lock must be held before calling this
326d62e5feeSJonathan Cameron */
__sca3000_unlock_reg_lock(struct sca3000_state * st)327d62e5feeSJonathan Cameron static int __sca3000_unlock_reg_lock(struct sca3000_state *st)
328d62e5feeSJonathan Cameron {
329d62e5feeSJonathan Cameron struct spi_transfer xfer[3] = {
330d62e5feeSJonathan Cameron {
331d62e5feeSJonathan Cameron .len = 2,
332d62e5feeSJonathan Cameron .cs_change = 1,
333d62e5feeSJonathan Cameron .tx_buf = st->tx,
334d62e5feeSJonathan Cameron }, {
335d62e5feeSJonathan Cameron .len = 2,
336d62e5feeSJonathan Cameron .cs_change = 1,
337d62e5feeSJonathan Cameron .tx_buf = st->tx + 2,
338d62e5feeSJonathan Cameron }, {
339d62e5feeSJonathan Cameron .len = 2,
340d62e5feeSJonathan Cameron .tx_buf = st->tx + 4,
341d62e5feeSJonathan Cameron },
342d62e5feeSJonathan Cameron };
343d62e5feeSJonathan Cameron st->tx[0] = SCA3000_WRITE_REG(SCA3000_REG_UNLOCK_ADDR);
344d62e5feeSJonathan Cameron st->tx[1] = 0x00;
345d62e5feeSJonathan Cameron st->tx[2] = SCA3000_WRITE_REG(SCA3000_REG_UNLOCK_ADDR);
346d62e5feeSJonathan Cameron st->tx[3] = 0x50;
347d62e5feeSJonathan Cameron st->tx[4] = SCA3000_WRITE_REG(SCA3000_REG_UNLOCK_ADDR);
348d62e5feeSJonathan Cameron st->tx[5] = 0xA0;
349d62e5feeSJonathan Cameron
350d62e5feeSJonathan Cameron return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer));
351d62e5feeSJonathan Cameron }
352d62e5feeSJonathan Cameron
353d62e5feeSJonathan Cameron /**
354d7f1c0c3SJonathan Cameron * sca3000_write_ctrl_reg() - write to a lock protect ctrl register
355d62e5feeSJonathan Cameron * @st: Driver specific device instance data.
356d62e5feeSJonathan Cameron * @sel: selects which registers we wish to write to
357d62e5feeSJonathan Cameron * @val: the value to be written
358d62e5feeSJonathan Cameron *
359d62e5feeSJonathan Cameron * Certain control registers are protected against overwriting by the lock
360d62e5feeSJonathan Cameron * register and use a shared write address. This function allows writing of
361d62e5feeSJonathan Cameron * these registers.
362d62e5feeSJonathan Cameron * Lock must be held.
363d62e5feeSJonathan Cameron */
sca3000_write_ctrl_reg(struct sca3000_state * st,u8 sel,uint8_t val)364d62e5feeSJonathan Cameron static int sca3000_write_ctrl_reg(struct sca3000_state *st,
365d62e5feeSJonathan Cameron u8 sel,
366d62e5feeSJonathan Cameron uint8_t val)
367d62e5feeSJonathan Cameron {
368d62e5feeSJonathan Cameron int ret;
369d62e5feeSJonathan Cameron
370d62e5feeSJonathan Cameron ret = sca3000_reg_lock_on(st);
371d62e5feeSJonathan Cameron if (ret < 0)
372d62e5feeSJonathan Cameron goto error_ret;
373d62e5feeSJonathan Cameron if (ret) {
374d62e5feeSJonathan Cameron ret = __sca3000_unlock_reg_lock(st);
375d62e5feeSJonathan Cameron if (ret)
376d62e5feeSJonathan Cameron goto error_ret;
377d62e5feeSJonathan Cameron }
378d62e5feeSJonathan Cameron
379d62e5feeSJonathan Cameron /* Set the control select register */
380d62e5feeSJonathan Cameron ret = sca3000_write_reg(st, SCA3000_REG_CTRL_SEL_ADDR, sel);
381d62e5feeSJonathan Cameron if (ret)
382d62e5feeSJonathan Cameron goto error_ret;
383d62e5feeSJonathan Cameron
384d62e5feeSJonathan Cameron /* Write the actual value into the register */
385d62e5feeSJonathan Cameron ret = sca3000_write_reg(st, SCA3000_REG_CTRL_DATA_ADDR, val);
386d62e5feeSJonathan Cameron
387d62e5feeSJonathan Cameron error_ret:
388d62e5feeSJonathan Cameron return ret;
389d62e5feeSJonathan Cameron }
390d62e5feeSJonathan Cameron
391d62e5feeSJonathan Cameron /**
392d7f1c0c3SJonathan Cameron * sca3000_read_ctrl_reg() - read from lock protected control register.
393d62e5feeSJonathan Cameron * @st: Driver specific device instance data.
394d62e5feeSJonathan Cameron * @ctrl_reg: Which ctrl register do we want to read.
395d62e5feeSJonathan Cameron *
396d62e5feeSJonathan Cameron * Lock must be held.
397d62e5feeSJonathan Cameron */
sca3000_read_ctrl_reg(struct sca3000_state * st,u8 ctrl_reg)398d62e5feeSJonathan Cameron static int sca3000_read_ctrl_reg(struct sca3000_state *st,
399d62e5feeSJonathan Cameron u8 ctrl_reg)
400d62e5feeSJonathan Cameron {
401d62e5feeSJonathan Cameron int ret;
402d62e5feeSJonathan Cameron
403d62e5feeSJonathan Cameron ret = sca3000_reg_lock_on(st);
404d62e5feeSJonathan Cameron if (ret < 0)
405d62e5feeSJonathan Cameron goto error_ret;
406d62e5feeSJonathan Cameron if (ret) {
407d62e5feeSJonathan Cameron ret = __sca3000_unlock_reg_lock(st);
408d62e5feeSJonathan Cameron if (ret)
409d62e5feeSJonathan Cameron goto error_ret;
410d62e5feeSJonathan Cameron }
411d62e5feeSJonathan Cameron /* Set the control select register */
412d62e5feeSJonathan Cameron ret = sca3000_write_reg(st, SCA3000_REG_CTRL_SEL_ADDR, ctrl_reg);
413d62e5feeSJonathan Cameron if (ret)
414d62e5feeSJonathan Cameron goto error_ret;
415d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_CTRL_DATA_ADDR, 1);
416d62e5feeSJonathan Cameron if (ret)
417d62e5feeSJonathan Cameron goto error_ret;
418d62e5feeSJonathan Cameron return st->rx[0];
419d62e5feeSJonathan Cameron error_ret:
420d62e5feeSJonathan Cameron return ret;
421d62e5feeSJonathan Cameron }
422d62e5feeSJonathan Cameron
423d62e5feeSJonathan Cameron /**
424d7f1c0c3SJonathan Cameron * sca3000_print_rev() - sysfs interface to read the chip revision number
425d62e5feeSJonathan Cameron * @indio_dev: Device instance specific generic IIO data.
426d62e5feeSJonathan Cameron * Driver specific device instance data can be obtained via
4279e63be2aSXiang wangx * iio_priv(indio_dev)
428d62e5feeSJonathan Cameron */
sca3000_print_rev(struct iio_dev * indio_dev)429d62e5feeSJonathan Cameron static int sca3000_print_rev(struct iio_dev *indio_dev)
430d62e5feeSJonathan Cameron {
431d62e5feeSJonathan Cameron int ret;
432d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev);
433d62e5feeSJonathan Cameron
434d62e5feeSJonathan Cameron mutex_lock(&st->lock);
435d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_REVID_ADDR, 1);
436d62e5feeSJonathan Cameron if (ret < 0)
437d62e5feeSJonathan Cameron goto error_ret;
438d62e5feeSJonathan Cameron dev_info(&indio_dev->dev,
439d62e5feeSJonathan Cameron "sca3000 revision major=%lu, minor=%lu\n",
440d62e5feeSJonathan Cameron st->rx[0] & SCA3000_REG_REVID_MAJOR_MASK,
441d62e5feeSJonathan Cameron st->rx[0] & SCA3000_REG_REVID_MINOR_MASK);
442d62e5feeSJonathan Cameron error_ret:
443d62e5feeSJonathan Cameron mutex_unlock(&st->lock);
444d62e5feeSJonathan Cameron
445d62e5feeSJonathan Cameron return ret;
446d62e5feeSJonathan Cameron }
447d62e5feeSJonathan Cameron
448d62e5feeSJonathan Cameron static ssize_t
sca3000_show_available_3db_freqs(struct device * dev,struct device_attribute * attr,char * buf)449d62e5feeSJonathan Cameron sca3000_show_available_3db_freqs(struct device *dev,
450d62e5feeSJonathan Cameron struct device_attribute *attr,
451d62e5feeSJonathan Cameron char *buf)
452d62e5feeSJonathan Cameron {
453d62e5feeSJonathan Cameron struct iio_dev *indio_dev = dev_to_iio_dev(dev);
454d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev);
455d62e5feeSJonathan Cameron int len;
456d62e5feeSJonathan Cameron
457d62e5feeSJonathan Cameron len = sprintf(buf, "%d", st->info->measurement_mode_3db_freq);
458d62e5feeSJonathan Cameron if (st->info->option_mode_1)
459d62e5feeSJonathan Cameron len += sprintf(buf + len, " %d",
460d62e5feeSJonathan Cameron st->info->option_mode_1_3db_freq);
461d62e5feeSJonathan Cameron if (st->info->option_mode_2)
462d62e5feeSJonathan Cameron len += sprintf(buf + len, " %d",
463d62e5feeSJonathan Cameron st->info->option_mode_2_3db_freq);
464d62e5feeSJonathan Cameron len += sprintf(buf + len, "\n");
465d62e5feeSJonathan Cameron
466d62e5feeSJonathan Cameron return len;
467d62e5feeSJonathan Cameron }
468d62e5feeSJonathan Cameron
469d62e5feeSJonathan Cameron static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available,
470d62e5feeSJonathan Cameron S_IRUGO, sca3000_show_available_3db_freqs,
471d62e5feeSJonathan Cameron NULL, 0);
472d62e5feeSJonathan Cameron
473d62e5feeSJonathan Cameron static const struct iio_event_spec sca3000_event = {
474d62e5feeSJonathan Cameron .type = IIO_EV_TYPE_MAG,
475d62e5feeSJonathan Cameron .dir = IIO_EV_DIR_RISING,
476d62e5feeSJonathan Cameron .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE),
477d62e5feeSJonathan Cameron };
478d62e5feeSJonathan Cameron
479d62e5feeSJonathan Cameron /*
480d62e5feeSJonathan Cameron * Note the hack in the number of bits to pretend we have 2 more than
481d62e5feeSJonathan Cameron * we do in the fifo.
482d62e5feeSJonathan Cameron */
483d62e5feeSJonathan Cameron #define SCA3000_CHAN(index, mod) \
484d62e5feeSJonathan Cameron { \
485d62e5feeSJonathan Cameron .type = IIO_ACCEL, \
486d62e5feeSJonathan Cameron .modified = 1, \
487d62e5feeSJonathan Cameron .channel2 = mod, \
488d62e5feeSJonathan Cameron .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
489d62e5feeSJonathan Cameron .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |\
490d62e5feeSJonathan Cameron BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),\
491d62e5feeSJonathan Cameron .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
492d62e5feeSJonathan Cameron .address = index, \
493d62e5feeSJonathan Cameron .scan_index = index, \
494d62e5feeSJonathan Cameron .scan_type = { \
495d62e5feeSJonathan Cameron .sign = 's', \
496d62e5feeSJonathan Cameron .realbits = 13, \
497d62e5feeSJonathan Cameron .storagebits = 16, \
498d62e5feeSJonathan Cameron .shift = 3, \
499d62e5feeSJonathan Cameron .endianness = IIO_BE, \
500d62e5feeSJonathan Cameron }, \
501d62e5feeSJonathan Cameron .event_spec = &sca3000_event, \
502d62e5feeSJonathan Cameron .num_event_specs = 1, \
503d62e5feeSJonathan Cameron }
504d62e5feeSJonathan Cameron
505d62e5feeSJonathan Cameron static const struct iio_event_spec sca3000_freefall_event_spec = {
506d62e5feeSJonathan Cameron .type = IIO_EV_TYPE_MAG,
507d62e5feeSJonathan Cameron .dir = IIO_EV_DIR_FALLING,
508d62e5feeSJonathan Cameron .mask_separate = BIT(IIO_EV_INFO_ENABLE) |
509d62e5feeSJonathan Cameron BIT(IIO_EV_INFO_PERIOD),
510d62e5feeSJonathan Cameron };
511d62e5feeSJonathan Cameron
512d62e5feeSJonathan Cameron static const struct iio_chan_spec sca3000_channels[] = {
513d62e5feeSJonathan Cameron SCA3000_CHAN(0, IIO_MOD_X),
514d62e5feeSJonathan Cameron SCA3000_CHAN(1, IIO_MOD_Y),
515d62e5feeSJonathan Cameron SCA3000_CHAN(2, IIO_MOD_Z),
516d62e5feeSJonathan Cameron {
517d62e5feeSJonathan Cameron .type = IIO_ACCEL,
518d62e5feeSJonathan Cameron .modified = 1,
519d62e5feeSJonathan Cameron .channel2 = IIO_MOD_X_AND_Y_AND_Z,
520d62e5feeSJonathan Cameron .scan_index = -1, /* Fake channel */
521d62e5feeSJonathan Cameron .event_spec = &sca3000_freefall_event_spec,
522d62e5feeSJonathan Cameron .num_event_specs = 1,
523d62e5feeSJonathan Cameron },
524d62e5feeSJonathan Cameron };
525d62e5feeSJonathan Cameron
526d62e5feeSJonathan Cameron static const struct iio_chan_spec sca3000_channels_with_temp[] = {
527d62e5feeSJonathan Cameron SCA3000_CHAN(0, IIO_MOD_X),
528d62e5feeSJonathan Cameron SCA3000_CHAN(1, IIO_MOD_Y),
529d62e5feeSJonathan Cameron SCA3000_CHAN(2, IIO_MOD_Z),
530d62e5feeSJonathan Cameron {
531d62e5feeSJonathan Cameron .type = IIO_TEMP,
532d62e5feeSJonathan Cameron .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
533d62e5feeSJonathan Cameron .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
534d62e5feeSJonathan Cameron BIT(IIO_CHAN_INFO_OFFSET),
535d62e5feeSJonathan Cameron /* No buffer support */
536d62e5feeSJonathan Cameron .scan_index = -1,
5375405c9b4SGwendal Grignou .scan_type = {
5385405c9b4SGwendal Grignou .sign = 'u',
5395405c9b4SGwendal Grignou .realbits = 9,
5405405c9b4SGwendal Grignou .storagebits = 16,
5415405c9b4SGwendal Grignou .shift = 5,
5425405c9b4SGwendal Grignou .endianness = IIO_BE,
5435405c9b4SGwendal Grignou },
544d62e5feeSJonathan Cameron },
545d62e5feeSJonathan Cameron {
546d62e5feeSJonathan Cameron .type = IIO_ACCEL,
547d62e5feeSJonathan Cameron .modified = 1,
548d62e5feeSJonathan Cameron .channel2 = IIO_MOD_X_AND_Y_AND_Z,
549d62e5feeSJonathan Cameron .scan_index = -1, /* Fake channel */
550d62e5feeSJonathan Cameron .event_spec = &sca3000_freefall_event_spec,
551d62e5feeSJonathan Cameron .num_event_specs = 1,
552d62e5feeSJonathan Cameron },
553d62e5feeSJonathan Cameron };
554d62e5feeSJonathan Cameron
555d62e5feeSJonathan Cameron static u8 sca3000_addresses[3][3] = {
556d62e5feeSJonathan Cameron [0] = {SCA3000_REG_X_MSB_ADDR, SCA3000_REG_CTRL_SEL_MD_X_TH,
557d62e5feeSJonathan Cameron SCA3000_MD_CTRL_OR_X},
558d62e5feeSJonathan Cameron [1] = {SCA3000_REG_Y_MSB_ADDR, SCA3000_REG_CTRL_SEL_MD_Y_TH,
559d62e5feeSJonathan Cameron SCA3000_MD_CTRL_OR_Y},
560d62e5feeSJonathan Cameron [2] = {SCA3000_REG_Z_MSB_ADDR, SCA3000_REG_CTRL_SEL_MD_Z_TH,
561d62e5feeSJonathan Cameron SCA3000_MD_CTRL_OR_Z},
562d62e5feeSJonathan Cameron };
563d62e5feeSJonathan Cameron
564d62e5feeSJonathan Cameron /**
565d62e5feeSJonathan Cameron * __sca3000_get_base_freq() - obtain mode specific base frequency
566d62e5feeSJonathan Cameron * @st: Private driver specific device instance specific state.
567d62e5feeSJonathan Cameron * @info: chip type specific information.
568d62e5feeSJonathan Cameron * @base_freq: Base frequency for the current measurement mode.
569d62e5feeSJonathan Cameron *
570d62e5feeSJonathan Cameron * lock must be held
571d62e5feeSJonathan Cameron */
__sca3000_get_base_freq(struct sca3000_state * st,const struct sca3000_chip_info * info,int * base_freq)572d62e5feeSJonathan Cameron static inline int __sca3000_get_base_freq(struct sca3000_state *st,
573d62e5feeSJonathan Cameron const struct sca3000_chip_info *info,
574d62e5feeSJonathan Cameron int *base_freq)
575d62e5feeSJonathan Cameron {
576d62e5feeSJonathan Cameron int ret;
577d62e5feeSJonathan Cameron
578d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
579d62e5feeSJonathan Cameron if (ret)
580d62e5feeSJonathan Cameron goto error_ret;
581d62e5feeSJonathan Cameron switch (SCA3000_REG_MODE_MODE_MASK & st->rx[0]) {
582d62e5feeSJonathan Cameron case SCA3000_REG_MODE_MEAS_MODE_NORMAL:
583d62e5feeSJonathan Cameron *base_freq = info->measurement_mode_freq;
584d62e5feeSJonathan Cameron break;
585d62e5feeSJonathan Cameron case SCA3000_REG_MODE_MEAS_MODE_OP_1:
586d62e5feeSJonathan Cameron *base_freq = info->option_mode_1_freq;
587d62e5feeSJonathan Cameron break;
588d62e5feeSJonathan Cameron case SCA3000_REG_MODE_MEAS_MODE_OP_2:
589d62e5feeSJonathan Cameron *base_freq = info->option_mode_2_freq;
590d62e5feeSJonathan Cameron break;
591d62e5feeSJonathan Cameron default:
592d62e5feeSJonathan Cameron ret = -EINVAL;
593d62e5feeSJonathan Cameron }
594d62e5feeSJonathan Cameron error_ret:
595d62e5feeSJonathan Cameron return ret;
596d62e5feeSJonathan Cameron }
597d62e5feeSJonathan Cameron
598d62e5feeSJonathan Cameron /**
599d62e5feeSJonathan Cameron * sca3000_read_raw_samp_freq() - read_raw handler for IIO_CHAN_INFO_SAMP_FREQ
600d62e5feeSJonathan Cameron * @st: Private driver specific device instance specific state.
601d62e5feeSJonathan Cameron * @val: The frequency read back.
602d62e5feeSJonathan Cameron *
603d62e5feeSJonathan Cameron * lock must be held
604d62e5feeSJonathan Cameron **/
sca3000_read_raw_samp_freq(struct sca3000_state * st,int * val)605d62e5feeSJonathan Cameron static int sca3000_read_raw_samp_freq(struct sca3000_state *st, int *val)
606d62e5feeSJonathan Cameron {
607d62e5feeSJonathan Cameron int ret;
608d62e5feeSJonathan Cameron
609d62e5feeSJonathan Cameron ret = __sca3000_get_base_freq(st, st->info, val);
610d62e5feeSJonathan Cameron if (ret)
611d62e5feeSJonathan Cameron return ret;
612d62e5feeSJonathan Cameron
613d62e5feeSJonathan Cameron ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL);
614d62e5feeSJonathan Cameron if (ret < 0)
615d62e5feeSJonathan Cameron return ret;
616d62e5feeSJonathan Cameron
617d62e5feeSJonathan Cameron if (*val > 0) {
618d62e5feeSJonathan Cameron ret &= SCA3000_REG_OUT_CTRL_BUF_DIV_MASK;
619d62e5feeSJonathan Cameron switch (ret) {
620d62e5feeSJonathan Cameron case SCA3000_REG_OUT_CTRL_BUF_DIV_2:
621d62e5feeSJonathan Cameron *val /= 2;
622d62e5feeSJonathan Cameron break;
623d62e5feeSJonathan Cameron case SCA3000_REG_OUT_CTRL_BUF_DIV_4:
624d62e5feeSJonathan Cameron *val /= 4;
625d62e5feeSJonathan Cameron break;
626d62e5feeSJonathan Cameron }
627d62e5feeSJonathan Cameron }
628d62e5feeSJonathan Cameron
629d62e5feeSJonathan Cameron return 0;
630d62e5feeSJonathan Cameron }
631d62e5feeSJonathan Cameron
632d62e5feeSJonathan Cameron /**
633d62e5feeSJonathan Cameron * sca3000_write_raw_samp_freq() - write_raw handler for IIO_CHAN_INFO_SAMP_FREQ
634d62e5feeSJonathan Cameron * @st: Private driver specific device instance specific state.
635d62e5feeSJonathan Cameron * @val: The frequency desired.
636d62e5feeSJonathan Cameron *
637d62e5feeSJonathan Cameron * lock must be held
638d62e5feeSJonathan Cameron */
sca3000_write_raw_samp_freq(struct sca3000_state * st,int val)639d62e5feeSJonathan Cameron static int sca3000_write_raw_samp_freq(struct sca3000_state *st, int val)
640d62e5feeSJonathan Cameron {
641d62e5feeSJonathan Cameron int ret, base_freq, ctrlval;
642d62e5feeSJonathan Cameron
643d62e5feeSJonathan Cameron ret = __sca3000_get_base_freq(st, st->info, &base_freq);
644d62e5feeSJonathan Cameron if (ret)
645d62e5feeSJonathan Cameron return ret;
646d62e5feeSJonathan Cameron
647d62e5feeSJonathan Cameron ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL);
648d62e5feeSJonathan Cameron if (ret < 0)
649d62e5feeSJonathan Cameron return ret;
650d62e5feeSJonathan Cameron
651d62e5feeSJonathan Cameron ctrlval = ret & ~SCA3000_REG_OUT_CTRL_BUF_DIV_MASK;
652d62e5feeSJonathan Cameron
653d62e5feeSJonathan Cameron if (val == base_freq / 2)
654d62e5feeSJonathan Cameron ctrlval |= SCA3000_REG_OUT_CTRL_BUF_DIV_2;
655d62e5feeSJonathan Cameron if (val == base_freq / 4)
656d62e5feeSJonathan Cameron ctrlval |= SCA3000_REG_OUT_CTRL_BUF_DIV_4;
657d62e5feeSJonathan Cameron else if (val != base_freq)
658d62e5feeSJonathan Cameron return -EINVAL;
659d62e5feeSJonathan Cameron
660d62e5feeSJonathan Cameron return sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL,
661d62e5feeSJonathan Cameron ctrlval);
662d62e5feeSJonathan Cameron }
663d62e5feeSJonathan Cameron
sca3000_read_3db_freq(struct sca3000_state * st,int * val)664d62e5feeSJonathan Cameron static int sca3000_read_3db_freq(struct sca3000_state *st, int *val)
665d62e5feeSJonathan Cameron {
666d62e5feeSJonathan Cameron int ret;
667d62e5feeSJonathan Cameron
668d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
669d62e5feeSJonathan Cameron if (ret)
670d62e5feeSJonathan Cameron return ret;
671d62e5feeSJonathan Cameron
672d62e5feeSJonathan Cameron /* mask bottom 2 bits - only ones that are relevant */
673d62e5feeSJonathan Cameron st->rx[0] &= SCA3000_REG_MODE_MODE_MASK;
674d62e5feeSJonathan Cameron switch (st->rx[0]) {
675d62e5feeSJonathan Cameron case SCA3000_REG_MODE_MEAS_MODE_NORMAL:
676d62e5feeSJonathan Cameron *val = st->info->measurement_mode_3db_freq;
677d62e5feeSJonathan Cameron return IIO_VAL_INT;
678d62e5feeSJonathan Cameron case SCA3000_REG_MODE_MEAS_MODE_MOT_DET:
679d62e5feeSJonathan Cameron return -EBUSY;
680d62e5feeSJonathan Cameron case SCA3000_REG_MODE_MEAS_MODE_OP_1:
681d62e5feeSJonathan Cameron *val = st->info->option_mode_1_3db_freq;
682d62e5feeSJonathan Cameron return IIO_VAL_INT;
683d62e5feeSJonathan Cameron case SCA3000_REG_MODE_MEAS_MODE_OP_2:
684d62e5feeSJonathan Cameron *val = st->info->option_mode_2_3db_freq;
685d62e5feeSJonathan Cameron return IIO_VAL_INT;
686d62e5feeSJonathan Cameron default:
687d62e5feeSJonathan Cameron return -EINVAL;
688d62e5feeSJonathan Cameron }
689d62e5feeSJonathan Cameron }
690d62e5feeSJonathan Cameron
sca3000_write_3db_freq(struct sca3000_state * st,int val)691d62e5feeSJonathan Cameron static int sca3000_write_3db_freq(struct sca3000_state *st, int val)
692d62e5feeSJonathan Cameron {
693d62e5feeSJonathan Cameron int ret;
694d62e5feeSJonathan Cameron int mode;
695d62e5feeSJonathan Cameron
696d62e5feeSJonathan Cameron if (val == st->info->measurement_mode_3db_freq)
697d62e5feeSJonathan Cameron mode = SCA3000_REG_MODE_MEAS_MODE_NORMAL;
698d62e5feeSJonathan Cameron else if (st->info->option_mode_1 &&
699d62e5feeSJonathan Cameron (val == st->info->option_mode_1_3db_freq))
700d62e5feeSJonathan Cameron mode = SCA3000_REG_MODE_MEAS_MODE_OP_1;
701d62e5feeSJonathan Cameron else if (st->info->option_mode_2 &&
702d62e5feeSJonathan Cameron (val == st->info->option_mode_2_3db_freq))
703d62e5feeSJonathan Cameron mode = SCA3000_REG_MODE_MEAS_MODE_OP_2;
704d62e5feeSJonathan Cameron else
705d62e5feeSJonathan Cameron return -EINVAL;
706d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
707d62e5feeSJonathan Cameron if (ret)
708d62e5feeSJonathan Cameron return ret;
709d62e5feeSJonathan Cameron
710d62e5feeSJonathan Cameron st->rx[0] &= ~SCA3000_REG_MODE_MODE_MASK;
711d62e5feeSJonathan Cameron st->rx[0] |= (mode & SCA3000_REG_MODE_MODE_MASK);
712d62e5feeSJonathan Cameron
713d62e5feeSJonathan Cameron return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, st->rx[0]);
714d62e5feeSJonathan Cameron }
715d62e5feeSJonathan Cameron
sca3000_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)716d62e5feeSJonathan Cameron static int sca3000_read_raw(struct iio_dev *indio_dev,
717d62e5feeSJonathan Cameron struct iio_chan_spec const *chan,
718d62e5feeSJonathan Cameron int *val,
719d62e5feeSJonathan Cameron int *val2,
720d62e5feeSJonathan Cameron long mask)
721d62e5feeSJonathan Cameron {
722d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev);
723d62e5feeSJonathan Cameron int ret;
724d62e5feeSJonathan Cameron u8 address;
725d62e5feeSJonathan Cameron
726d62e5feeSJonathan Cameron switch (mask) {
727d62e5feeSJonathan Cameron case IIO_CHAN_INFO_RAW:
728d62e5feeSJonathan Cameron mutex_lock(&st->lock);
729d62e5feeSJonathan Cameron if (chan->type == IIO_ACCEL) {
730d62e5feeSJonathan Cameron if (st->mo_det_use_count) {
731d62e5feeSJonathan Cameron mutex_unlock(&st->lock);
732d62e5feeSJonathan Cameron return -EBUSY;
733d62e5feeSJonathan Cameron }
734d62e5feeSJonathan Cameron address = sca3000_addresses[chan->address][0];
735d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, address, 2);
736d62e5feeSJonathan Cameron if (ret < 0) {
737d62e5feeSJonathan Cameron mutex_unlock(&st->lock);
738d62e5feeSJonathan Cameron return ret;
739d62e5feeSJonathan Cameron }
7405405c9b4SGwendal Grignou *val = sign_extend32(be16_to_cpup((__be16 *)st->rx) >>
7415405c9b4SGwendal Grignou chan->scan_type.shift,
7425405c9b4SGwendal Grignou chan->scan_type.realbits - 1);
743d62e5feeSJonathan Cameron } else {
744d62e5feeSJonathan Cameron /* get the temperature when available */
745d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st,
746d62e5feeSJonathan Cameron SCA3000_REG_TEMP_MSB_ADDR,
747d62e5feeSJonathan Cameron 2);
748d62e5feeSJonathan Cameron if (ret < 0) {
749d62e5feeSJonathan Cameron mutex_unlock(&st->lock);
750d62e5feeSJonathan Cameron return ret;
751d62e5feeSJonathan Cameron }
7525405c9b4SGwendal Grignou *val = (be16_to_cpup((__be16 *)st->rx) >>
7535405c9b4SGwendal Grignou chan->scan_type.shift) &
7545405c9b4SGwendal Grignou GENMASK(chan->scan_type.realbits - 1, 0);
755d62e5feeSJonathan Cameron }
756d62e5feeSJonathan Cameron mutex_unlock(&st->lock);
757d62e5feeSJonathan Cameron return IIO_VAL_INT;
758d62e5feeSJonathan Cameron case IIO_CHAN_INFO_SCALE:
759d62e5feeSJonathan Cameron *val = 0;
760d62e5feeSJonathan Cameron if (chan->type == IIO_ACCEL)
761d62e5feeSJonathan Cameron *val2 = st->info->scale;
762d62e5feeSJonathan Cameron else /* temperature */
763d62e5feeSJonathan Cameron *val2 = 555556;
764d62e5feeSJonathan Cameron return IIO_VAL_INT_PLUS_MICRO;
765d62e5feeSJonathan Cameron case IIO_CHAN_INFO_OFFSET:
766d62e5feeSJonathan Cameron *val = -214;
767d62e5feeSJonathan Cameron *val2 = 600000;
768d62e5feeSJonathan Cameron return IIO_VAL_INT_PLUS_MICRO;
769d62e5feeSJonathan Cameron case IIO_CHAN_INFO_SAMP_FREQ:
770d62e5feeSJonathan Cameron mutex_lock(&st->lock);
771d62e5feeSJonathan Cameron ret = sca3000_read_raw_samp_freq(st, val);
772d62e5feeSJonathan Cameron mutex_unlock(&st->lock);
773d62e5feeSJonathan Cameron return ret ? ret : IIO_VAL_INT;
774d62e5feeSJonathan Cameron case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
775d62e5feeSJonathan Cameron mutex_lock(&st->lock);
776d62e5feeSJonathan Cameron ret = sca3000_read_3db_freq(st, val);
777d62e5feeSJonathan Cameron mutex_unlock(&st->lock);
778d62e5feeSJonathan Cameron return ret;
779d62e5feeSJonathan Cameron default:
780d62e5feeSJonathan Cameron return -EINVAL;
781d62e5feeSJonathan Cameron }
782d62e5feeSJonathan Cameron }
783d62e5feeSJonathan Cameron
sca3000_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)784d62e5feeSJonathan Cameron static int sca3000_write_raw(struct iio_dev *indio_dev,
785d62e5feeSJonathan Cameron struct iio_chan_spec const *chan,
786d62e5feeSJonathan Cameron int val, int val2, long mask)
787d62e5feeSJonathan Cameron {
788d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev);
789d62e5feeSJonathan Cameron int ret;
790d62e5feeSJonathan Cameron
791d62e5feeSJonathan Cameron switch (mask) {
792d62e5feeSJonathan Cameron case IIO_CHAN_INFO_SAMP_FREQ:
793d62e5feeSJonathan Cameron if (val2)
794d62e5feeSJonathan Cameron return -EINVAL;
795d62e5feeSJonathan Cameron mutex_lock(&st->lock);
796d62e5feeSJonathan Cameron ret = sca3000_write_raw_samp_freq(st, val);
797d62e5feeSJonathan Cameron mutex_unlock(&st->lock);
798d62e5feeSJonathan Cameron return ret;
799d62e5feeSJonathan Cameron case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
800d62e5feeSJonathan Cameron if (val2)
801d62e5feeSJonathan Cameron return -EINVAL;
802d62e5feeSJonathan Cameron mutex_lock(&st->lock);
803d62e5feeSJonathan Cameron ret = sca3000_write_3db_freq(st, val);
804d62e5feeSJonathan Cameron mutex_unlock(&st->lock);
805c5b974beSGustavo A. R. Silva return ret;
806d62e5feeSJonathan Cameron default:
807d62e5feeSJonathan Cameron return -EINVAL;
808d62e5feeSJonathan Cameron }
809d62e5feeSJonathan Cameron
810d62e5feeSJonathan Cameron return ret;
811d62e5feeSJonathan Cameron }
812d62e5feeSJonathan Cameron
813d62e5feeSJonathan Cameron /**
814d62e5feeSJonathan Cameron * sca3000_read_av_freq() - sysfs function to get available frequencies
815d62e5feeSJonathan Cameron * @dev: Device structure for this device.
816d62e5feeSJonathan Cameron * @attr: Description of the attribute.
817d62e5feeSJonathan Cameron * @buf: Incoming string
818d62e5feeSJonathan Cameron *
819d62e5feeSJonathan Cameron * The later modes are only relevant to the ring buffer - and depend on current
820d62e5feeSJonathan Cameron * mode. Note that data sheet gives rather wide tolerances for these so integer
821d62e5feeSJonathan Cameron * division will give good enough answer and not all chips have them specified
822d62e5feeSJonathan Cameron * at all.
823d62e5feeSJonathan Cameron **/
sca3000_read_av_freq(struct device * dev,struct device_attribute * attr,char * buf)824d62e5feeSJonathan Cameron static ssize_t sca3000_read_av_freq(struct device *dev,
825d62e5feeSJonathan Cameron struct device_attribute *attr,
826d62e5feeSJonathan Cameron char *buf)
827d62e5feeSJonathan Cameron {
828d62e5feeSJonathan Cameron struct iio_dev *indio_dev = dev_to_iio_dev(dev);
829d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev);
830d62e5feeSJonathan Cameron int len = 0, ret, val;
831d62e5feeSJonathan Cameron
832d62e5feeSJonathan Cameron mutex_lock(&st->lock);
833d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
834d62e5feeSJonathan Cameron val = st->rx[0];
835d62e5feeSJonathan Cameron mutex_unlock(&st->lock);
836d62e5feeSJonathan Cameron if (ret)
837d62e5feeSJonathan Cameron goto error_ret;
838d62e5feeSJonathan Cameron
839d62e5feeSJonathan Cameron switch (val & SCA3000_REG_MODE_MODE_MASK) {
840d62e5feeSJonathan Cameron case SCA3000_REG_MODE_MEAS_MODE_NORMAL:
841d62e5feeSJonathan Cameron len += sprintf(buf + len, "%d %d %d\n",
842d62e5feeSJonathan Cameron st->info->measurement_mode_freq,
843d62e5feeSJonathan Cameron st->info->measurement_mode_freq / 2,
844d62e5feeSJonathan Cameron st->info->measurement_mode_freq / 4);
845d62e5feeSJonathan Cameron break;
846d62e5feeSJonathan Cameron case SCA3000_REG_MODE_MEAS_MODE_OP_1:
847d62e5feeSJonathan Cameron len += sprintf(buf + len, "%d %d %d\n",
848d62e5feeSJonathan Cameron st->info->option_mode_1_freq,
849d62e5feeSJonathan Cameron st->info->option_mode_1_freq / 2,
850d62e5feeSJonathan Cameron st->info->option_mode_1_freq / 4);
851d62e5feeSJonathan Cameron break;
852d62e5feeSJonathan Cameron case SCA3000_REG_MODE_MEAS_MODE_OP_2:
853d62e5feeSJonathan Cameron len += sprintf(buf + len, "%d %d %d\n",
854d62e5feeSJonathan Cameron st->info->option_mode_2_freq,
855d62e5feeSJonathan Cameron st->info->option_mode_2_freq / 2,
856d62e5feeSJonathan Cameron st->info->option_mode_2_freq / 4);
857d62e5feeSJonathan Cameron break;
858d62e5feeSJonathan Cameron }
859d62e5feeSJonathan Cameron return len;
860d62e5feeSJonathan Cameron error_ret:
861d62e5feeSJonathan Cameron return ret;
862d62e5feeSJonathan Cameron }
863d62e5feeSJonathan Cameron
864d62e5feeSJonathan Cameron /*
865d62e5feeSJonathan Cameron * Should only really be registered if ring buffer support is compiled in.
866d62e5feeSJonathan Cameron * Does no harm however and doing it right would add a fair bit of complexity
867d62e5feeSJonathan Cameron */
868d62e5feeSJonathan Cameron static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(sca3000_read_av_freq);
869d62e5feeSJonathan Cameron
870fb37b5f8SLee Jones /*
871d62e5feeSJonathan Cameron * sca3000_read_event_value() - query of a threshold or period
872fb37b5f8SLee Jones */
sca3000_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)873d62e5feeSJonathan Cameron static int sca3000_read_event_value(struct iio_dev *indio_dev,
874d62e5feeSJonathan Cameron const struct iio_chan_spec *chan,
875d62e5feeSJonathan Cameron enum iio_event_type type,
876d62e5feeSJonathan Cameron enum iio_event_direction dir,
877d62e5feeSJonathan Cameron enum iio_event_info info,
878d62e5feeSJonathan Cameron int *val, int *val2)
879d62e5feeSJonathan Cameron {
880d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev);
881aabcbfe8SDan Carpenter long ret;
882aabcbfe8SDan Carpenter int i;
883d62e5feeSJonathan Cameron
884d62e5feeSJonathan Cameron switch (info) {
885d62e5feeSJonathan Cameron case IIO_EV_INFO_VALUE:
886d62e5feeSJonathan Cameron mutex_lock(&st->lock);
887d62e5feeSJonathan Cameron ret = sca3000_read_ctrl_reg(st,
888d62e5feeSJonathan Cameron sca3000_addresses[chan->address][1]);
889d62e5feeSJonathan Cameron mutex_unlock(&st->lock);
890d62e5feeSJonathan Cameron if (ret < 0)
891d62e5feeSJonathan Cameron return ret;
892d62e5feeSJonathan Cameron *val = 0;
893d62e5feeSJonathan Cameron if (chan->channel2 == IIO_MOD_Y)
894aabcbfe8SDan Carpenter for_each_set_bit(i, &ret,
895d62e5feeSJonathan Cameron ARRAY_SIZE(st->info->mot_det_mult_y))
896d62e5feeSJonathan Cameron *val += st->info->mot_det_mult_y[i];
897d62e5feeSJonathan Cameron else
898aabcbfe8SDan Carpenter for_each_set_bit(i, &ret,
899d62e5feeSJonathan Cameron ARRAY_SIZE(st->info->mot_det_mult_xz))
900d62e5feeSJonathan Cameron *val += st->info->mot_det_mult_xz[i];
901d62e5feeSJonathan Cameron
902d62e5feeSJonathan Cameron return IIO_VAL_INT;
903d62e5feeSJonathan Cameron case IIO_EV_INFO_PERIOD:
904d62e5feeSJonathan Cameron *val = 0;
905d62e5feeSJonathan Cameron *val2 = 226000;
906d62e5feeSJonathan Cameron return IIO_VAL_INT_PLUS_MICRO;
907d62e5feeSJonathan Cameron default:
908d62e5feeSJonathan Cameron return -EINVAL;
909d62e5feeSJonathan Cameron }
910d62e5feeSJonathan Cameron }
911d62e5feeSJonathan Cameron
912d62e5feeSJonathan Cameron /**
913d7f1c0c3SJonathan Cameron * sca3000_write_event_value() - control of threshold and period
914d62e5feeSJonathan Cameron * @indio_dev: Device instance specific IIO information.
915d62e5feeSJonathan Cameron * @chan: Description of the channel for which the event is being
916d62e5feeSJonathan Cameron * configured.
917d62e5feeSJonathan Cameron * @type: The type of event being configured, here magnitude rising
918d62e5feeSJonathan Cameron * as everything else is read only.
919d62e5feeSJonathan Cameron * @dir: Direction of the event (here rising)
920d62e5feeSJonathan Cameron * @info: What information about the event are we configuring.
921d62e5feeSJonathan Cameron * Here the threshold only.
922d62e5feeSJonathan Cameron * @val: Integer part of the value being written..
923d62e5feeSJonathan Cameron * @val2: Non integer part of the value being written. Here always 0.
924d62e5feeSJonathan Cameron */
sca3000_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)925d62e5feeSJonathan Cameron static int sca3000_write_event_value(struct iio_dev *indio_dev,
926d62e5feeSJonathan Cameron const struct iio_chan_spec *chan,
927d62e5feeSJonathan Cameron enum iio_event_type type,
928d62e5feeSJonathan Cameron enum iio_event_direction dir,
929d62e5feeSJonathan Cameron enum iio_event_info info,
930d62e5feeSJonathan Cameron int val, int val2)
931d62e5feeSJonathan Cameron {
932d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev);
933d62e5feeSJonathan Cameron int ret;
934d62e5feeSJonathan Cameron int i;
935d62e5feeSJonathan Cameron u8 nonlinear = 0;
936d62e5feeSJonathan Cameron
937d62e5feeSJonathan Cameron if (chan->channel2 == IIO_MOD_Y) {
938d62e5feeSJonathan Cameron i = ARRAY_SIZE(st->info->mot_det_mult_y);
939d62e5feeSJonathan Cameron while (i > 0)
940d62e5feeSJonathan Cameron if (val >= st->info->mot_det_mult_y[--i]) {
941d62e5feeSJonathan Cameron nonlinear |= (1 << i);
942d62e5feeSJonathan Cameron val -= st->info->mot_det_mult_y[i];
943d62e5feeSJonathan Cameron }
944d62e5feeSJonathan Cameron } else {
945d62e5feeSJonathan Cameron i = ARRAY_SIZE(st->info->mot_det_mult_xz);
946d62e5feeSJonathan Cameron while (i > 0)
947d62e5feeSJonathan Cameron if (val >= st->info->mot_det_mult_xz[--i]) {
948d62e5feeSJonathan Cameron nonlinear |= (1 << i);
949d62e5feeSJonathan Cameron val -= st->info->mot_det_mult_xz[i];
950d62e5feeSJonathan Cameron }
951d62e5feeSJonathan Cameron }
952d62e5feeSJonathan Cameron
953d62e5feeSJonathan Cameron mutex_lock(&st->lock);
954d62e5feeSJonathan Cameron ret = sca3000_write_ctrl_reg(st,
955d62e5feeSJonathan Cameron sca3000_addresses[chan->address][1],
956d62e5feeSJonathan Cameron nonlinear);
957d62e5feeSJonathan Cameron mutex_unlock(&st->lock);
958d62e5feeSJonathan Cameron
959d62e5feeSJonathan Cameron return ret;
960d62e5feeSJonathan Cameron }
961d62e5feeSJonathan Cameron
962d62e5feeSJonathan Cameron static struct attribute *sca3000_attributes[] = {
963d62e5feeSJonathan Cameron &iio_dev_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr,
964d62e5feeSJonathan Cameron &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
965d62e5feeSJonathan Cameron NULL,
966d62e5feeSJonathan Cameron };
967d62e5feeSJonathan Cameron
968d62e5feeSJonathan Cameron static const struct attribute_group sca3000_attribute_group = {
969d62e5feeSJonathan Cameron .attrs = sca3000_attributes,
970d62e5feeSJonathan Cameron };
971d62e5feeSJonathan Cameron
sca3000_read_data(struct sca3000_state * st,u8 reg_address_high,u8 * rx,int len)972d62e5feeSJonathan Cameron static int sca3000_read_data(struct sca3000_state *st,
973d62e5feeSJonathan Cameron u8 reg_address_high,
974d62e5feeSJonathan Cameron u8 *rx,
975d62e5feeSJonathan Cameron int len)
976d62e5feeSJonathan Cameron {
977d62e5feeSJonathan Cameron int ret;
978d62e5feeSJonathan Cameron struct spi_transfer xfer[2] = {
979d62e5feeSJonathan Cameron {
980d62e5feeSJonathan Cameron .len = 1,
981d62e5feeSJonathan Cameron .tx_buf = st->tx,
982d62e5feeSJonathan Cameron }, {
983d62e5feeSJonathan Cameron .len = len,
984d62e5feeSJonathan Cameron .rx_buf = rx,
985d62e5feeSJonathan Cameron }
986d62e5feeSJonathan Cameron };
987d62e5feeSJonathan Cameron
988d62e5feeSJonathan Cameron st->tx[0] = SCA3000_READ_REG(reg_address_high);
989d62e5feeSJonathan Cameron ret = spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer));
990d62e5feeSJonathan Cameron if (ret) {
991928edefbSChristophe JAILLET dev_err(&st->us->dev, "problem reading register\n");
992d62e5feeSJonathan Cameron return ret;
993d62e5feeSJonathan Cameron }
994d62e5feeSJonathan Cameron
995d62e5feeSJonathan Cameron return 0;
996d62e5feeSJonathan Cameron }
997d62e5feeSJonathan Cameron
998d62e5feeSJonathan Cameron /**
999d62e5feeSJonathan Cameron * sca3000_ring_int_process() - ring specific interrupt handling.
1000d62e5feeSJonathan Cameron * @val: Value of the interrupt status register.
1001d62e5feeSJonathan Cameron * @indio_dev: Device instance specific IIO device structure.
1002d62e5feeSJonathan Cameron */
sca3000_ring_int_process(u8 val,struct iio_dev * indio_dev)1003d62e5feeSJonathan Cameron static void sca3000_ring_int_process(u8 val, struct iio_dev *indio_dev)
1004d62e5feeSJonathan Cameron {
1005d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev);
1006d62e5feeSJonathan Cameron int ret, i, num_available;
1007d62e5feeSJonathan Cameron
1008d62e5feeSJonathan Cameron mutex_lock(&st->lock);
1009d62e5feeSJonathan Cameron
1010d62e5feeSJonathan Cameron if (val & SCA3000_REG_INT_STATUS_HALF) {
1011d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_BUF_COUNT_ADDR,
1012d62e5feeSJonathan Cameron 1);
1013d62e5feeSJonathan Cameron if (ret)
1014d62e5feeSJonathan Cameron goto error_ret;
1015d62e5feeSJonathan Cameron num_available = st->rx[0];
1016d62e5feeSJonathan Cameron /*
1017d62e5feeSJonathan Cameron * num_available is the total number of samples available
1018d62e5feeSJonathan Cameron * i.e. number of time points * number of channels.
1019d62e5feeSJonathan Cameron */
1020d62e5feeSJonathan Cameron ret = sca3000_read_data(st, SCA3000_REG_RING_OUT_ADDR, st->rx,
1021d62e5feeSJonathan Cameron num_available * 2);
1022d62e5feeSJonathan Cameron if (ret)
1023d62e5feeSJonathan Cameron goto error_ret;
1024d62e5feeSJonathan Cameron for (i = 0; i < num_available / 3; i++) {
1025d62e5feeSJonathan Cameron /*
1026d62e5feeSJonathan Cameron * Dirty hack to cover for 11 bit in fifo, 13 bit
1027d62e5feeSJonathan Cameron * direct reading.
1028d62e5feeSJonathan Cameron *
1029d62e5feeSJonathan Cameron * In theory the bottom two bits are undefined.
1030d62e5feeSJonathan Cameron * In reality they appear to always be 0.
1031d62e5feeSJonathan Cameron */
1032d62e5feeSJonathan Cameron iio_push_to_buffers(indio_dev, st->rx + i * 3 * 2);
1033d62e5feeSJonathan Cameron }
1034d62e5feeSJonathan Cameron }
1035d62e5feeSJonathan Cameron error_ret:
1036d62e5feeSJonathan Cameron mutex_unlock(&st->lock);
1037d62e5feeSJonathan Cameron }
1038d62e5feeSJonathan Cameron
1039d62e5feeSJonathan Cameron /**
1040d62e5feeSJonathan Cameron * sca3000_event_handler() - handling ring and non ring events
1041d62e5feeSJonathan Cameron * @irq: The irq being handled.
1042d62e5feeSJonathan Cameron * @private: struct iio_device pointer for the device.
1043d62e5feeSJonathan Cameron *
1044d62e5feeSJonathan Cameron * Ring related interrupt handler. Depending on event, push to
1045d62e5feeSJonathan Cameron * the ring buffer event chrdev or the event one.
1046d62e5feeSJonathan Cameron *
1047d62e5feeSJonathan Cameron * This function is complicated by the fact that the devices can signify ring
1048d62e5feeSJonathan Cameron * and non ring events via the same interrupt line and they can only
1049d62e5feeSJonathan Cameron * be distinguished via a read of the relevant status register.
1050d62e5feeSJonathan Cameron */
sca3000_event_handler(int irq,void * private)1051d62e5feeSJonathan Cameron static irqreturn_t sca3000_event_handler(int irq, void *private)
1052d62e5feeSJonathan Cameron {
1053d62e5feeSJonathan Cameron struct iio_dev *indio_dev = private;
1054d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev);
1055d62e5feeSJonathan Cameron int ret, val;
1056d62e5feeSJonathan Cameron s64 last_timestamp = iio_get_time_ns(indio_dev);
1057d62e5feeSJonathan Cameron
1058d62e5feeSJonathan Cameron /*
1059d62e5feeSJonathan Cameron * Could lead if badly timed to an extra read of status reg,
1060d62e5feeSJonathan Cameron * but ensures no interrupt is missed.
1061d62e5feeSJonathan Cameron */
1062d62e5feeSJonathan Cameron mutex_lock(&st->lock);
1063d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_INT_STATUS_ADDR, 1);
1064d62e5feeSJonathan Cameron val = st->rx[0];
1065d62e5feeSJonathan Cameron mutex_unlock(&st->lock);
1066d62e5feeSJonathan Cameron if (ret)
1067d62e5feeSJonathan Cameron goto done;
1068d62e5feeSJonathan Cameron
1069d62e5feeSJonathan Cameron sca3000_ring_int_process(val, indio_dev);
1070d62e5feeSJonathan Cameron
1071d62e5feeSJonathan Cameron if (val & SCA3000_INT_STATUS_FREE_FALL)
1072d62e5feeSJonathan Cameron iio_push_event(indio_dev,
1073d62e5feeSJonathan Cameron IIO_MOD_EVENT_CODE(IIO_ACCEL,
1074d62e5feeSJonathan Cameron 0,
1075d62e5feeSJonathan Cameron IIO_MOD_X_AND_Y_AND_Z,
1076d62e5feeSJonathan Cameron IIO_EV_TYPE_MAG,
1077d62e5feeSJonathan Cameron IIO_EV_DIR_FALLING),
1078d62e5feeSJonathan Cameron last_timestamp);
1079d62e5feeSJonathan Cameron
1080d62e5feeSJonathan Cameron if (val & SCA3000_INT_STATUS_Y_TRIGGER)
1081d62e5feeSJonathan Cameron iio_push_event(indio_dev,
1082d62e5feeSJonathan Cameron IIO_MOD_EVENT_CODE(IIO_ACCEL,
1083d62e5feeSJonathan Cameron 0,
1084d62e5feeSJonathan Cameron IIO_MOD_Y,
1085d62e5feeSJonathan Cameron IIO_EV_TYPE_MAG,
1086d62e5feeSJonathan Cameron IIO_EV_DIR_RISING),
1087d62e5feeSJonathan Cameron last_timestamp);
1088d62e5feeSJonathan Cameron
1089d62e5feeSJonathan Cameron if (val & SCA3000_INT_STATUS_X_TRIGGER)
1090d62e5feeSJonathan Cameron iio_push_event(indio_dev,
1091d62e5feeSJonathan Cameron IIO_MOD_EVENT_CODE(IIO_ACCEL,
1092d62e5feeSJonathan Cameron 0,
1093d62e5feeSJonathan Cameron IIO_MOD_X,
1094d62e5feeSJonathan Cameron IIO_EV_TYPE_MAG,
1095d62e5feeSJonathan Cameron IIO_EV_DIR_RISING),
1096d62e5feeSJonathan Cameron last_timestamp);
1097d62e5feeSJonathan Cameron
1098d62e5feeSJonathan Cameron if (val & SCA3000_INT_STATUS_Z_TRIGGER)
1099d62e5feeSJonathan Cameron iio_push_event(indio_dev,
1100d62e5feeSJonathan Cameron IIO_MOD_EVENT_CODE(IIO_ACCEL,
1101d62e5feeSJonathan Cameron 0,
1102d62e5feeSJonathan Cameron IIO_MOD_Z,
1103d62e5feeSJonathan Cameron IIO_EV_TYPE_MAG,
1104d62e5feeSJonathan Cameron IIO_EV_DIR_RISING),
1105d62e5feeSJonathan Cameron last_timestamp);
1106d62e5feeSJonathan Cameron
1107d62e5feeSJonathan Cameron done:
1108d62e5feeSJonathan Cameron return IRQ_HANDLED;
1109d62e5feeSJonathan Cameron }
1110d62e5feeSJonathan Cameron
1111fb37b5f8SLee Jones /*
1112d62e5feeSJonathan Cameron * sca3000_read_event_config() what events are enabled
1113fb37b5f8SLee Jones */
sca3000_read_event_config(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum iio_event_type type,enum iio_event_direction dir)1114d62e5feeSJonathan Cameron static int sca3000_read_event_config(struct iio_dev *indio_dev,
1115d62e5feeSJonathan Cameron const struct iio_chan_spec *chan,
1116d62e5feeSJonathan Cameron enum iio_event_type type,
1117d62e5feeSJonathan Cameron enum iio_event_direction dir)
1118d62e5feeSJonathan Cameron {
1119d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev);
1120d62e5feeSJonathan Cameron int ret;
1121d62e5feeSJonathan Cameron /* read current value of mode register */
1122d62e5feeSJonathan Cameron mutex_lock(&st->lock);
1123d62e5feeSJonathan Cameron
1124d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
1125d62e5feeSJonathan Cameron if (ret)
1126d62e5feeSJonathan Cameron goto error_ret;
1127d62e5feeSJonathan Cameron
1128d62e5feeSJonathan Cameron switch (chan->channel2) {
1129d62e5feeSJonathan Cameron case IIO_MOD_X_AND_Y_AND_Z:
1130d62e5feeSJonathan Cameron ret = !!(st->rx[0] & SCA3000_REG_MODE_FREE_FALL_DETECT);
1131d62e5feeSJonathan Cameron break;
1132d62e5feeSJonathan Cameron case IIO_MOD_X:
1133d62e5feeSJonathan Cameron case IIO_MOD_Y:
1134d62e5feeSJonathan Cameron case IIO_MOD_Z:
1135d62e5feeSJonathan Cameron /*
1136d62e5feeSJonathan Cameron * Motion detection mode cannot run at the same time as
1137d62e5feeSJonathan Cameron * acceleration data being read.
1138d62e5feeSJonathan Cameron */
1139d62e5feeSJonathan Cameron if ((st->rx[0] & SCA3000_REG_MODE_MODE_MASK)
1140d62e5feeSJonathan Cameron != SCA3000_REG_MODE_MEAS_MODE_MOT_DET) {
1141d62e5feeSJonathan Cameron ret = 0;
1142d62e5feeSJonathan Cameron } else {
1143d62e5feeSJonathan Cameron ret = sca3000_read_ctrl_reg(st,
1144d62e5feeSJonathan Cameron SCA3000_REG_CTRL_SEL_MD_CTRL);
1145d62e5feeSJonathan Cameron if (ret < 0)
1146d62e5feeSJonathan Cameron goto error_ret;
1147d62e5feeSJonathan Cameron /* only supporting logical or's for now */
1148d62e5feeSJonathan Cameron ret = !!(ret & sca3000_addresses[chan->address][2]);
1149d62e5feeSJonathan Cameron }
1150d62e5feeSJonathan Cameron break;
1151d62e5feeSJonathan Cameron default:
1152d62e5feeSJonathan Cameron ret = -EINVAL;
1153d62e5feeSJonathan Cameron }
1154d62e5feeSJonathan Cameron
1155d62e5feeSJonathan Cameron error_ret:
1156d62e5feeSJonathan Cameron mutex_unlock(&st->lock);
1157d62e5feeSJonathan Cameron
1158d62e5feeSJonathan Cameron return ret;
1159d62e5feeSJonathan Cameron }
1160d62e5feeSJonathan Cameron
sca3000_freefall_set_state(struct iio_dev * indio_dev,int state)1161d62e5feeSJonathan Cameron static int sca3000_freefall_set_state(struct iio_dev *indio_dev, int state)
1162d62e5feeSJonathan Cameron {
1163d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev);
1164d62e5feeSJonathan Cameron int ret;
1165d62e5feeSJonathan Cameron
1166d62e5feeSJonathan Cameron /* read current value of mode register */
1167d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
1168d62e5feeSJonathan Cameron if (ret)
1169d62e5feeSJonathan Cameron return ret;
1170d62e5feeSJonathan Cameron
1171d62e5feeSJonathan Cameron /* if off and should be on */
1172d62e5feeSJonathan Cameron if (state && !(st->rx[0] & SCA3000_REG_MODE_FREE_FALL_DETECT))
1173d62e5feeSJonathan Cameron return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR,
1174d62e5feeSJonathan Cameron st->rx[0] | SCA3000_REG_MODE_FREE_FALL_DETECT);
1175d62e5feeSJonathan Cameron /* if on and should be off */
1176d62e5feeSJonathan Cameron else if (!state && (st->rx[0] & SCA3000_REG_MODE_FREE_FALL_DETECT))
1177d62e5feeSJonathan Cameron return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR,
1178d62e5feeSJonathan Cameron st->rx[0] & ~SCA3000_REG_MODE_FREE_FALL_DETECT);
1179d62e5feeSJonathan Cameron else
1180d62e5feeSJonathan Cameron return 0;
1181d62e5feeSJonathan Cameron }
1182d62e5feeSJonathan Cameron
sca3000_motion_detect_set_state(struct iio_dev * indio_dev,int axis,int state)1183d62e5feeSJonathan Cameron static int sca3000_motion_detect_set_state(struct iio_dev *indio_dev, int axis,
1184d62e5feeSJonathan Cameron int state)
1185d62e5feeSJonathan Cameron {
1186d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev);
1187d62e5feeSJonathan Cameron int ret, ctrlval;
1188d62e5feeSJonathan Cameron
1189d62e5feeSJonathan Cameron /*
1190d62e5feeSJonathan Cameron * First read the motion detector config to find out if
1191d62e5feeSJonathan Cameron * this axis is on
1192d62e5feeSJonathan Cameron */
1193d62e5feeSJonathan Cameron ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL);
1194d62e5feeSJonathan Cameron if (ret < 0)
1195d62e5feeSJonathan Cameron return ret;
1196d62e5feeSJonathan Cameron ctrlval = ret;
1197d62e5feeSJonathan Cameron /* if off and should be on */
1198d62e5feeSJonathan Cameron if (state && !(ctrlval & sca3000_addresses[axis][2])) {
1199d62e5feeSJonathan Cameron ret = sca3000_write_ctrl_reg(st,
1200d62e5feeSJonathan Cameron SCA3000_REG_CTRL_SEL_MD_CTRL,
1201d62e5feeSJonathan Cameron ctrlval |
1202d62e5feeSJonathan Cameron sca3000_addresses[axis][2]);
1203d62e5feeSJonathan Cameron if (ret)
1204d62e5feeSJonathan Cameron return ret;
1205d62e5feeSJonathan Cameron st->mo_det_use_count++;
1206d62e5feeSJonathan Cameron } else if (!state && (ctrlval & sca3000_addresses[axis][2])) {
1207d62e5feeSJonathan Cameron ret = sca3000_write_ctrl_reg(st,
1208d62e5feeSJonathan Cameron SCA3000_REG_CTRL_SEL_MD_CTRL,
1209d62e5feeSJonathan Cameron ctrlval &
1210d62e5feeSJonathan Cameron ~(sca3000_addresses[axis][2]));
1211d62e5feeSJonathan Cameron if (ret)
1212d62e5feeSJonathan Cameron return ret;
1213d62e5feeSJonathan Cameron st->mo_det_use_count--;
1214d62e5feeSJonathan Cameron }
1215d62e5feeSJonathan Cameron
1216d62e5feeSJonathan Cameron /* read current value of mode register */
1217d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
1218d62e5feeSJonathan Cameron if (ret)
1219d62e5feeSJonathan Cameron return ret;
1220d62e5feeSJonathan Cameron /* if off and should be on */
1221d62e5feeSJonathan Cameron if ((st->mo_det_use_count) &&
1222d62e5feeSJonathan Cameron ((st->rx[0] & SCA3000_REG_MODE_MODE_MASK)
1223d62e5feeSJonathan Cameron != SCA3000_REG_MODE_MEAS_MODE_MOT_DET))
1224d62e5feeSJonathan Cameron return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR,
1225d62e5feeSJonathan Cameron (st->rx[0] & ~SCA3000_REG_MODE_MODE_MASK)
1226d62e5feeSJonathan Cameron | SCA3000_REG_MODE_MEAS_MODE_MOT_DET);
1227d62e5feeSJonathan Cameron /* if on and should be off */
1228d62e5feeSJonathan Cameron else if (!(st->mo_det_use_count) &&
1229d62e5feeSJonathan Cameron ((st->rx[0] & SCA3000_REG_MODE_MODE_MASK)
1230d62e5feeSJonathan Cameron == SCA3000_REG_MODE_MEAS_MODE_MOT_DET))
1231d62e5feeSJonathan Cameron return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR,
1232d62e5feeSJonathan Cameron st->rx[0] & SCA3000_REG_MODE_MODE_MASK);
1233d62e5feeSJonathan Cameron else
1234d62e5feeSJonathan Cameron return 0;
1235d62e5feeSJonathan Cameron }
1236d62e5feeSJonathan Cameron
1237d62e5feeSJonathan Cameron /**
1238d62e5feeSJonathan Cameron * sca3000_write_event_config() - simple on off control for motion detector
1239d62e5feeSJonathan Cameron * @indio_dev: IIO device instance specific structure. Data specific to this
1240d62e5feeSJonathan Cameron * particular driver may be accessed via iio_priv(indio_dev).
1241d62e5feeSJonathan Cameron * @chan: Description of the channel whose event we are configuring.
1242d62e5feeSJonathan Cameron * @type: The type of event.
1243d62e5feeSJonathan Cameron * @dir: The direction of the event.
1244d62e5feeSJonathan Cameron * @state: Desired state of event being configured.
1245d62e5feeSJonathan Cameron *
1246d62e5feeSJonathan Cameron * This is a per axis control, but enabling any will result in the
1247d62e5feeSJonathan Cameron * motion detector unit being enabled.
1248d62e5feeSJonathan Cameron * N.B. enabling motion detector stops normal data acquisition.
1249d62e5feeSJonathan Cameron * There is a complexity in knowing which mode to return to when
1250d62e5feeSJonathan Cameron * this mode is disabled. Currently normal mode is assumed.
1251d62e5feeSJonathan Cameron **/
sca3000_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)1252d62e5feeSJonathan Cameron static int sca3000_write_event_config(struct iio_dev *indio_dev,
1253d62e5feeSJonathan Cameron const struct iio_chan_spec *chan,
1254d62e5feeSJonathan Cameron enum iio_event_type type,
1255d62e5feeSJonathan Cameron enum iio_event_direction dir,
1256d62e5feeSJonathan Cameron int state)
1257d62e5feeSJonathan Cameron {
1258d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev);
1259d62e5feeSJonathan Cameron int ret;
1260d62e5feeSJonathan Cameron
1261d62e5feeSJonathan Cameron mutex_lock(&st->lock);
1262d62e5feeSJonathan Cameron switch (chan->channel2) {
1263d62e5feeSJonathan Cameron case IIO_MOD_X_AND_Y_AND_Z:
1264d62e5feeSJonathan Cameron ret = sca3000_freefall_set_state(indio_dev, state);
1265d62e5feeSJonathan Cameron break;
1266d62e5feeSJonathan Cameron
1267d62e5feeSJonathan Cameron case IIO_MOD_X:
1268d62e5feeSJonathan Cameron case IIO_MOD_Y:
1269d62e5feeSJonathan Cameron case IIO_MOD_Z:
1270d62e5feeSJonathan Cameron ret = sca3000_motion_detect_set_state(indio_dev,
1271d62e5feeSJonathan Cameron chan->address,
1272d62e5feeSJonathan Cameron state);
1273d62e5feeSJonathan Cameron break;
1274d62e5feeSJonathan Cameron default:
1275d62e5feeSJonathan Cameron ret = -EINVAL;
1276d62e5feeSJonathan Cameron break;
1277d62e5feeSJonathan Cameron }
1278d62e5feeSJonathan Cameron mutex_unlock(&st->lock);
1279d62e5feeSJonathan Cameron
1280d62e5feeSJonathan Cameron return ret;
1281d62e5feeSJonathan Cameron }
1282d62e5feeSJonathan Cameron
1283d62e5feeSJonathan Cameron static inline
__sca3000_hw_ring_state_set(struct iio_dev * indio_dev,bool state)1284d62e5feeSJonathan Cameron int __sca3000_hw_ring_state_set(struct iio_dev *indio_dev, bool state)
1285d62e5feeSJonathan Cameron {
1286d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev);
1287d62e5feeSJonathan Cameron int ret;
1288d62e5feeSJonathan Cameron
1289d62e5feeSJonathan Cameron mutex_lock(&st->lock);
1290d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
1291d62e5feeSJonathan Cameron if (ret)
1292d62e5feeSJonathan Cameron goto error_ret;
1293d62e5feeSJonathan Cameron if (state) {
1294d62e5feeSJonathan Cameron dev_info(&indio_dev->dev, "supposedly enabling ring buffer\n");
1295d62e5feeSJonathan Cameron ret = sca3000_write_reg(st,
1296d62e5feeSJonathan Cameron SCA3000_REG_MODE_ADDR,
1297d62e5feeSJonathan Cameron (st->rx[0] | SCA3000_REG_MODE_RING_BUF_ENABLE));
1298d62e5feeSJonathan Cameron } else
1299d62e5feeSJonathan Cameron ret = sca3000_write_reg(st,
1300d62e5feeSJonathan Cameron SCA3000_REG_MODE_ADDR,
1301d62e5feeSJonathan Cameron (st->rx[0] & ~SCA3000_REG_MODE_RING_BUF_ENABLE));
1302d62e5feeSJonathan Cameron error_ret:
1303d62e5feeSJonathan Cameron mutex_unlock(&st->lock);
1304d62e5feeSJonathan Cameron
1305d62e5feeSJonathan Cameron return ret;
1306d62e5feeSJonathan Cameron }
1307d62e5feeSJonathan Cameron
1308d62e5feeSJonathan Cameron /**
1309d62e5feeSJonathan Cameron * sca3000_hw_ring_preenable() - hw ring buffer preenable function
1310d62e5feeSJonathan Cameron * @indio_dev: structure representing the IIO device. Device instance
1311d62e5feeSJonathan Cameron * specific state can be accessed via iio_priv(indio_dev).
1312d62e5feeSJonathan Cameron *
1313d62e5feeSJonathan Cameron * Very simple enable function as the chip will allows normal reads
1314d62e5feeSJonathan Cameron * during ring buffer operation so as long as it is indeed running
1315d62e5feeSJonathan Cameron * before we notify the core, the precise ordering does not matter.
1316d62e5feeSJonathan Cameron */
sca3000_hw_ring_preenable(struct iio_dev * indio_dev)1317d62e5feeSJonathan Cameron static int sca3000_hw_ring_preenable(struct iio_dev *indio_dev)
1318d62e5feeSJonathan Cameron {
1319d62e5feeSJonathan Cameron int ret;
1320d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev);
1321d62e5feeSJonathan Cameron
1322d62e5feeSJonathan Cameron mutex_lock(&st->lock);
1323d62e5feeSJonathan Cameron
1324d62e5feeSJonathan Cameron /* Enable the 50% full interrupt */
1325d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1);
1326d62e5feeSJonathan Cameron if (ret)
1327d62e5feeSJonathan Cameron goto error_unlock;
1328d62e5feeSJonathan Cameron ret = sca3000_write_reg(st,
1329d62e5feeSJonathan Cameron SCA3000_REG_INT_MASK_ADDR,
1330d62e5feeSJonathan Cameron st->rx[0] | SCA3000_REG_INT_MASK_RING_HALF);
1331d62e5feeSJonathan Cameron if (ret)
1332d62e5feeSJonathan Cameron goto error_unlock;
1333d62e5feeSJonathan Cameron
1334d62e5feeSJonathan Cameron mutex_unlock(&st->lock);
1335d62e5feeSJonathan Cameron
1336d62e5feeSJonathan Cameron return __sca3000_hw_ring_state_set(indio_dev, 1);
1337d62e5feeSJonathan Cameron
1338d62e5feeSJonathan Cameron error_unlock:
1339d62e5feeSJonathan Cameron mutex_unlock(&st->lock);
1340d62e5feeSJonathan Cameron
1341d62e5feeSJonathan Cameron return ret;
1342d62e5feeSJonathan Cameron }
1343d62e5feeSJonathan Cameron
sca3000_hw_ring_postdisable(struct iio_dev * indio_dev)1344d62e5feeSJonathan Cameron static int sca3000_hw_ring_postdisable(struct iio_dev *indio_dev)
1345d62e5feeSJonathan Cameron {
1346d62e5feeSJonathan Cameron int ret;
1347d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev);
1348d62e5feeSJonathan Cameron
1349d62e5feeSJonathan Cameron ret = __sca3000_hw_ring_state_set(indio_dev, 0);
1350d62e5feeSJonathan Cameron if (ret)
1351d62e5feeSJonathan Cameron return ret;
1352d62e5feeSJonathan Cameron
1353d62e5feeSJonathan Cameron /* Disable the 50% full interrupt */
1354d62e5feeSJonathan Cameron mutex_lock(&st->lock);
1355d62e5feeSJonathan Cameron
1356d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1);
1357d62e5feeSJonathan Cameron if (ret)
1358d62e5feeSJonathan Cameron goto unlock;
1359d62e5feeSJonathan Cameron ret = sca3000_write_reg(st,
1360d62e5feeSJonathan Cameron SCA3000_REG_INT_MASK_ADDR,
1361d62e5feeSJonathan Cameron st->rx[0] & ~SCA3000_REG_INT_MASK_RING_HALF);
1362d62e5feeSJonathan Cameron unlock:
1363d62e5feeSJonathan Cameron mutex_unlock(&st->lock);
1364d62e5feeSJonathan Cameron return ret;
1365d62e5feeSJonathan Cameron }
1366d62e5feeSJonathan Cameron
1367d62e5feeSJonathan Cameron static const struct iio_buffer_setup_ops sca3000_ring_setup_ops = {
1368d62e5feeSJonathan Cameron .preenable = &sca3000_hw_ring_preenable,
1369d62e5feeSJonathan Cameron .postdisable = &sca3000_hw_ring_postdisable,
1370d62e5feeSJonathan Cameron };
1371d62e5feeSJonathan Cameron
1372d62e5feeSJonathan Cameron /**
1373d62e5feeSJonathan Cameron * sca3000_clean_setup() - get the device into a predictable state
1374d62e5feeSJonathan Cameron * @st: Device instance specific private data structure
1375d62e5feeSJonathan Cameron *
1376d62e5feeSJonathan Cameron * Devices use flash memory to store many of the register values
1377d62e5feeSJonathan Cameron * and hence can come up in somewhat unpredictable states.
1378d62e5feeSJonathan Cameron * Hence reset everything on driver load.
1379d62e5feeSJonathan Cameron */
sca3000_clean_setup(struct sca3000_state * st)1380d62e5feeSJonathan Cameron static int sca3000_clean_setup(struct sca3000_state *st)
1381d62e5feeSJonathan Cameron {
1382d62e5feeSJonathan Cameron int ret;
1383d62e5feeSJonathan Cameron
1384d62e5feeSJonathan Cameron mutex_lock(&st->lock);
1385d62e5feeSJonathan Cameron /* Ensure all interrupts have been acknowledged */
1386d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_INT_STATUS_ADDR, 1);
1387d62e5feeSJonathan Cameron if (ret)
1388d62e5feeSJonathan Cameron goto error_ret;
1389d62e5feeSJonathan Cameron
1390d62e5feeSJonathan Cameron /* Turn off all motion detection channels */
1391d62e5feeSJonathan Cameron ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL);
1392d62e5feeSJonathan Cameron if (ret < 0)
1393d62e5feeSJonathan Cameron goto error_ret;
1394d62e5feeSJonathan Cameron ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL,
1395d62e5feeSJonathan Cameron ret & SCA3000_MD_CTRL_PROT_MASK);
1396d62e5feeSJonathan Cameron if (ret)
1397d62e5feeSJonathan Cameron goto error_ret;
1398d62e5feeSJonathan Cameron
1399d62e5feeSJonathan Cameron /* Disable ring buffer */
1400d62e5feeSJonathan Cameron ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL);
1401d62e5feeSJonathan Cameron if (ret < 0)
1402d62e5feeSJonathan Cameron goto error_ret;
1403d62e5feeSJonathan Cameron ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL,
1404d62e5feeSJonathan Cameron (ret & SCA3000_REG_OUT_CTRL_PROT_MASK)
1405d62e5feeSJonathan Cameron | SCA3000_REG_OUT_CTRL_BUF_X_EN
1406d62e5feeSJonathan Cameron | SCA3000_REG_OUT_CTRL_BUF_Y_EN
1407d62e5feeSJonathan Cameron | SCA3000_REG_OUT_CTRL_BUF_Z_EN
1408d62e5feeSJonathan Cameron | SCA3000_REG_OUT_CTRL_BUF_DIV_4);
1409d62e5feeSJonathan Cameron if (ret)
1410d62e5feeSJonathan Cameron goto error_ret;
1411d62e5feeSJonathan Cameron /* Enable interrupts, relevant to mode and set up as active low */
1412d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1);
1413d62e5feeSJonathan Cameron if (ret)
1414d62e5feeSJonathan Cameron goto error_ret;
1415d62e5feeSJonathan Cameron ret = sca3000_write_reg(st,
1416d62e5feeSJonathan Cameron SCA3000_REG_INT_MASK_ADDR,
1417d62e5feeSJonathan Cameron (ret & SCA3000_REG_INT_MASK_PROT_MASK)
1418d62e5feeSJonathan Cameron | SCA3000_REG_INT_MASK_ACTIVE_LOW);
1419d62e5feeSJonathan Cameron if (ret)
1420d62e5feeSJonathan Cameron goto error_ret;
1421d62e5feeSJonathan Cameron /*
1422d62e5feeSJonathan Cameron * Select normal measurement mode, free fall off, ring off
1423d62e5feeSJonathan Cameron * Ring in 12 bit mode - it is fine to overwrite reserved bits 3,5
1424d62e5feeSJonathan Cameron * as that occurs in one of the example on the datasheet
1425d62e5feeSJonathan Cameron */
1426d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
1427d62e5feeSJonathan Cameron if (ret)
1428d62e5feeSJonathan Cameron goto error_ret;
1429d62e5feeSJonathan Cameron ret = sca3000_write_reg(st, SCA3000_REG_MODE_ADDR,
1430d62e5feeSJonathan Cameron (st->rx[0] & SCA3000_MODE_PROT_MASK));
1431d62e5feeSJonathan Cameron
1432d62e5feeSJonathan Cameron error_ret:
1433d62e5feeSJonathan Cameron mutex_unlock(&st->lock);
1434d62e5feeSJonathan Cameron return ret;
1435d62e5feeSJonathan Cameron }
1436d62e5feeSJonathan Cameron
1437d62e5feeSJonathan Cameron static const struct iio_info sca3000_info = {
1438d62e5feeSJonathan Cameron .attrs = &sca3000_attribute_group,
1439d62e5feeSJonathan Cameron .read_raw = &sca3000_read_raw,
1440d62e5feeSJonathan Cameron .write_raw = &sca3000_write_raw,
1441d62e5feeSJonathan Cameron .read_event_value = &sca3000_read_event_value,
1442d62e5feeSJonathan Cameron .write_event_value = &sca3000_write_event_value,
1443d62e5feeSJonathan Cameron .read_event_config = &sca3000_read_event_config,
1444d62e5feeSJonathan Cameron .write_event_config = &sca3000_write_event_config,
1445d62e5feeSJonathan Cameron };
1446d62e5feeSJonathan Cameron
sca3000_probe(struct spi_device * spi)1447d62e5feeSJonathan Cameron static int sca3000_probe(struct spi_device *spi)
1448d62e5feeSJonathan Cameron {
1449d62e5feeSJonathan Cameron int ret;
1450d62e5feeSJonathan Cameron struct sca3000_state *st;
1451d62e5feeSJonathan Cameron struct iio_dev *indio_dev;
1452d62e5feeSJonathan Cameron
1453d62e5feeSJonathan Cameron indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
1454d62e5feeSJonathan Cameron if (!indio_dev)
1455d62e5feeSJonathan Cameron return -ENOMEM;
1456d62e5feeSJonathan Cameron
1457d62e5feeSJonathan Cameron st = iio_priv(indio_dev);
1458d62e5feeSJonathan Cameron spi_set_drvdata(spi, indio_dev);
1459d62e5feeSJonathan Cameron st->us = spi;
1460d62e5feeSJonathan Cameron mutex_init(&st->lock);
1461d62e5feeSJonathan Cameron st->info = &sca3000_spi_chip_info_tbl[spi_get_device_id(spi)
1462d62e5feeSJonathan Cameron ->driver_data];
1463d62e5feeSJonathan Cameron
1464d62e5feeSJonathan Cameron indio_dev->name = spi_get_device_id(spi)->name;
1465d62e5feeSJonathan Cameron indio_dev->info = &sca3000_info;
1466d62e5feeSJonathan Cameron if (st->info->temp_output) {
1467d62e5feeSJonathan Cameron indio_dev->channels = sca3000_channels_with_temp;
1468d62e5feeSJonathan Cameron indio_dev->num_channels =
1469d62e5feeSJonathan Cameron ARRAY_SIZE(sca3000_channels_with_temp);
1470d62e5feeSJonathan Cameron } else {
1471d62e5feeSJonathan Cameron indio_dev->channels = sca3000_channels;
1472d62e5feeSJonathan Cameron indio_dev->num_channels = ARRAY_SIZE(sca3000_channels);
1473d62e5feeSJonathan Cameron }
1474d62e5feeSJonathan Cameron indio_dev->modes = INDIO_DIRECT_MODE;
1475d62e5feeSJonathan Cameron
1476e03ed893SAlexandru Ardelean ret = devm_iio_kfifo_buffer_setup(&spi->dev, indio_dev,
1477e03ed893SAlexandru Ardelean &sca3000_ring_setup_ops);
1478da2d5449SChristophe JAILLET if (ret)
1479da2d5449SChristophe JAILLET return ret;
1480d62e5feeSJonathan Cameron
1481d62e5feeSJonathan Cameron if (spi->irq) {
1482d62e5feeSJonathan Cameron ret = request_threaded_irq(spi->irq,
1483d62e5feeSJonathan Cameron NULL,
1484d62e5feeSJonathan Cameron &sca3000_event_handler,
1485d62e5feeSJonathan Cameron IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
1486d62e5feeSJonathan Cameron "sca3000",
1487d62e5feeSJonathan Cameron indio_dev);
1488d62e5feeSJonathan Cameron if (ret)
1489d62e5feeSJonathan Cameron return ret;
1490d62e5feeSJonathan Cameron }
1491d62e5feeSJonathan Cameron ret = sca3000_clean_setup(st);
1492d62e5feeSJonathan Cameron if (ret)
1493d62e5feeSJonathan Cameron goto error_free_irq;
1494d62e5feeSJonathan Cameron
1495d62e5feeSJonathan Cameron ret = sca3000_print_rev(indio_dev);
1496d62e5feeSJonathan Cameron if (ret)
1497d62e5feeSJonathan Cameron goto error_free_irq;
1498d62e5feeSJonathan Cameron
1499d62e5feeSJonathan Cameron return iio_device_register(indio_dev);
1500d62e5feeSJonathan Cameron
1501d62e5feeSJonathan Cameron error_free_irq:
1502d62e5feeSJonathan Cameron if (spi->irq)
1503d62e5feeSJonathan Cameron free_irq(spi->irq, indio_dev);
1504d62e5feeSJonathan Cameron
1505d62e5feeSJonathan Cameron return ret;
1506d62e5feeSJonathan Cameron }
1507d62e5feeSJonathan Cameron
sca3000_stop_all_interrupts(struct sca3000_state * st)1508d62e5feeSJonathan Cameron static int sca3000_stop_all_interrupts(struct sca3000_state *st)
1509d62e5feeSJonathan Cameron {
1510d62e5feeSJonathan Cameron int ret;
1511d62e5feeSJonathan Cameron
1512d62e5feeSJonathan Cameron mutex_lock(&st->lock);
1513d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1);
1514d62e5feeSJonathan Cameron if (ret)
1515d62e5feeSJonathan Cameron goto error_ret;
1516d62e5feeSJonathan Cameron ret = sca3000_write_reg(st, SCA3000_REG_INT_MASK_ADDR,
1517d62e5feeSJonathan Cameron (st->rx[0] &
1518d62e5feeSJonathan Cameron ~(SCA3000_REG_INT_MASK_RING_THREE_QUARTER |
1519d62e5feeSJonathan Cameron SCA3000_REG_INT_MASK_RING_HALF |
1520d62e5feeSJonathan Cameron SCA3000_REG_INT_MASK_ALL_INTS)));
1521d62e5feeSJonathan Cameron error_ret:
1522d62e5feeSJonathan Cameron mutex_unlock(&st->lock);
1523d62e5feeSJonathan Cameron return ret;
1524d62e5feeSJonathan Cameron }
1525d62e5feeSJonathan Cameron
sca3000_remove(struct spi_device * spi)1526a0386bbaSUwe Kleine-König static void sca3000_remove(struct spi_device *spi)
1527d62e5feeSJonathan Cameron {
1528d62e5feeSJonathan Cameron struct iio_dev *indio_dev = spi_get_drvdata(spi);
1529d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev);
1530d62e5feeSJonathan Cameron
1531d62e5feeSJonathan Cameron iio_device_unregister(indio_dev);
1532d62e5feeSJonathan Cameron
1533d62e5feeSJonathan Cameron /* Must ensure no interrupts can be generated after this! */
1534d62e5feeSJonathan Cameron sca3000_stop_all_interrupts(st);
1535d62e5feeSJonathan Cameron if (spi->irq)
1536d62e5feeSJonathan Cameron free_irq(spi->irq, indio_dev);
1537d62e5feeSJonathan Cameron }
1538d62e5feeSJonathan Cameron
1539d62e5feeSJonathan Cameron static const struct spi_device_id sca3000_id[] = {
1540d62e5feeSJonathan Cameron {"sca3000_d01", d01},
1541d62e5feeSJonathan Cameron {"sca3000_e02", e02},
1542d62e5feeSJonathan Cameron {"sca3000_e04", e04},
1543d62e5feeSJonathan Cameron {"sca3000_e05", e05},
1544d62e5feeSJonathan Cameron {}
1545d62e5feeSJonathan Cameron };
1546d62e5feeSJonathan Cameron MODULE_DEVICE_TABLE(spi, sca3000_id);
1547d62e5feeSJonathan Cameron
1548d62e5feeSJonathan Cameron static struct spi_driver sca3000_driver = {
1549d62e5feeSJonathan Cameron .driver = {
1550d62e5feeSJonathan Cameron .name = "sca3000",
1551d62e5feeSJonathan Cameron },
1552d62e5feeSJonathan Cameron .probe = sca3000_probe,
1553d62e5feeSJonathan Cameron .remove = sca3000_remove,
1554d62e5feeSJonathan Cameron .id_table = sca3000_id,
1555d62e5feeSJonathan Cameron };
1556d62e5feeSJonathan Cameron module_spi_driver(sca3000_driver);
1557d62e5feeSJonathan Cameron
1558d62e5feeSJonathan Cameron MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
1559d62e5feeSJonathan Cameron MODULE_DESCRIPTION("VTI SCA3000 Series Accelerometers SPI driver");
1560d62e5feeSJonathan Cameron MODULE_LICENSE("GPL v2");
1561