xref: /openbmc/linux/drivers/iio/accel/sca3000.c (revision a263456f)
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