162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * sca3000_core.c -- support VTI sca3000 series accelerometers via SPI
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2009 Jonathan Cameron <jic23@kernel.org>
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * See industrialio/accels/sca3000.h for comments.
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/interrupt.h>
1162306a36Sopenharmony_ci#include <linux/fs.h>
1262306a36Sopenharmony_ci#include <linux/device.h>
1362306a36Sopenharmony_ci#include <linux/slab.h>
1462306a36Sopenharmony_ci#include <linux/kernel.h>
1562306a36Sopenharmony_ci#include <linux/spi/spi.h>
1662306a36Sopenharmony_ci#include <linux/sysfs.h>
1762306a36Sopenharmony_ci#include <linux/module.h>
1862306a36Sopenharmony_ci#include <linux/uaccess.h>
1962306a36Sopenharmony_ci#include <linux/iio/iio.h>
2062306a36Sopenharmony_ci#include <linux/iio/sysfs.h>
2162306a36Sopenharmony_ci#include <linux/iio/events.h>
2262306a36Sopenharmony_ci#include <linux/iio/buffer.h>
2362306a36Sopenharmony_ci#include <linux/iio/kfifo_buf.h>
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define SCA3000_WRITE_REG(a) (((a) << 2) | 0x02)
2662306a36Sopenharmony_ci#define SCA3000_READ_REG(a) ((a) << 2)
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#define SCA3000_REG_REVID_ADDR				0x00
2962306a36Sopenharmony_ci#define   SCA3000_REG_REVID_MAJOR_MASK			GENMASK(8, 4)
3062306a36Sopenharmony_ci#define   SCA3000_REG_REVID_MINOR_MASK			GENMASK(3, 0)
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#define SCA3000_REG_STATUS_ADDR				0x02
3362306a36Sopenharmony_ci#define   SCA3000_LOCKED				BIT(5)
3462306a36Sopenharmony_ci#define   SCA3000_EEPROM_CS_ERROR			BIT(1)
3562306a36Sopenharmony_ci#define   SCA3000_SPI_FRAME_ERROR			BIT(0)
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci/* All reads done using register decrement so no need to directly access LSBs */
3862306a36Sopenharmony_ci#define SCA3000_REG_X_MSB_ADDR				0x05
3962306a36Sopenharmony_ci#define SCA3000_REG_Y_MSB_ADDR				0x07
4062306a36Sopenharmony_ci#define SCA3000_REG_Z_MSB_ADDR				0x09
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#define SCA3000_REG_RING_OUT_ADDR			0x0f
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci/* Temp read untested - the e05 doesn't have the sensor */
4562306a36Sopenharmony_ci#define SCA3000_REG_TEMP_MSB_ADDR			0x13
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#define SCA3000_REG_MODE_ADDR				0x14
4862306a36Sopenharmony_ci#define SCA3000_MODE_PROT_MASK				0x28
4962306a36Sopenharmony_ci#define   SCA3000_REG_MODE_RING_BUF_ENABLE		BIT(7)
5062306a36Sopenharmony_ci#define   SCA3000_REG_MODE_RING_BUF_8BIT		BIT(6)
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci/*
5362306a36Sopenharmony_ci * Free fall detection triggers an interrupt if the acceleration
5462306a36Sopenharmony_ci * is below a threshold for equivalent of 25cm drop
5562306a36Sopenharmony_ci */
5662306a36Sopenharmony_ci#define   SCA3000_REG_MODE_FREE_FALL_DETECT		BIT(4)
5762306a36Sopenharmony_ci#define   SCA3000_REG_MODE_MEAS_MODE_NORMAL		0x00
5862306a36Sopenharmony_ci#define   SCA3000_REG_MODE_MEAS_MODE_OP_1		0x01
5962306a36Sopenharmony_ci#define   SCA3000_REG_MODE_MEAS_MODE_OP_2		0x02
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci/*
6262306a36Sopenharmony_ci * In motion detection mode the accelerations are band pass filtered
6362306a36Sopenharmony_ci * (approx 1 - 25Hz) and then a programmable threshold used to trigger
6462306a36Sopenharmony_ci * and interrupt.
6562306a36Sopenharmony_ci */
6662306a36Sopenharmony_ci#define   SCA3000_REG_MODE_MEAS_MODE_MOT_DET		0x03
6762306a36Sopenharmony_ci#define   SCA3000_REG_MODE_MODE_MASK			0x03
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci#define SCA3000_REG_BUF_COUNT_ADDR			0x15
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci#define SCA3000_REG_INT_STATUS_ADDR			0x16
7262306a36Sopenharmony_ci#define   SCA3000_REG_INT_STATUS_THREE_QUARTERS		BIT(7)
7362306a36Sopenharmony_ci#define   SCA3000_REG_INT_STATUS_HALF			BIT(6)
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci#define SCA3000_INT_STATUS_FREE_FALL			BIT(3)
7662306a36Sopenharmony_ci#define SCA3000_INT_STATUS_Y_TRIGGER			BIT(2)
7762306a36Sopenharmony_ci#define SCA3000_INT_STATUS_X_TRIGGER			BIT(1)
7862306a36Sopenharmony_ci#define SCA3000_INT_STATUS_Z_TRIGGER			BIT(0)
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci/* Used to allow access to multiplexed registers */
8162306a36Sopenharmony_ci#define SCA3000_REG_CTRL_SEL_ADDR			0x18
8262306a36Sopenharmony_ci/* Only available for SCA3000-D03 and SCA3000-D01 */
8362306a36Sopenharmony_ci#define   SCA3000_REG_CTRL_SEL_I2C_DISABLE		0x01
8462306a36Sopenharmony_ci#define   SCA3000_REG_CTRL_SEL_MD_CTRL			0x02
8562306a36Sopenharmony_ci#define   SCA3000_REG_CTRL_SEL_MD_Y_TH			0x03
8662306a36Sopenharmony_ci#define   SCA3000_REG_CTRL_SEL_MD_X_TH			0x04
8762306a36Sopenharmony_ci#define   SCA3000_REG_CTRL_SEL_MD_Z_TH			0x05
8862306a36Sopenharmony_ci/*
8962306a36Sopenharmony_ci * BE VERY CAREFUL WITH THIS, IF 3 BITS ARE NOT SET the device
9062306a36Sopenharmony_ci * will not function
9162306a36Sopenharmony_ci */
9262306a36Sopenharmony_ci#define   SCA3000_REG_CTRL_SEL_OUT_CTRL			0x0B
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci#define     SCA3000_REG_OUT_CTRL_PROT_MASK		0xE0
9562306a36Sopenharmony_ci#define     SCA3000_REG_OUT_CTRL_BUF_X_EN		0x10
9662306a36Sopenharmony_ci#define     SCA3000_REG_OUT_CTRL_BUF_Y_EN		0x08
9762306a36Sopenharmony_ci#define     SCA3000_REG_OUT_CTRL_BUF_Z_EN		0x04
9862306a36Sopenharmony_ci#define     SCA3000_REG_OUT_CTRL_BUF_DIV_MASK		0x03
9962306a36Sopenharmony_ci#define     SCA3000_REG_OUT_CTRL_BUF_DIV_4		0x02
10062306a36Sopenharmony_ci#define     SCA3000_REG_OUT_CTRL_BUF_DIV_2		0x01
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci/*
10462306a36Sopenharmony_ci * Control which motion detector interrupts are on.
10562306a36Sopenharmony_ci * For now only OR combinations are supported.
10662306a36Sopenharmony_ci */
10762306a36Sopenharmony_ci#define SCA3000_MD_CTRL_PROT_MASK			0xC0
10862306a36Sopenharmony_ci#define SCA3000_MD_CTRL_OR_Y				BIT(0)
10962306a36Sopenharmony_ci#define SCA3000_MD_CTRL_OR_X				BIT(1)
11062306a36Sopenharmony_ci#define SCA3000_MD_CTRL_OR_Z				BIT(2)
11162306a36Sopenharmony_ci/* Currently unsupported */
11262306a36Sopenharmony_ci#define SCA3000_MD_CTRL_AND_Y				BIT(3)
11362306a36Sopenharmony_ci#define SCA3000_MD_CTRL_AND_X				BIT(4)
11462306a36Sopenharmony_ci#define SCA3000_MD_CTRL_AND_Z				BIT(5)
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci/*
11762306a36Sopenharmony_ci * Some control registers of complex access methods requiring this register to
11862306a36Sopenharmony_ci * be used to remove a lock.
11962306a36Sopenharmony_ci */
12062306a36Sopenharmony_ci#define SCA3000_REG_UNLOCK_ADDR				0x1e
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci#define SCA3000_REG_INT_MASK_ADDR			0x21
12362306a36Sopenharmony_ci#define   SCA3000_REG_INT_MASK_PROT_MASK		0x1C
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci#define   SCA3000_REG_INT_MASK_RING_THREE_QUARTER	BIT(7)
12662306a36Sopenharmony_ci#define   SCA3000_REG_INT_MASK_RING_HALF		BIT(6)
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci#define SCA3000_REG_INT_MASK_ALL_INTS			0x02
12962306a36Sopenharmony_ci#define SCA3000_REG_INT_MASK_ACTIVE_HIGH		0x01
13062306a36Sopenharmony_ci#define SCA3000_REG_INT_MASK_ACTIVE_LOW			0x00
13162306a36Sopenharmony_ci/* Values of multiplexed registers (write to ctrl_data after select) */
13262306a36Sopenharmony_ci#define SCA3000_REG_CTRL_DATA_ADDR			0x22
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci/*
13562306a36Sopenharmony_ci * Measurement modes available on some sca3000 series chips. Code assumes others
13662306a36Sopenharmony_ci * may become available in the future.
13762306a36Sopenharmony_ci *
13862306a36Sopenharmony_ci * Bypass - Bypass the low-pass filter in the signal channel so as to increase
13962306a36Sopenharmony_ci *          signal bandwidth.
14062306a36Sopenharmony_ci *
14162306a36Sopenharmony_ci * Narrow - Narrow low-pass filtering of the signal channel and half output
14262306a36Sopenharmony_ci *          data rate by decimation.
14362306a36Sopenharmony_ci *
14462306a36Sopenharmony_ci * Wide - Widen low-pass filtering of signal channel to increase bandwidth
14562306a36Sopenharmony_ci */
14662306a36Sopenharmony_ci#define SCA3000_OP_MODE_BYPASS				0x01
14762306a36Sopenharmony_ci#define SCA3000_OP_MODE_NARROW				0x02
14862306a36Sopenharmony_ci#define SCA3000_OP_MODE_WIDE				0x04
14962306a36Sopenharmony_ci#define SCA3000_MAX_TX 6
15062306a36Sopenharmony_ci#define SCA3000_MAX_RX 2
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci/**
15362306a36Sopenharmony_ci * struct sca3000_state - device instance state information
15462306a36Sopenharmony_ci * @us:			the associated spi device
15562306a36Sopenharmony_ci * @info:			chip variant information
15662306a36Sopenharmony_ci * @last_timestamp:		the timestamp of the last event
15762306a36Sopenharmony_ci * @mo_det_use_count:		reference counter for the motion detection unit
15862306a36Sopenharmony_ci * @lock:			lock used to protect elements of sca3000_state
15962306a36Sopenharmony_ci *				and the underlying device state.
16062306a36Sopenharmony_ci * @tx:			dma-able transmit buffer
16162306a36Sopenharmony_ci * @rx:			dma-able receive buffer
16262306a36Sopenharmony_ci **/
16362306a36Sopenharmony_cistruct sca3000_state {
16462306a36Sopenharmony_ci	struct spi_device		*us;
16562306a36Sopenharmony_ci	const struct sca3000_chip_info	*info;
16662306a36Sopenharmony_ci	s64				last_timestamp;
16762306a36Sopenharmony_ci	int				mo_det_use_count;
16862306a36Sopenharmony_ci	struct mutex			lock;
16962306a36Sopenharmony_ci	/* Can these share a cacheline ? */
17062306a36Sopenharmony_ci	u8				rx[384] __aligned(IIO_DMA_MINALIGN);
17162306a36Sopenharmony_ci	u8				tx[6] __aligned(IIO_DMA_MINALIGN);
17262306a36Sopenharmony_ci};
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci/**
17562306a36Sopenharmony_ci * struct sca3000_chip_info - model dependent parameters
17662306a36Sopenharmony_ci * @scale:			scale * 10^-6
17762306a36Sopenharmony_ci * @temp_output:		some devices have temperature sensors.
17862306a36Sopenharmony_ci * @measurement_mode_freq:	normal mode sampling frequency
17962306a36Sopenharmony_ci * @measurement_mode_3db_freq:	3db cutoff frequency of the low pass filter for
18062306a36Sopenharmony_ci * the normal measurement mode.
18162306a36Sopenharmony_ci * @option_mode_1:		first optional mode. Not all models have one
18262306a36Sopenharmony_ci * @option_mode_1_freq:		option mode 1 sampling frequency
18362306a36Sopenharmony_ci * @option_mode_1_3db_freq:	3db cutoff frequency of the low pass filter for
18462306a36Sopenharmony_ci * the first option mode.
18562306a36Sopenharmony_ci * @option_mode_2:		second optional mode. Not all chips have one
18662306a36Sopenharmony_ci * @option_mode_2_freq:		option mode 2 sampling frequency
18762306a36Sopenharmony_ci * @option_mode_2_3db_freq:	3db cutoff frequency of the low pass filter for
18862306a36Sopenharmony_ci * the second option mode.
18962306a36Sopenharmony_ci * @mot_det_mult_xz:		Bit wise multipliers to calculate the threshold
19062306a36Sopenharmony_ci * for motion detection in the x and z axis.
19162306a36Sopenharmony_ci * @mot_det_mult_y:		Bit wise multipliers to calculate the threshold
19262306a36Sopenharmony_ci * for motion detection in the y axis.
19362306a36Sopenharmony_ci *
19462306a36Sopenharmony_ci * This structure is used to hold information about the functionality of a given
19562306a36Sopenharmony_ci * sca3000 variant.
19662306a36Sopenharmony_ci **/
19762306a36Sopenharmony_cistruct sca3000_chip_info {
19862306a36Sopenharmony_ci	unsigned int		scale;
19962306a36Sopenharmony_ci	bool			temp_output;
20062306a36Sopenharmony_ci	int			measurement_mode_freq;
20162306a36Sopenharmony_ci	int			measurement_mode_3db_freq;
20262306a36Sopenharmony_ci	int			option_mode_1;
20362306a36Sopenharmony_ci	int			option_mode_1_freq;
20462306a36Sopenharmony_ci	int			option_mode_1_3db_freq;
20562306a36Sopenharmony_ci	int			option_mode_2;
20662306a36Sopenharmony_ci	int			option_mode_2_freq;
20762306a36Sopenharmony_ci	int			option_mode_2_3db_freq;
20862306a36Sopenharmony_ci	int			mot_det_mult_xz[6];
20962306a36Sopenharmony_ci	int			mot_det_mult_y[7];
21062306a36Sopenharmony_ci};
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_cienum sca3000_variant {
21362306a36Sopenharmony_ci	d01,
21462306a36Sopenharmony_ci	e02,
21562306a36Sopenharmony_ci	e04,
21662306a36Sopenharmony_ci	e05,
21762306a36Sopenharmony_ci};
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci/*
22062306a36Sopenharmony_ci * Note where option modes are not defined, the chip simply does not
22162306a36Sopenharmony_ci * support any.
22262306a36Sopenharmony_ci * Other chips in the sca3000 series use i2c and are not included here.
22362306a36Sopenharmony_ci *
22462306a36Sopenharmony_ci * Some of these devices are only listed in the family data sheet and
22562306a36Sopenharmony_ci * do not actually appear to be available.
22662306a36Sopenharmony_ci */
22762306a36Sopenharmony_cistatic const struct sca3000_chip_info sca3000_spi_chip_info_tbl[] = {
22862306a36Sopenharmony_ci	[d01] = {
22962306a36Sopenharmony_ci		.scale = 7357,
23062306a36Sopenharmony_ci		.temp_output = true,
23162306a36Sopenharmony_ci		.measurement_mode_freq = 250,
23262306a36Sopenharmony_ci		.measurement_mode_3db_freq = 45,
23362306a36Sopenharmony_ci		.option_mode_1 = SCA3000_OP_MODE_BYPASS,
23462306a36Sopenharmony_ci		.option_mode_1_freq = 250,
23562306a36Sopenharmony_ci		.option_mode_1_3db_freq = 70,
23662306a36Sopenharmony_ci		.mot_det_mult_xz = {50, 100, 200, 350, 650, 1300},
23762306a36Sopenharmony_ci		.mot_det_mult_y = {50, 100, 150, 250, 450, 850, 1750},
23862306a36Sopenharmony_ci	},
23962306a36Sopenharmony_ci	[e02] = {
24062306a36Sopenharmony_ci		.scale = 9810,
24162306a36Sopenharmony_ci		.measurement_mode_freq = 125,
24262306a36Sopenharmony_ci		.measurement_mode_3db_freq = 40,
24362306a36Sopenharmony_ci		.option_mode_1 = SCA3000_OP_MODE_NARROW,
24462306a36Sopenharmony_ci		.option_mode_1_freq = 63,
24562306a36Sopenharmony_ci		.option_mode_1_3db_freq = 11,
24662306a36Sopenharmony_ci		.mot_det_mult_xz = {100, 150, 300, 550, 1050, 2050},
24762306a36Sopenharmony_ci		.mot_det_mult_y = {50, 100, 200, 350, 700, 1350, 2700},
24862306a36Sopenharmony_ci	},
24962306a36Sopenharmony_ci	[e04] = {
25062306a36Sopenharmony_ci		.scale = 19620,
25162306a36Sopenharmony_ci		.measurement_mode_freq = 100,
25262306a36Sopenharmony_ci		.measurement_mode_3db_freq = 38,
25362306a36Sopenharmony_ci		.option_mode_1 = SCA3000_OP_MODE_NARROW,
25462306a36Sopenharmony_ci		.option_mode_1_freq = 50,
25562306a36Sopenharmony_ci		.option_mode_1_3db_freq = 9,
25662306a36Sopenharmony_ci		.option_mode_2 = SCA3000_OP_MODE_WIDE,
25762306a36Sopenharmony_ci		.option_mode_2_freq = 400,
25862306a36Sopenharmony_ci		.option_mode_2_3db_freq = 70,
25962306a36Sopenharmony_ci		.mot_det_mult_xz = {200, 300, 600, 1100, 2100, 4100},
26062306a36Sopenharmony_ci		.mot_det_mult_y = {100, 200, 400, 7000, 1400, 2700, 54000},
26162306a36Sopenharmony_ci	},
26262306a36Sopenharmony_ci	[e05] = {
26362306a36Sopenharmony_ci		.scale = 61313,
26462306a36Sopenharmony_ci		.measurement_mode_freq = 200,
26562306a36Sopenharmony_ci		.measurement_mode_3db_freq = 60,
26662306a36Sopenharmony_ci		.option_mode_1 = SCA3000_OP_MODE_NARROW,
26762306a36Sopenharmony_ci		.option_mode_1_freq = 50,
26862306a36Sopenharmony_ci		.option_mode_1_3db_freq = 9,
26962306a36Sopenharmony_ci		.option_mode_2 = SCA3000_OP_MODE_WIDE,
27062306a36Sopenharmony_ci		.option_mode_2_freq = 400,
27162306a36Sopenharmony_ci		.option_mode_2_3db_freq = 75,
27262306a36Sopenharmony_ci		.mot_det_mult_xz = {600, 900, 1700, 3200, 6100, 11900},
27362306a36Sopenharmony_ci		.mot_det_mult_y = {300, 600, 1200, 2000, 4100, 7800, 15600},
27462306a36Sopenharmony_ci	},
27562306a36Sopenharmony_ci};
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_cistatic int sca3000_write_reg(struct sca3000_state *st, u8 address, u8 val)
27862306a36Sopenharmony_ci{
27962306a36Sopenharmony_ci	st->tx[0] = SCA3000_WRITE_REG(address);
28062306a36Sopenharmony_ci	st->tx[1] = val;
28162306a36Sopenharmony_ci	return spi_write(st->us, st->tx, 2);
28262306a36Sopenharmony_ci}
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_cistatic int sca3000_read_data_short(struct sca3000_state *st,
28562306a36Sopenharmony_ci				   u8 reg_address_high,
28662306a36Sopenharmony_ci				   int len)
28762306a36Sopenharmony_ci{
28862306a36Sopenharmony_ci	struct spi_transfer xfer[2] = {
28962306a36Sopenharmony_ci		{
29062306a36Sopenharmony_ci			.len = 1,
29162306a36Sopenharmony_ci			.tx_buf = st->tx,
29262306a36Sopenharmony_ci		}, {
29362306a36Sopenharmony_ci			.len = len,
29462306a36Sopenharmony_ci			.rx_buf = st->rx,
29562306a36Sopenharmony_ci		}
29662306a36Sopenharmony_ci	};
29762306a36Sopenharmony_ci	st->tx[0] = SCA3000_READ_REG(reg_address_high);
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer));
30062306a36Sopenharmony_ci}
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci/**
30362306a36Sopenharmony_ci * sca3000_reg_lock_on() - test if the ctrl register lock is on
30462306a36Sopenharmony_ci * @st: Driver specific device instance data.
30562306a36Sopenharmony_ci *
30662306a36Sopenharmony_ci * Lock must be held.
30762306a36Sopenharmony_ci **/
30862306a36Sopenharmony_cistatic int sca3000_reg_lock_on(struct sca3000_state *st)
30962306a36Sopenharmony_ci{
31062306a36Sopenharmony_ci	int ret;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	ret = sca3000_read_data_short(st, SCA3000_REG_STATUS_ADDR, 1);
31362306a36Sopenharmony_ci	if (ret < 0)
31462306a36Sopenharmony_ci		return ret;
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	return !(st->rx[0] & SCA3000_LOCKED);
31762306a36Sopenharmony_ci}
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci/**
32062306a36Sopenharmony_ci * __sca3000_unlock_reg_lock() - unlock the control registers
32162306a36Sopenharmony_ci * @st: Driver specific device instance data.
32262306a36Sopenharmony_ci *
32362306a36Sopenharmony_ci * Note the device does not appear to support doing this in a single transfer.
32462306a36Sopenharmony_ci * This should only ever be used as part of ctrl reg read.
32562306a36Sopenharmony_ci * Lock must be held before calling this
32662306a36Sopenharmony_ci */
32762306a36Sopenharmony_cistatic int __sca3000_unlock_reg_lock(struct sca3000_state *st)
32862306a36Sopenharmony_ci{
32962306a36Sopenharmony_ci	struct spi_transfer xfer[3] = {
33062306a36Sopenharmony_ci		{
33162306a36Sopenharmony_ci			.len = 2,
33262306a36Sopenharmony_ci			.cs_change = 1,
33362306a36Sopenharmony_ci			.tx_buf = st->tx,
33462306a36Sopenharmony_ci		}, {
33562306a36Sopenharmony_ci			.len = 2,
33662306a36Sopenharmony_ci			.cs_change = 1,
33762306a36Sopenharmony_ci			.tx_buf = st->tx + 2,
33862306a36Sopenharmony_ci		}, {
33962306a36Sopenharmony_ci			.len = 2,
34062306a36Sopenharmony_ci			.tx_buf = st->tx + 4,
34162306a36Sopenharmony_ci		},
34262306a36Sopenharmony_ci	};
34362306a36Sopenharmony_ci	st->tx[0] = SCA3000_WRITE_REG(SCA3000_REG_UNLOCK_ADDR);
34462306a36Sopenharmony_ci	st->tx[1] = 0x00;
34562306a36Sopenharmony_ci	st->tx[2] = SCA3000_WRITE_REG(SCA3000_REG_UNLOCK_ADDR);
34662306a36Sopenharmony_ci	st->tx[3] = 0x50;
34762306a36Sopenharmony_ci	st->tx[4] = SCA3000_WRITE_REG(SCA3000_REG_UNLOCK_ADDR);
34862306a36Sopenharmony_ci	st->tx[5] = 0xA0;
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer));
35162306a36Sopenharmony_ci}
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci/**
35462306a36Sopenharmony_ci * sca3000_write_ctrl_reg() - write to a lock protect ctrl register
35562306a36Sopenharmony_ci * @st: Driver specific device instance data.
35662306a36Sopenharmony_ci * @sel: selects which registers we wish to write to
35762306a36Sopenharmony_ci * @val: the value to be written
35862306a36Sopenharmony_ci *
35962306a36Sopenharmony_ci * Certain control registers are protected against overwriting by the lock
36062306a36Sopenharmony_ci * register and use a shared write address. This function allows writing of
36162306a36Sopenharmony_ci * these registers.
36262306a36Sopenharmony_ci * Lock must be held.
36362306a36Sopenharmony_ci */
36462306a36Sopenharmony_cistatic int sca3000_write_ctrl_reg(struct sca3000_state *st,
36562306a36Sopenharmony_ci				  u8 sel,
36662306a36Sopenharmony_ci				  uint8_t val)
36762306a36Sopenharmony_ci{
36862306a36Sopenharmony_ci	int ret;
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	ret = sca3000_reg_lock_on(st);
37162306a36Sopenharmony_ci	if (ret < 0)
37262306a36Sopenharmony_ci		goto error_ret;
37362306a36Sopenharmony_ci	if (ret) {
37462306a36Sopenharmony_ci		ret = __sca3000_unlock_reg_lock(st);
37562306a36Sopenharmony_ci		if (ret)
37662306a36Sopenharmony_ci			goto error_ret;
37762306a36Sopenharmony_ci	}
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	/* Set the control select register */
38062306a36Sopenharmony_ci	ret = sca3000_write_reg(st, SCA3000_REG_CTRL_SEL_ADDR, sel);
38162306a36Sopenharmony_ci	if (ret)
38262306a36Sopenharmony_ci		goto error_ret;
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci	/* Write the actual value into the register */
38562306a36Sopenharmony_ci	ret = sca3000_write_reg(st, SCA3000_REG_CTRL_DATA_ADDR, val);
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_cierror_ret:
38862306a36Sopenharmony_ci	return ret;
38962306a36Sopenharmony_ci}
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci/**
39262306a36Sopenharmony_ci * sca3000_read_ctrl_reg() - read from lock protected control register.
39362306a36Sopenharmony_ci * @st: Driver specific device instance data.
39462306a36Sopenharmony_ci * @ctrl_reg: Which ctrl register do we want to read.
39562306a36Sopenharmony_ci *
39662306a36Sopenharmony_ci * Lock must be held.
39762306a36Sopenharmony_ci */
39862306a36Sopenharmony_cistatic int sca3000_read_ctrl_reg(struct sca3000_state *st,
39962306a36Sopenharmony_ci				 u8 ctrl_reg)
40062306a36Sopenharmony_ci{
40162306a36Sopenharmony_ci	int ret;
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	ret = sca3000_reg_lock_on(st);
40462306a36Sopenharmony_ci	if (ret < 0)
40562306a36Sopenharmony_ci		goto error_ret;
40662306a36Sopenharmony_ci	if (ret) {
40762306a36Sopenharmony_ci		ret = __sca3000_unlock_reg_lock(st);
40862306a36Sopenharmony_ci		if (ret)
40962306a36Sopenharmony_ci			goto error_ret;
41062306a36Sopenharmony_ci	}
41162306a36Sopenharmony_ci	/* Set the control select register */
41262306a36Sopenharmony_ci	ret = sca3000_write_reg(st, SCA3000_REG_CTRL_SEL_ADDR, ctrl_reg);
41362306a36Sopenharmony_ci	if (ret)
41462306a36Sopenharmony_ci		goto error_ret;
41562306a36Sopenharmony_ci	ret = sca3000_read_data_short(st, SCA3000_REG_CTRL_DATA_ADDR, 1);
41662306a36Sopenharmony_ci	if (ret)
41762306a36Sopenharmony_ci		goto error_ret;
41862306a36Sopenharmony_ci	return st->rx[0];
41962306a36Sopenharmony_cierror_ret:
42062306a36Sopenharmony_ci	return ret;
42162306a36Sopenharmony_ci}
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci/**
42462306a36Sopenharmony_ci * sca3000_print_rev() - sysfs interface to read the chip revision number
42562306a36Sopenharmony_ci * @indio_dev: Device instance specific generic IIO data.
42662306a36Sopenharmony_ci * Driver specific device instance data can be obtained via
42762306a36Sopenharmony_ci * iio_priv(indio_dev)
42862306a36Sopenharmony_ci */
42962306a36Sopenharmony_cistatic int sca3000_print_rev(struct iio_dev *indio_dev)
43062306a36Sopenharmony_ci{
43162306a36Sopenharmony_ci	int ret;
43262306a36Sopenharmony_ci	struct sca3000_state *st = iio_priv(indio_dev);
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	mutex_lock(&st->lock);
43562306a36Sopenharmony_ci	ret = sca3000_read_data_short(st, SCA3000_REG_REVID_ADDR, 1);
43662306a36Sopenharmony_ci	if (ret < 0)
43762306a36Sopenharmony_ci		goto error_ret;
43862306a36Sopenharmony_ci	dev_info(&indio_dev->dev,
43962306a36Sopenharmony_ci		 "sca3000 revision major=%lu, minor=%lu\n",
44062306a36Sopenharmony_ci		 st->rx[0] & SCA3000_REG_REVID_MAJOR_MASK,
44162306a36Sopenharmony_ci		 st->rx[0] & SCA3000_REG_REVID_MINOR_MASK);
44262306a36Sopenharmony_cierror_ret:
44362306a36Sopenharmony_ci	mutex_unlock(&st->lock);
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci	return ret;
44662306a36Sopenharmony_ci}
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_cistatic ssize_t
44962306a36Sopenharmony_cisca3000_show_available_3db_freqs(struct device *dev,
45062306a36Sopenharmony_ci				 struct device_attribute *attr,
45162306a36Sopenharmony_ci				 char *buf)
45262306a36Sopenharmony_ci{
45362306a36Sopenharmony_ci	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
45462306a36Sopenharmony_ci	struct sca3000_state *st = iio_priv(indio_dev);
45562306a36Sopenharmony_ci	int len;
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci	len = sprintf(buf, "%d", st->info->measurement_mode_3db_freq);
45862306a36Sopenharmony_ci	if (st->info->option_mode_1)
45962306a36Sopenharmony_ci		len += sprintf(buf + len, " %d",
46062306a36Sopenharmony_ci			       st->info->option_mode_1_3db_freq);
46162306a36Sopenharmony_ci	if (st->info->option_mode_2)
46262306a36Sopenharmony_ci		len += sprintf(buf + len, " %d",
46362306a36Sopenharmony_ci			       st->info->option_mode_2_3db_freq);
46462306a36Sopenharmony_ci	len += sprintf(buf + len, "\n");
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	return len;
46762306a36Sopenharmony_ci}
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_cistatic IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available,
47062306a36Sopenharmony_ci		       S_IRUGO, sca3000_show_available_3db_freqs,
47162306a36Sopenharmony_ci		       NULL, 0);
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_cistatic const struct iio_event_spec sca3000_event = {
47462306a36Sopenharmony_ci	.type = IIO_EV_TYPE_MAG,
47562306a36Sopenharmony_ci	.dir = IIO_EV_DIR_RISING,
47662306a36Sopenharmony_ci	.mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE),
47762306a36Sopenharmony_ci};
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci/*
48062306a36Sopenharmony_ci * Note the hack in the number of bits to pretend we have 2 more than
48162306a36Sopenharmony_ci * we do in the fifo.
48262306a36Sopenharmony_ci */
48362306a36Sopenharmony_ci#define SCA3000_CHAN(index, mod)				\
48462306a36Sopenharmony_ci	{							\
48562306a36Sopenharmony_ci		.type = IIO_ACCEL,				\
48662306a36Sopenharmony_ci		.modified = 1,					\
48762306a36Sopenharmony_ci		.channel2 = mod,				\
48862306a36Sopenharmony_ci		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
48962306a36Sopenharmony_ci		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |\
49062306a36Sopenharmony_ci			BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),\
49162306a36Sopenharmony_ci		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
49262306a36Sopenharmony_ci		.address = index,				\
49362306a36Sopenharmony_ci		.scan_index = index,				\
49462306a36Sopenharmony_ci		.scan_type = {					\
49562306a36Sopenharmony_ci			.sign = 's',				\
49662306a36Sopenharmony_ci			.realbits = 13,				\
49762306a36Sopenharmony_ci			.storagebits = 16,			\
49862306a36Sopenharmony_ci			.shift = 3,				\
49962306a36Sopenharmony_ci			.endianness = IIO_BE,			\
50062306a36Sopenharmony_ci		},						\
50162306a36Sopenharmony_ci		.event_spec = &sca3000_event,			\
50262306a36Sopenharmony_ci		.num_event_specs = 1,				\
50362306a36Sopenharmony_ci	}
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_cistatic const struct iio_event_spec sca3000_freefall_event_spec = {
50662306a36Sopenharmony_ci	.type = IIO_EV_TYPE_MAG,
50762306a36Sopenharmony_ci	.dir = IIO_EV_DIR_FALLING,
50862306a36Sopenharmony_ci	.mask_separate = BIT(IIO_EV_INFO_ENABLE) |
50962306a36Sopenharmony_ci		BIT(IIO_EV_INFO_PERIOD),
51062306a36Sopenharmony_ci};
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_cistatic const struct iio_chan_spec sca3000_channels[] = {
51362306a36Sopenharmony_ci	SCA3000_CHAN(0, IIO_MOD_X),
51462306a36Sopenharmony_ci	SCA3000_CHAN(1, IIO_MOD_Y),
51562306a36Sopenharmony_ci	SCA3000_CHAN(2, IIO_MOD_Z),
51662306a36Sopenharmony_ci	{
51762306a36Sopenharmony_ci		.type = IIO_ACCEL,
51862306a36Sopenharmony_ci		.modified = 1,
51962306a36Sopenharmony_ci		.channel2 = IIO_MOD_X_AND_Y_AND_Z,
52062306a36Sopenharmony_ci		.scan_index = -1, /* Fake channel */
52162306a36Sopenharmony_ci		.event_spec = &sca3000_freefall_event_spec,
52262306a36Sopenharmony_ci		.num_event_specs = 1,
52362306a36Sopenharmony_ci	},
52462306a36Sopenharmony_ci};
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_cistatic const struct iio_chan_spec sca3000_channels_with_temp[] = {
52762306a36Sopenharmony_ci	SCA3000_CHAN(0, IIO_MOD_X),
52862306a36Sopenharmony_ci	SCA3000_CHAN(1, IIO_MOD_Y),
52962306a36Sopenharmony_ci	SCA3000_CHAN(2, IIO_MOD_Z),
53062306a36Sopenharmony_ci	{
53162306a36Sopenharmony_ci		.type = IIO_TEMP,
53262306a36Sopenharmony_ci		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
53362306a36Sopenharmony_ci		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
53462306a36Sopenharmony_ci			BIT(IIO_CHAN_INFO_OFFSET),
53562306a36Sopenharmony_ci		/* No buffer support */
53662306a36Sopenharmony_ci		.scan_index = -1,
53762306a36Sopenharmony_ci		.scan_type = {
53862306a36Sopenharmony_ci			.sign = 'u',
53962306a36Sopenharmony_ci			.realbits = 9,
54062306a36Sopenharmony_ci			.storagebits = 16,
54162306a36Sopenharmony_ci			.shift = 5,
54262306a36Sopenharmony_ci			.endianness = IIO_BE,
54362306a36Sopenharmony_ci		},
54462306a36Sopenharmony_ci	},
54562306a36Sopenharmony_ci	{
54662306a36Sopenharmony_ci		.type = IIO_ACCEL,
54762306a36Sopenharmony_ci		.modified = 1,
54862306a36Sopenharmony_ci		.channel2 = IIO_MOD_X_AND_Y_AND_Z,
54962306a36Sopenharmony_ci		.scan_index = -1, /* Fake channel */
55062306a36Sopenharmony_ci		.event_spec = &sca3000_freefall_event_spec,
55162306a36Sopenharmony_ci		.num_event_specs = 1,
55262306a36Sopenharmony_ci	},
55362306a36Sopenharmony_ci};
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_cistatic u8 sca3000_addresses[3][3] = {
55662306a36Sopenharmony_ci	[0] = {SCA3000_REG_X_MSB_ADDR, SCA3000_REG_CTRL_SEL_MD_X_TH,
55762306a36Sopenharmony_ci	       SCA3000_MD_CTRL_OR_X},
55862306a36Sopenharmony_ci	[1] = {SCA3000_REG_Y_MSB_ADDR, SCA3000_REG_CTRL_SEL_MD_Y_TH,
55962306a36Sopenharmony_ci	       SCA3000_MD_CTRL_OR_Y},
56062306a36Sopenharmony_ci	[2] = {SCA3000_REG_Z_MSB_ADDR, SCA3000_REG_CTRL_SEL_MD_Z_TH,
56162306a36Sopenharmony_ci	       SCA3000_MD_CTRL_OR_Z},
56262306a36Sopenharmony_ci};
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci/**
56562306a36Sopenharmony_ci * __sca3000_get_base_freq() - obtain mode specific base frequency
56662306a36Sopenharmony_ci * @st: Private driver specific device instance specific state.
56762306a36Sopenharmony_ci * @info: chip type specific information.
56862306a36Sopenharmony_ci * @base_freq: Base frequency for the current measurement mode.
56962306a36Sopenharmony_ci *
57062306a36Sopenharmony_ci * lock must be held
57162306a36Sopenharmony_ci */
57262306a36Sopenharmony_cistatic inline int __sca3000_get_base_freq(struct sca3000_state *st,
57362306a36Sopenharmony_ci					  const struct sca3000_chip_info *info,
57462306a36Sopenharmony_ci					  int *base_freq)
57562306a36Sopenharmony_ci{
57662306a36Sopenharmony_ci	int ret;
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_ci	ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
57962306a36Sopenharmony_ci	if (ret)
58062306a36Sopenharmony_ci		goto error_ret;
58162306a36Sopenharmony_ci	switch (SCA3000_REG_MODE_MODE_MASK & st->rx[0]) {
58262306a36Sopenharmony_ci	case SCA3000_REG_MODE_MEAS_MODE_NORMAL:
58362306a36Sopenharmony_ci		*base_freq = info->measurement_mode_freq;
58462306a36Sopenharmony_ci		break;
58562306a36Sopenharmony_ci	case SCA3000_REG_MODE_MEAS_MODE_OP_1:
58662306a36Sopenharmony_ci		*base_freq = info->option_mode_1_freq;
58762306a36Sopenharmony_ci		break;
58862306a36Sopenharmony_ci	case SCA3000_REG_MODE_MEAS_MODE_OP_2:
58962306a36Sopenharmony_ci		*base_freq = info->option_mode_2_freq;
59062306a36Sopenharmony_ci		break;
59162306a36Sopenharmony_ci	default:
59262306a36Sopenharmony_ci		ret = -EINVAL;
59362306a36Sopenharmony_ci	}
59462306a36Sopenharmony_cierror_ret:
59562306a36Sopenharmony_ci	return ret;
59662306a36Sopenharmony_ci}
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci/**
59962306a36Sopenharmony_ci * sca3000_read_raw_samp_freq() - read_raw handler for IIO_CHAN_INFO_SAMP_FREQ
60062306a36Sopenharmony_ci * @st: Private driver specific device instance specific state.
60162306a36Sopenharmony_ci * @val: The frequency read back.
60262306a36Sopenharmony_ci *
60362306a36Sopenharmony_ci * lock must be held
60462306a36Sopenharmony_ci **/
60562306a36Sopenharmony_cistatic int sca3000_read_raw_samp_freq(struct sca3000_state *st, int *val)
60662306a36Sopenharmony_ci{
60762306a36Sopenharmony_ci	int ret;
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci	ret = __sca3000_get_base_freq(st, st->info, val);
61062306a36Sopenharmony_ci	if (ret)
61162306a36Sopenharmony_ci		return ret;
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci	ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL);
61462306a36Sopenharmony_ci	if (ret < 0)
61562306a36Sopenharmony_ci		return ret;
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	if (*val > 0) {
61862306a36Sopenharmony_ci		ret &= SCA3000_REG_OUT_CTRL_BUF_DIV_MASK;
61962306a36Sopenharmony_ci		switch (ret) {
62062306a36Sopenharmony_ci		case SCA3000_REG_OUT_CTRL_BUF_DIV_2:
62162306a36Sopenharmony_ci			*val /= 2;
62262306a36Sopenharmony_ci			break;
62362306a36Sopenharmony_ci		case SCA3000_REG_OUT_CTRL_BUF_DIV_4:
62462306a36Sopenharmony_ci			*val /= 4;
62562306a36Sopenharmony_ci			break;
62662306a36Sopenharmony_ci		}
62762306a36Sopenharmony_ci	}
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci	return 0;
63062306a36Sopenharmony_ci}
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci/**
63362306a36Sopenharmony_ci * sca3000_write_raw_samp_freq() - write_raw handler for IIO_CHAN_INFO_SAMP_FREQ
63462306a36Sopenharmony_ci * @st: Private driver specific device instance specific state.
63562306a36Sopenharmony_ci * @val: The frequency desired.
63662306a36Sopenharmony_ci *
63762306a36Sopenharmony_ci * lock must be held
63862306a36Sopenharmony_ci */
63962306a36Sopenharmony_cistatic int sca3000_write_raw_samp_freq(struct sca3000_state *st, int val)
64062306a36Sopenharmony_ci{
64162306a36Sopenharmony_ci	int ret, base_freq, ctrlval;
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci	ret = __sca3000_get_base_freq(st, st->info, &base_freq);
64462306a36Sopenharmony_ci	if (ret)
64562306a36Sopenharmony_ci		return ret;
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci	ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL);
64862306a36Sopenharmony_ci	if (ret < 0)
64962306a36Sopenharmony_ci		return ret;
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci	ctrlval = ret & ~SCA3000_REG_OUT_CTRL_BUF_DIV_MASK;
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	if (val == base_freq / 2)
65462306a36Sopenharmony_ci		ctrlval |= SCA3000_REG_OUT_CTRL_BUF_DIV_2;
65562306a36Sopenharmony_ci	if (val == base_freq / 4)
65662306a36Sopenharmony_ci		ctrlval |= SCA3000_REG_OUT_CTRL_BUF_DIV_4;
65762306a36Sopenharmony_ci	else if (val != base_freq)
65862306a36Sopenharmony_ci		return -EINVAL;
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci	return sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL,
66162306a36Sopenharmony_ci				     ctrlval);
66262306a36Sopenharmony_ci}
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_cistatic int sca3000_read_3db_freq(struct sca3000_state *st, int *val)
66562306a36Sopenharmony_ci{
66662306a36Sopenharmony_ci	int ret;
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci	ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
66962306a36Sopenharmony_ci	if (ret)
67062306a36Sopenharmony_ci		return ret;
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci	/* mask bottom 2 bits - only ones that are relevant */
67362306a36Sopenharmony_ci	st->rx[0] &= SCA3000_REG_MODE_MODE_MASK;
67462306a36Sopenharmony_ci	switch (st->rx[0]) {
67562306a36Sopenharmony_ci	case SCA3000_REG_MODE_MEAS_MODE_NORMAL:
67662306a36Sopenharmony_ci		*val = st->info->measurement_mode_3db_freq;
67762306a36Sopenharmony_ci		return IIO_VAL_INT;
67862306a36Sopenharmony_ci	case SCA3000_REG_MODE_MEAS_MODE_MOT_DET:
67962306a36Sopenharmony_ci		return -EBUSY;
68062306a36Sopenharmony_ci	case SCA3000_REG_MODE_MEAS_MODE_OP_1:
68162306a36Sopenharmony_ci		*val = st->info->option_mode_1_3db_freq;
68262306a36Sopenharmony_ci		return IIO_VAL_INT;
68362306a36Sopenharmony_ci	case SCA3000_REG_MODE_MEAS_MODE_OP_2:
68462306a36Sopenharmony_ci		*val = st->info->option_mode_2_3db_freq;
68562306a36Sopenharmony_ci		return IIO_VAL_INT;
68662306a36Sopenharmony_ci	default:
68762306a36Sopenharmony_ci		return -EINVAL;
68862306a36Sopenharmony_ci	}
68962306a36Sopenharmony_ci}
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_cistatic int sca3000_write_3db_freq(struct sca3000_state *st, int val)
69262306a36Sopenharmony_ci{
69362306a36Sopenharmony_ci	int ret;
69462306a36Sopenharmony_ci	int mode;
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci	if (val == st->info->measurement_mode_3db_freq)
69762306a36Sopenharmony_ci		mode = SCA3000_REG_MODE_MEAS_MODE_NORMAL;
69862306a36Sopenharmony_ci	else if (st->info->option_mode_1 &&
69962306a36Sopenharmony_ci		 (val == st->info->option_mode_1_3db_freq))
70062306a36Sopenharmony_ci		mode = SCA3000_REG_MODE_MEAS_MODE_OP_1;
70162306a36Sopenharmony_ci	else if (st->info->option_mode_2 &&
70262306a36Sopenharmony_ci		 (val == st->info->option_mode_2_3db_freq))
70362306a36Sopenharmony_ci		mode = SCA3000_REG_MODE_MEAS_MODE_OP_2;
70462306a36Sopenharmony_ci	else
70562306a36Sopenharmony_ci		return -EINVAL;
70662306a36Sopenharmony_ci	ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
70762306a36Sopenharmony_ci	if (ret)
70862306a36Sopenharmony_ci		return ret;
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_ci	st->rx[0] &= ~SCA3000_REG_MODE_MODE_MASK;
71162306a36Sopenharmony_ci	st->rx[0] |= (mode & SCA3000_REG_MODE_MODE_MASK);
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci	return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, st->rx[0]);
71462306a36Sopenharmony_ci}
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_cistatic int sca3000_read_raw(struct iio_dev *indio_dev,
71762306a36Sopenharmony_ci			    struct iio_chan_spec const *chan,
71862306a36Sopenharmony_ci			    int *val,
71962306a36Sopenharmony_ci			    int *val2,
72062306a36Sopenharmony_ci			    long mask)
72162306a36Sopenharmony_ci{
72262306a36Sopenharmony_ci	struct sca3000_state *st = iio_priv(indio_dev);
72362306a36Sopenharmony_ci	int ret;
72462306a36Sopenharmony_ci	u8 address;
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci	switch (mask) {
72762306a36Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
72862306a36Sopenharmony_ci		mutex_lock(&st->lock);
72962306a36Sopenharmony_ci		if (chan->type == IIO_ACCEL) {
73062306a36Sopenharmony_ci			if (st->mo_det_use_count) {
73162306a36Sopenharmony_ci				mutex_unlock(&st->lock);
73262306a36Sopenharmony_ci				return -EBUSY;
73362306a36Sopenharmony_ci			}
73462306a36Sopenharmony_ci			address = sca3000_addresses[chan->address][0];
73562306a36Sopenharmony_ci			ret = sca3000_read_data_short(st, address, 2);
73662306a36Sopenharmony_ci			if (ret < 0) {
73762306a36Sopenharmony_ci				mutex_unlock(&st->lock);
73862306a36Sopenharmony_ci				return ret;
73962306a36Sopenharmony_ci			}
74062306a36Sopenharmony_ci			*val = sign_extend32(be16_to_cpup((__be16 *)st->rx) >>
74162306a36Sopenharmony_ci					     chan->scan_type.shift,
74262306a36Sopenharmony_ci					     chan->scan_type.realbits - 1);
74362306a36Sopenharmony_ci		} else {
74462306a36Sopenharmony_ci			/* get the temperature when available */
74562306a36Sopenharmony_ci			ret = sca3000_read_data_short(st,
74662306a36Sopenharmony_ci						      SCA3000_REG_TEMP_MSB_ADDR,
74762306a36Sopenharmony_ci						      2);
74862306a36Sopenharmony_ci			if (ret < 0) {
74962306a36Sopenharmony_ci				mutex_unlock(&st->lock);
75062306a36Sopenharmony_ci				return ret;
75162306a36Sopenharmony_ci			}
75262306a36Sopenharmony_ci			*val = (be16_to_cpup((__be16 *)st->rx) >>
75362306a36Sopenharmony_ci				chan->scan_type.shift) &
75462306a36Sopenharmony_ci				GENMASK(chan->scan_type.realbits - 1, 0);
75562306a36Sopenharmony_ci		}
75662306a36Sopenharmony_ci		mutex_unlock(&st->lock);
75762306a36Sopenharmony_ci		return IIO_VAL_INT;
75862306a36Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
75962306a36Sopenharmony_ci		*val = 0;
76062306a36Sopenharmony_ci		if (chan->type == IIO_ACCEL)
76162306a36Sopenharmony_ci			*val2 = st->info->scale;
76262306a36Sopenharmony_ci		else /* temperature */
76362306a36Sopenharmony_ci			*val2 = 555556;
76462306a36Sopenharmony_ci		return IIO_VAL_INT_PLUS_MICRO;
76562306a36Sopenharmony_ci	case IIO_CHAN_INFO_OFFSET:
76662306a36Sopenharmony_ci		*val = -214;
76762306a36Sopenharmony_ci		*val2 = 600000;
76862306a36Sopenharmony_ci		return IIO_VAL_INT_PLUS_MICRO;
76962306a36Sopenharmony_ci	case IIO_CHAN_INFO_SAMP_FREQ:
77062306a36Sopenharmony_ci		mutex_lock(&st->lock);
77162306a36Sopenharmony_ci		ret = sca3000_read_raw_samp_freq(st, val);
77262306a36Sopenharmony_ci		mutex_unlock(&st->lock);
77362306a36Sopenharmony_ci		return ret ? ret : IIO_VAL_INT;
77462306a36Sopenharmony_ci	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
77562306a36Sopenharmony_ci		mutex_lock(&st->lock);
77662306a36Sopenharmony_ci		ret = sca3000_read_3db_freq(st, val);
77762306a36Sopenharmony_ci		mutex_unlock(&st->lock);
77862306a36Sopenharmony_ci		return ret;
77962306a36Sopenharmony_ci	default:
78062306a36Sopenharmony_ci		return -EINVAL;
78162306a36Sopenharmony_ci	}
78262306a36Sopenharmony_ci}
78362306a36Sopenharmony_ci
78462306a36Sopenharmony_cistatic int sca3000_write_raw(struct iio_dev *indio_dev,
78562306a36Sopenharmony_ci			     struct iio_chan_spec const *chan,
78662306a36Sopenharmony_ci			     int val, int val2, long mask)
78762306a36Sopenharmony_ci{
78862306a36Sopenharmony_ci	struct sca3000_state *st = iio_priv(indio_dev);
78962306a36Sopenharmony_ci	int ret;
79062306a36Sopenharmony_ci
79162306a36Sopenharmony_ci	switch (mask) {
79262306a36Sopenharmony_ci	case IIO_CHAN_INFO_SAMP_FREQ:
79362306a36Sopenharmony_ci		if (val2)
79462306a36Sopenharmony_ci			return -EINVAL;
79562306a36Sopenharmony_ci		mutex_lock(&st->lock);
79662306a36Sopenharmony_ci		ret = sca3000_write_raw_samp_freq(st, val);
79762306a36Sopenharmony_ci		mutex_unlock(&st->lock);
79862306a36Sopenharmony_ci		return ret;
79962306a36Sopenharmony_ci	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
80062306a36Sopenharmony_ci		if (val2)
80162306a36Sopenharmony_ci			return -EINVAL;
80262306a36Sopenharmony_ci		mutex_lock(&st->lock);
80362306a36Sopenharmony_ci		ret = sca3000_write_3db_freq(st, val);
80462306a36Sopenharmony_ci		mutex_unlock(&st->lock);
80562306a36Sopenharmony_ci		return ret;
80662306a36Sopenharmony_ci	default:
80762306a36Sopenharmony_ci		return -EINVAL;
80862306a36Sopenharmony_ci	}
80962306a36Sopenharmony_ci
81062306a36Sopenharmony_ci	return ret;
81162306a36Sopenharmony_ci}
81262306a36Sopenharmony_ci
81362306a36Sopenharmony_ci/**
81462306a36Sopenharmony_ci * sca3000_read_av_freq() - sysfs function to get available frequencies
81562306a36Sopenharmony_ci * @dev: Device structure for this device.
81662306a36Sopenharmony_ci * @attr: Description of the attribute.
81762306a36Sopenharmony_ci * @buf: Incoming string
81862306a36Sopenharmony_ci *
81962306a36Sopenharmony_ci * The later modes are only relevant to the ring buffer - and depend on current
82062306a36Sopenharmony_ci * mode. Note that data sheet gives rather wide tolerances for these so integer
82162306a36Sopenharmony_ci * division will give good enough answer and not all chips have them specified
82262306a36Sopenharmony_ci * at all.
82362306a36Sopenharmony_ci **/
82462306a36Sopenharmony_cistatic ssize_t sca3000_read_av_freq(struct device *dev,
82562306a36Sopenharmony_ci				    struct device_attribute *attr,
82662306a36Sopenharmony_ci				    char *buf)
82762306a36Sopenharmony_ci{
82862306a36Sopenharmony_ci	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
82962306a36Sopenharmony_ci	struct sca3000_state *st = iio_priv(indio_dev);
83062306a36Sopenharmony_ci	int len = 0, ret, val;
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci	mutex_lock(&st->lock);
83362306a36Sopenharmony_ci	ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
83462306a36Sopenharmony_ci	val = st->rx[0];
83562306a36Sopenharmony_ci	mutex_unlock(&st->lock);
83662306a36Sopenharmony_ci	if (ret)
83762306a36Sopenharmony_ci		goto error_ret;
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci	switch (val & SCA3000_REG_MODE_MODE_MASK) {
84062306a36Sopenharmony_ci	case SCA3000_REG_MODE_MEAS_MODE_NORMAL:
84162306a36Sopenharmony_ci		len += sprintf(buf + len, "%d %d %d\n",
84262306a36Sopenharmony_ci			       st->info->measurement_mode_freq,
84362306a36Sopenharmony_ci			       st->info->measurement_mode_freq / 2,
84462306a36Sopenharmony_ci			       st->info->measurement_mode_freq / 4);
84562306a36Sopenharmony_ci		break;
84662306a36Sopenharmony_ci	case SCA3000_REG_MODE_MEAS_MODE_OP_1:
84762306a36Sopenharmony_ci		len += sprintf(buf + len, "%d %d %d\n",
84862306a36Sopenharmony_ci			       st->info->option_mode_1_freq,
84962306a36Sopenharmony_ci			       st->info->option_mode_1_freq / 2,
85062306a36Sopenharmony_ci			       st->info->option_mode_1_freq / 4);
85162306a36Sopenharmony_ci		break;
85262306a36Sopenharmony_ci	case SCA3000_REG_MODE_MEAS_MODE_OP_2:
85362306a36Sopenharmony_ci		len += sprintf(buf + len, "%d %d %d\n",
85462306a36Sopenharmony_ci			       st->info->option_mode_2_freq,
85562306a36Sopenharmony_ci			       st->info->option_mode_2_freq / 2,
85662306a36Sopenharmony_ci			       st->info->option_mode_2_freq / 4);
85762306a36Sopenharmony_ci		break;
85862306a36Sopenharmony_ci	}
85962306a36Sopenharmony_ci	return len;
86062306a36Sopenharmony_cierror_ret:
86162306a36Sopenharmony_ci	return ret;
86262306a36Sopenharmony_ci}
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_ci/*
86562306a36Sopenharmony_ci * Should only really be registered if ring buffer support is compiled in.
86662306a36Sopenharmony_ci * Does no harm however and doing it right would add a fair bit of complexity
86762306a36Sopenharmony_ci */
86862306a36Sopenharmony_cistatic IIO_DEV_ATTR_SAMP_FREQ_AVAIL(sca3000_read_av_freq);
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_ci/*
87162306a36Sopenharmony_ci * sca3000_read_event_value() - query of a threshold or period
87262306a36Sopenharmony_ci */
87362306a36Sopenharmony_cistatic int sca3000_read_event_value(struct iio_dev *indio_dev,
87462306a36Sopenharmony_ci				    const struct iio_chan_spec *chan,
87562306a36Sopenharmony_ci				    enum iio_event_type type,
87662306a36Sopenharmony_ci				    enum iio_event_direction dir,
87762306a36Sopenharmony_ci				    enum iio_event_info info,
87862306a36Sopenharmony_ci				    int *val, int *val2)
87962306a36Sopenharmony_ci{
88062306a36Sopenharmony_ci	struct sca3000_state *st = iio_priv(indio_dev);
88162306a36Sopenharmony_ci	long ret;
88262306a36Sopenharmony_ci	int i;
88362306a36Sopenharmony_ci
88462306a36Sopenharmony_ci	switch (info) {
88562306a36Sopenharmony_ci	case IIO_EV_INFO_VALUE:
88662306a36Sopenharmony_ci		mutex_lock(&st->lock);
88762306a36Sopenharmony_ci		ret = sca3000_read_ctrl_reg(st,
88862306a36Sopenharmony_ci					    sca3000_addresses[chan->address][1]);
88962306a36Sopenharmony_ci		mutex_unlock(&st->lock);
89062306a36Sopenharmony_ci		if (ret < 0)
89162306a36Sopenharmony_ci			return ret;
89262306a36Sopenharmony_ci		*val = 0;
89362306a36Sopenharmony_ci		if (chan->channel2 == IIO_MOD_Y)
89462306a36Sopenharmony_ci			for_each_set_bit(i, &ret,
89562306a36Sopenharmony_ci					 ARRAY_SIZE(st->info->mot_det_mult_y))
89662306a36Sopenharmony_ci				*val += st->info->mot_det_mult_y[i];
89762306a36Sopenharmony_ci		else
89862306a36Sopenharmony_ci			for_each_set_bit(i, &ret,
89962306a36Sopenharmony_ci					 ARRAY_SIZE(st->info->mot_det_mult_xz))
90062306a36Sopenharmony_ci				*val += st->info->mot_det_mult_xz[i];
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_ci		return IIO_VAL_INT;
90362306a36Sopenharmony_ci	case IIO_EV_INFO_PERIOD:
90462306a36Sopenharmony_ci		*val = 0;
90562306a36Sopenharmony_ci		*val2 = 226000;
90662306a36Sopenharmony_ci		return IIO_VAL_INT_PLUS_MICRO;
90762306a36Sopenharmony_ci	default:
90862306a36Sopenharmony_ci		return -EINVAL;
90962306a36Sopenharmony_ci	}
91062306a36Sopenharmony_ci}
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci/**
91362306a36Sopenharmony_ci * sca3000_write_event_value() - control of threshold and period
91462306a36Sopenharmony_ci * @indio_dev: Device instance specific IIO information.
91562306a36Sopenharmony_ci * @chan: Description of the channel for which the event is being
91662306a36Sopenharmony_ci * configured.
91762306a36Sopenharmony_ci * @type: The type of event being configured, here magnitude rising
91862306a36Sopenharmony_ci * as everything else is read only.
91962306a36Sopenharmony_ci * @dir: Direction of the event (here rising)
92062306a36Sopenharmony_ci * @info: What information about the event are we configuring.
92162306a36Sopenharmony_ci * Here the threshold only.
92262306a36Sopenharmony_ci * @val: Integer part of the value being written..
92362306a36Sopenharmony_ci * @val2: Non integer part of the value being written. Here always 0.
92462306a36Sopenharmony_ci */
92562306a36Sopenharmony_cistatic int sca3000_write_event_value(struct iio_dev *indio_dev,
92662306a36Sopenharmony_ci				     const struct iio_chan_spec *chan,
92762306a36Sopenharmony_ci				     enum iio_event_type type,
92862306a36Sopenharmony_ci				     enum iio_event_direction dir,
92962306a36Sopenharmony_ci				     enum iio_event_info info,
93062306a36Sopenharmony_ci				     int val, int val2)
93162306a36Sopenharmony_ci{
93262306a36Sopenharmony_ci	struct sca3000_state *st = iio_priv(indio_dev);
93362306a36Sopenharmony_ci	int ret;
93462306a36Sopenharmony_ci	int i;
93562306a36Sopenharmony_ci	u8 nonlinear = 0;
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_ci	if (chan->channel2 == IIO_MOD_Y) {
93862306a36Sopenharmony_ci		i = ARRAY_SIZE(st->info->mot_det_mult_y);
93962306a36Sopenharmony_ci		while (i > 0)
94062306a36Sopenharmony_ci			if (val >= st->info->mot_det_mult_y[--i]) {
94162306a36Sopenharmony_ci				nonlinear |= (1 << i);
94262306a36Sopenharmony_ci				val -= st->info->mot_det_mult_y[i];
94362306a36Sopenharmony_ci			}
94462306a36Sopenharmony_ci	} else {
94562306a36Sopenharmony_ci		i = ARRAY_SIZE(st->info->mot_det_mult_xz);
94662306a36Sopenharmony_ci		while (i > 0)
94762306a36Sopenharmony_ci			if (val >= st->info->mot_det_mult_xz[--i]) {
94862306a36Sopenharmony_ci				nonlinear |= (1 << i);
94962306a36Sopenharmony_ci				val -= st->info->mot_det_mult_xz[i];
95062306a36Sopenharmony_ci			}
95162306a36Sopenharmony_ci	}
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci	mutex_lock(&st->lock);
95462306a36Sopenharmony_ci	ret = sca3000_write_ctrl_reg(st,
95562306a36Sopenharmony_ci				     sca3000_addresses[chan->address][1],
95662306a36Sopenharmony_ci				     nonlinear);
95762306a36Sopenharmony_ci	mutex_unlock(&st->lock);
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_ci	return ret;
96062306a36Sopenharmony_ci}
96162306a36Sopenharmony_ci
96262306a36Sopenharmony_cistatic struct attribute *sca3000_attributes[] = {
96362306a36Sopenharmony_ci	&iio_dev_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr,
96462306a36Sopenharmony_ci	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
96562306a36Sopenharmony_ci	NULL,
96662306a36Sopenharmony_ci};
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_cistatic const struct attribute_group sca3000_attribute_group = {
96962306a36Sopenharmony_ci	.attrs = sca3000_attributes,
97062306a36Sopenharmony_ci};
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_cistatic int sca3000_read_data(struct sca3000_state *st,
97362306a36Sopenharmony_ci			     u8 reg_address_high,
97462306a36Sopenharmony_ci			     u8 *rx,
97562306a36Sopenharmony_ci			     int len)
97662306a36Sopenharmony_ci{
97762306a36Sopenharmony_ci	int ret;
97862306a36Sopenharmony_ci	struct spi_transfer xfer[2] = {
97962306a36Sopenharmony_ci		{
98062306a36Sopenharmony_ci			.len = 1,
98162306a36Sopenharmony_ci			.tx_buf = st->tx,
98262306a36Sopenharmony_ci		}, {
98362306a36Sopenharmony_ci			.len = len,
98462306a36Sopenharmony_ci			.rx_buf = rx,
98562306a36Sopenharmony_ci		}
98662306a36Sopenharmony_ci	};
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci	st->tx[0] = SCA3000_READ_REG(reg_address_high);
98962306a36Sopenharmony_ci	ret = spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer));
99062306a36Sopenharmony_ci	if (ret) {
99162306a36Sopenharmony_ci		dev_err(&st->us->dev, "problem reading register\n");
99262306a36Sopenharmony_ci		return ret;
99362306a36Sopenharmony_ci	}
99462306a36Sopenharmony_ci
99562306a36Sopenharmony_ci	return 0;
99662306a36Sopenharmony_ci}
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_ci/**
99962306a36Sopenharmony_ci * sca3000_ring_int_process() - ring specific interrupt handling.
100062306a36Sopenharmony_ci * @val: Value of the interrupt status register.
100162306a36Sopenharmony_ci * @indio_dev: Device instance specific IIO device structure.
100262306a36Sopenharmony_ci */
100362306a36Sopenharmony_cistatic void sca3000_ring_int_process(u8 val, struct iio_dev *indio_dev)
100462306a36Sopenharmony_ci{
100562306a36Sopenharmony_ci	struct sca3000_state *st = iio_priv(indio_dev);
100662306a36Sopenharmony_ci	int ret, i, num_available;
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ci	mutex_lock(&st->lock);
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	if (val & SCA3000_REG_INT_STATUS_HALF) {
101162306a36Sopenharmony_ci		ret = sca3000_read_data_short(st, SCA3000_REG_BUF_COUNT_ADDR,
101262306a36Sopenharmony_ci					      1);
101362306a36Sopenharmony_ci		if (ret)
101462306a36Sopenharmony_ci			goto error_ret;
101562306a36Sopenharmony_ci		num_available = st->rx[0];
101662306a36Sopenharmony_ci		/*
101762306a36Sopenharmony_ci		 * num_available is the total number of samples available
101862306a36Sopenharmony_ci		 * i.e. number of time points * number of channels.
101962306a36Sopenharmony_ci		 */
102062306a36Sopenharmony_ci		ret = sca3000_read_data(st, SCA3000_REG_RING_OUT_ADDR, st->rx,
102162306a36Sopenharmony_ci					num_available * 2);
102262306a36Sopenharmony_ci		if (ret)
102362306a36Sopenharmony_ci			goto error_ret;
102462306a36Sopenharmony_ci		for (i = 0; i < num_available / 3; i++) {
102562306a36Sopenharmony_ci			/*
102662306a36Sopenharmony_ci			 * Dirty hack to cover for 11 bit in fifo, 13 bit
102762306a36Sopenharmony_ci			 * direct reading.
102862306a36Sopenharmony_ci			 *
102962306a36Sopenharmony_ci			 * In theory the bottom two bits are undefined.
103062306a36Sopenharmony_ci			 * In reality they appear to always be 0.
103162306a36Sopenharmony_ci			 */
103262306a36Sopenharmony_ci			iio_push_to_buffers(indio_dev, st->rx + i * 3 * 2);
103362306a36Sopenharmony_ci		}
103462306a36Sopenharmony_ci	}
103562306a36Sopenharmony_cierror_ret:
103662306a36Sopenharmony_ci	mutex_unlock(&st->lock);
103762306a36Sopenharmony_ci}
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci/**
104062306a36Sopenharmony_ci * sca3000_event_handler() - handling ring and non ring events
104162306a36Sopenharmony_ci * @irq: The irq being handled.
104262306a36Sopenharmony_ci * @private: struct iio_device pointer for the device.
104362306a36Sopenharmony_ci *
104462306a36Sopenharmony_ci * Ring related interrupt handler. Depending on event, push to
104562306a36Sopenharmony_ci * the ring buffer event chrdev or the event one.
104662306a36Sopenharmony_ci *
104762306a36Sopenharmony_ci * This function is complicated by the fact that the devices can signify ring
104862306a36Sopenharmony_ci * and non ring events via the same interrupt line and they can only
104962306a36Sopenharmony_ci * be distinguished via a read of the relevant status register.
105062306a36Sopenharmony_ci */
105162306a36Sopenharmony_cistatic irqreturn_t sca3000_event_handler(int irq, void *private)
105262306a36Sopenharmony_ci{
105362306a36Sopenharmony_ci	struct iio_dev *indio_dev = private;
105462306a36Sopenharmony_ci	struct sca3000_state *st = iio_priv(indio_dev);
105562306a36Sopenharmony_ci	int ret, val;
105662306a36Sopenharmony_ci	s64 last_timestamp = iio_get_time_ns(indio_dev);
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_ci	/*
105962306a36Sopenharmony_ci	 * Could lead if badly timed to an extra read of status reg,
106062306a36Sopenharmony_ci	 * but ensures no interrupt is missed.
106162306a36Sopenharmony_ci	 */
106262306a36Sopenharmony_ci	mutex_lock(&st->lock);
106362306a36Sopenharmony_ci	ret = sca3000_read_data_short(st, SCA3000_REG_INT_STATUS_ADDR, 1);
106462306a36Sopenharmony_ci	val = st->rx[0];
106562306a36Sopenharmony_ci	mutex_unlock(&st->lock);
106662306a36Sopenharmony_ci	if (ret)
106762306a36Sopenharmony_ci		goto done;
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_ci	sca3000_ring_int_process(val, indio_dev);
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci	if (val & SCA3000_INT_STATUS_FREE_FALL)
107262306a36Sopenharmony_ci		iio_push_event(indio_dev,
107362306a36Sopenharmony_ci			       IIO_MOD_EVENT_CODE(IIO_ACCEL,
107462306a36Sopenharmony_ci						  0,
107562306a36Sopenharmony_ci						  IIO_MOD_X_AND_Y_AND_Z,
107662306a36Sopenharmony_ci						  IIO_EV_TYPE_MAG,
107762306a36Sopenharmony_ci						  IIO_EV_DIR_FALLING),
107862306a36Sopenharmony_ci			       last_timestamp);
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci	if (val & SCA3000_INT_STATUS_Y_TRIGGER)
108162306a36Sopenharmony_ci		iio_push_event(indio_dev,
108262306a36Sopenharmony_ci			       IIO_MOD_EVENT_CODE(IIO_ACCEL,
108362306a36Sopenharmony_ci						  0,
108462306a36Sopenharmony_ci						  IIO_MOD_Y,
108562306a36Sopenharmony_ci						  IIO_EV_TYPE_MAG,
108662306a36Sopenharmony_ci						  IIO_EV_DIR_RISING),
108762306a36Sopenharmony_ci			       last_timestamp);
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_ci	if (val & SCA3000_INT_STATUS_X_TRIGGER)
109062306a36Sopenharmony_ci		iio_push_event(indio_dev,
109162306a36Sopenharmony_ci			       IIO_MOD_EVENT_CODE(IIO_ACCEL,
109262306a36Sopenharmony_ci						  0,
109362306a36Sopenharmony_ci						  IIO_MOD_X,
109462306a36Sopenharmony_ci						  IIO_EV_TYPE_MAG,
109562306a36Sopenharmony_ci						  IIO_EV_DIR_RISING),
109662306a36Sopenharmony_ci			       last_timestamp);
109762306a36Sopenharmony_ci
109862306a36Sopenharmony_ci	if (val & SCA3000_INT_STATUS_Z_TRIGGER)
109962306a36Sopenharmony_ci		iio_push_event(indio_dev,
110062306a36Sopenharmony_ci			       IIO_MOD_EVENT_CODE(IIO_ACCEL,
110162306a36Sopenharmony_ci						  0,
110262306a36Sopenharmony_ci						  IIO_MOD_Z,
110362306a36Sopenharmony_ci						  IIO_EV_TYPE_MAG,
110462306a36Sopenharmony_ci						  IIO_EV_DIR_RISING),
110562306a36Sopenharmony_ci			       last_timestamp);
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_cidone:
110862306a36Sopenharmony_ci	return IRQ_HANDLED;
110962306a36Sopenharmony_ci}
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ci/*
111262306a36Sopenharmony_ci * sca3000_read_event_config() what events are enabled
111362306a36Sopenharmony_ci */
111462306a36Sopenharmony_cistatic int sca3000_read_event_config(struct iio_dev *indio_dev,
111562306a36Sopenharmony_ci				     const struct iio_chan_spec *chan,
111662306a36Sopenharmony_ci				     enum iio_event_type type,
111762306a36Sopenharmony_ci				     enum iio_event_direction dir)
111862306a36Sopenharmony_ci{
111962306a36Sopenharmony_ci	struct sca3000_state *st = iio_priv(indio_dev);
112062306a36Sopenharmony_ci	int ret;
112162306a36Sopenharmony_ci	/* read current value of mode register */
112262306a36Sopenharmony_ci	mutex_lock(&st->lock);
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci	ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
112562306a36Sopenharmony_ci	if (ret)
112662306a36Sopenharmony_ci		goto error_ret;
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	switch (chan->channel2) {
112962306a36Sopenharmony_ci	case IIO_MOD_X_AND_Y_AND_Z:
113062306a36Sopenharmony_ci		ret = !!(st->rx[0] & SCA3000_REG_MODE_FREE_FALL_DETECT);
113162306a36Sopenharmony_ci		break;
113262306a36Sopenharmony_ci	case IIO_MOD_X:
113362306a36Sopenharmony_ci	case IIO_MOD_Y:
113462306a36Sopenharmony_ci	case IIO_MOD_Z:
113562306a36Sopenharmony_ci		/*
113662306a36Sopenharmony_ci		 * Motion detection mode cannot run at the same time as
113762306a36Sopenharmony_ci		 * acceleration data being read.
113862306a36Sopenharmony_ci		 */
113962306a36Sopenharmony_ci		if ((st->rx[0] & SCA3000_REG_MODE_MODE_MASK)
114062306a36Sopenharmony_ci		    != SCA3000_REG_MODE_MEAS_MODE_MOT_DET) {
114162306a36Sopenharmony_ci			ret = 0;
114262306a36Sopenharmony_ci		} else {
114362306a36Sopenharmony_ci			ret = sca3000_read_ctrl_reg(st,
114462306a36Sopenharmony_ci						SCA3000_REG_CTRL_SEL_MD_CTRL);
114562306a36Sopenharmony_ci			if (ret < 0)
114662306a36Sopenharmony_ci				goto error_ret;
114762306a36Sopenharmony_ci			/* only supporting logical or's for now */
114862306a36Sopenharmony_ci			ret = !!(ret & sca3000_addresses[chan->address][2]);
114962306a36Sopenharmony_ci		}
115062306a36Sopenharmony_ci		break;
115162306a36Sopenharmony_ci	default:
115262306a36Sopenharmony_ci		ret = -EINVAL;
115362306a36Sopenharmony_ci	}
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_cierror_ret:
115662306a36Sopenharmony_ci	mutex_unlock(&st->lock);
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci	return ret;
115962306a36Sopenharmony_ci}
116062306a36Sopenharmony_ci
116162306a36Sopenharmony_cistatic int sca3000_freefall_set_state(struct iio_dev *indio_dev, int state)
116262306a36Sopenharmony_ci{
116362306a36Sopenharmony_ci	struct sca3000_state *st = iio_priv(indio_dev);
116462306a36Sopenharmony_ci	int ret;
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_ci	/* read current value of mode register */
116762306a36Sopenharmony_ci	ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
116862306a36Sopenharmony_ci	if (ret)
116962306a36Sopenharmony_ci		return ret;
117062306a36Sopenharmony_ci
117162306a36Sopenharmony_ci	/* if off and should be on */
117262306a36Sopenharmony_ci	if (state && !(st->rx[0] & SCA3000_REG_MODE_FREE_FALL_DETECT))
117362306a36Sopenharmony_ci		return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR,
117462306a36Sopenharmony_ci					 st->rx[0] | SCA3000_REG_MODE_FREE_FALL_DETECT);
117562306a36Sopenharmony_ci	/* if on and should be off */
117662306a36Sopenharmony_ci	else if (!state && (st->rx[0] & SCA3000_REG_MODE_FREE_FALL_DETECT))
117762306a36Sopenharmony_ci		return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR,
117862306a36Sopenharmony_ci					 st->rx[0] & ~SCA3000_REG_MODE_FREE_FALL_DETECT);
117962306a36Sopenharmony_ci	else
118062306a36Sopenharmony_ci		return 0;
118162306a36Sopenharmony_ci}
118262306a36Sopenharmony_ci
118362306a36Sopenharmony_cistatic int sca3000_motion_detect_set_state(struct iio_dev *indio_dev, int axis,
118462306a36Sopenharmony_ci					   int state)
118562306a36Sopenharmony_ci{
118662306a36Sopenharmony_ci	struct sca3000_state *st = iio_priv(indio_dev);
118762306a36Sopenharmony_ci	int ret, ctrlval;
118862306a36Sopenharmony_ci
118962306a36Sopenharmony_ci	/*
119062306a36Sopenharmony_ci	 * First read the motion detector config to find out if
119162306a36Sopenharmony_ci	 * this axis is on
119262306a36Sopenharmony_ci	 */
119362306a36Sopenharmony_ci	ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL);
119462306a36Sopenharmony_ci	if (ret < 0)
119562306a36Sopenharmony_ci		return ret;
119662306a36Sopenharmony_ci	ctrlval = ret;
119762306a36Sopenharmony_ci	/* if off and should be on */
119862306a36Sopenharmony_ci	if (state && !(ctrlval & sca3000_addresses[axis][2])) {
119962306a36Sopenharmony_ci		ret = sca3000_write_ctrl_reg(st,
120062306a36Sopenharmony_ci					     SCA3000_REG_CTRL_SEL_MD_CTRL,
120162306a36Sopenharmony_ci					     ctrlval |
120262306a36Sopenharmony_ci					     sca3000_addresses[axis][2]);
120362306a36Sopenharmony_ci		if (ret)
120462306a36Sopenharmony_ci			return ret;
120562306a36Sopenharmony_ci		st->mo_det_use_count++;
120662306a36Sopenharmony_ci	} else if (!state && (ctrlval & sca3000_addresses[axis][2])) {
120762306a36Sopenharmony_ci		ret = sca3000_write_ctrl_reg(st,
120862306a36Sopenharmony_ci					     SCA3000_REG_CTRL_SEL_MD_CTRL,
120962306a36Sopenharmony_ci					     ctrlval &
121062306a36Sopenharmony_ci					     ~(sca3000_addresses[axis][2]));
121162306a36Sopenharmony_ci		if (ret)
121262306a36Sopenharmony_ci			return ret;
121362306a36Sopenharmony_ci		st->mo_det_use_count--;
121462306a36Sopenharmony_ci	}
121562306a36Sopenharmony_ci
121662306a36Sopenharmony_ci	/* read current value of mode register */
121762306a36Sopenharmony_ci	ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
121862306a36Sopenharmony_ci	if (ret)
121962306a36Sopenharmony_ci		return ret;
122062306a36Sopenharmony_ci	/* if off and should be on */
122162306a36Sopenharmony_ci	if ((st->mo_det_use_count) &&
122262306a36Sopenharmony_ci	    ((st->rx[0] & SCA3000_REG_MODE_MODE_MASK)
122362306a36Sopenharmony_ci	     != SCA3000_REG_MODE_MEAS_MODE_MOT_DET))
122462306a36Sopenharmony_ci		return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR,
122562306a36Sopenharmony_ci			(st->rx[0] & ~SCA3000_REG_MODE_MODE_MASK)
122662306a36Sopenharmony_ci			| SCA3000_REG_MODE_MEAS_MODE_MOT_DET);
122762306a36Sopenharmony_ci	/* if on and should be off */
122862306a36Sopenharmony_ci	else if (!(st->mo_det_use_count) &&
122962306a36Sopenharmony_ci		 ((st->rx[0] & SCA3000_REG_MODE_MODE_MASK)
123062306a36Sopenharmony_ci		  == SCA3000_REG_MODE_MEAS_MODE_MOT_DET))
123162306a36Sopenharmony_ci		return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR,
123262306a36Sopenharmony_ci			st->rx[0] & SCA3000_REG_MODE_MODE_MASK);
123362306a36Sopenharmony_ci	else
123462306a36Sopenharmony_ci		return 0;
123562306a36Sopenharmony_ci}
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ci/**
123862306a36Sopenharmony_ci * sca3000_write_event_config() - simple on off control for motion detector
123962306a36Sopenharmony_ci * @indio_dev: IIO device instance specific structure. Data specific to this
124062306a36Sopenharmony_ci * particular driver may be accessed via iio_priv(indio_dev).
124162306a36Sopenharmony_ci * @chan: Description of the channel whose event we are configuring.
124262306a36Sopenharmony_ci * @type: The type of event.
124362306a36Sopenharmony_ci * @dir: The direction of the event.
124462306a36Sopenharmony_ci * @state: Desired state of event being configured.
124562306a36Sopenharmony_ci *
124662306a36Sopenharmony_ci * This is a per axis control, but enabling any will result in the
124762306a36Sopenharmony_ci * motion detector unit being enabled.
124862306a36Sopenharmony_ci * N.B. enabling motion detector stops normal data acquisition.
124962306a36Sopenharmony_ci * There is a complexity in knowing which mode to return to when
125062306a36Sopenharmony_ci * this mode is disabled.  Currently normal mode is assumed.
125162306a36Sopenharmony_ci **/
125262306a36Sopenharmony_cistatic int sca3000_write_event_config(struct iio_dev *indio_dev,
125362306a36Sopenharmony_ci				      const struct iio_chan_spec *chan,
125462306a36Sopenharmony_ci				      enum iio_event_type type,
125562306a36Sopenharmony_ci				      enum iio_event_direction dir,
125662306a36Sopenharmony_ci				      int state)
125762306a36Sopenharmony_ci{
125862306a36Sopenharmony_ci	struct sca3000_state *st = iio_priv(indio_dev);
125962306a36Sopenharmony_ci	int ret;
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci	mutex_lock(&st->lock);
126262306a36Sopenharmony_ci	switch (chan->channel2) {
126362306a36Sopenharmony_ci	case IIO_MOD_X_AND_Y_AND_Z:
126462306a36Sopenharmony_ci		ret = sca3000_freefall_set_state(indio_dev, state);
126562306a36Sopenharmony_ci		break;
126662306a36Sopenharmony_ci
126762306a36Sopenharmony_ci	case IIO_MOD_X:
126862306a36Sopenharmony_ci	case IIO_MOD_Y:
126962306a36Sopenharmony_ci	case IIO_MOD_Z:
127062306a36Sopenharmony_ci		ret = sca3000_motion_detect_set_state(indio_dev,
127162306a36Sopenharmony_ci						      chan->address,
127262306a36Sopenharmony_ci						      state);
127362306a36Sopenharmony_ci		break;
127462306a36Sopenharmony_ci	default:
127562306a36Sopenharmony_ci		ret = -EINVAL;
127662306a36Sopenharmony_ci		break;
127762306a36Sopenharmony_ci	}
127862306a36Sopenharmony_ci	mutex_unlock(&st->lock);
127962306a36Sopenharmony_ci
128062306a36Sopenharmony_ci	return ret;
128162306a36Sopenharmony_ci}
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_cistatic inline
128462306a36Sopenharmony_ciint __sca3000_hw_ring_state_set(struct iio_dev *indio_dev, bool state)
128562306a36Sopenharmony_ci{
128662306a36Sopenharmony_ci	struct sca3000_state *st = iio_priv(indio_dev);
128762306a36Sopenharmony_ci	int ret;
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_ci	mutex_lock(&st->lock);
129062306a36Sopenharmony_ci	ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
129162306a36Sopenharmony_ci	if (ret)
129262306a36Sopenharmony_ci		goto error_ret;
129362306a36Sopenharmony_ci	if (state) {
129462306a36Sopenharmony_ci		dev_info(&indio_dev->dev, "supposedly enabling ring buffer\n");
129562306a36Sopenharmony_ci		ret = sca3000_write_reg(st,
129662306a36Sopenharmony_ci			SCA3000_REG_MODE_ADDR,
129762306a36Sopenharmony_ci			(st->rx[0] | SCA3000_REG_MODE_RING_BUF_ENABLE));
129862306a36Sopenharmony_ci	} else
129962306a36Sopenharmony_ci		ret = sca3000_write_reg(st,
130062306a36Sopenharmony_ci			SCA3000_REG_MODE_ADDR,
130162306a36Sopenharmony_ci			(st->rx[0] & ~SCA3000_REG_MODE_RING_BUF_ENABLE));
130262306a36Sopenharmony_cierror_ret:
130362306a36Sopenharmony_ci	mutex_unlock(&st->lock);
130462306a36Sopenharmony_ci
130562306a36Sopenharmony_ci	return ret;
130662306a36Sopenharmony_ci}
130762306a36Sopenharmony_ci
130862306a36Sopenharmony_ci/**
130962306a36Sopenharmony_ci * sca3000_hw_ring_preenable() - hw ring buffer preenable function
131062306a36Sopenharmony_ci * @indio_dev: structure representing the IIO device. Device instance
131162306a36Sopenharmony_ci * specific state can be accessed via iio_priv(indio_dev).
131262306a36Sopenharmony_ci *
131362306a36Sopenharmony_ci * Very simple enable function as the chip will allows normal reads
131462306a36Sopenharmony_ci * during ring buffer operation so as long as it is indeed running
131562306a36Sopenharmony_ci * before we notify the core, the precise ordering does not matter.
131662306a36Sopenharmony_ci */
131762306a36Sopenharmony_cistatic int sca3000_hw_ring_preenable(struct iio_dev *indio_dev)
131862306a36Sopenharmony_ci{
131962306a36Sopenharmony_ci	int ret;
132062306a36Sopenharmony_ci	struct sca3000_state *st = iio_priv(indio_dev);
132162306a36Sopenharmony_ci
132262306a36Sopenharmony_ci	mutex_lock(&st->lock);
132362306a36Sopenharmony_ci
132462306a36Sopenharmony_ci	/* Enable the 50% full interrupt */
132562306a36Sopenharmony_ci	ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1);
132662306a36Sopenharmony_ci	if (ret)
132762306a36Sopenharmony_ci		goto error_unlock;
132862306a36Sopenharmony_ci	ret = sca3000_write_reg(st,
132962306a36Sopenharmony_ci				SCA3000_REG_INT_MASK_ADDR,
133062306a36Sopenharmony_ci				st->rx[0] | SCA3000_REG_INT_MASK_RING_HALF);
133162306a36Sopenharmony_ci	if (ret)
133262306a36Sopenharmony_ci		goto error_unlock;
133362306a36Sopenharmony_ci
133462306a36Sopenharmony_ci	mutex_unlock(&st->lock);
133562306a36Sopenharmony_ci
133662306a36Sopenharmony_ci	return __sca3000_hw_ring_state_set(indio_dev, 1);
133762306a36Sopenharmony_ci
133862306a36Sopenharmony_cierror_unlock:
133962306a36Sopenharmony_ci	mutex_unlock(&st->lock);
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ci	return ret;
134262306a36Sopenharmony_ci}
134362306a36Sopenharmony_ci
134462306a36Sopenharmony_cistatic int sca3000_hw_ring_postdisable(struct iio_dev *indio_dev)
134562306a36Sopenharmony_ci{
134662306a36Sopenharmony_ci	int ret;
134762306a36Sopenharmony_ci	struct sca3000_state *st = iio_priv(indio_dev);
134862306a36Sopenharmony_ci
134962306a36Sopenharmony_ci	ret = __sca3000_hw_ring_state_set(indio_dev, 0);
135062306a36Sopenharmony_ci	if (ret)
135162306a36Sopenharmony_ci		return ret;
135262306a36Sopenharmony_ci
135362306a36Sopenharmony_ci	/* Disable the 50% full interrupt */
135462306a36Sopenharmony_ci	mutex_lock(&st->lock);
135562306a36Sopenharmony_ci
135662306a36Sopenharmony_ci	ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1);
135762306a36Sopenharmony_ci	if (ret)
135862306a36Sopenharmony_ci		goto unlock;
135962306a36Sopenharmony_ci	ret = sca3000_write_reg(st,
136062306a36Sopenharmony_ci				SCA3000_REG_INT_MASK_ADDR,
136162306a36Sopenharmony_ci				st->rx[0] & ~SCA3000_REG_INT_MASK_RING_HALF);
136262306a36Sopenharmony_ciunlock:
136362306a36Sopenharmony_ci	mutex_unlock(&st->lock);
136462306a36Sopenharmony_ci	return ret;
136562306a36Sopenharmony_ci}
136662306a36Sopenharmony_ci
136762306a36Sopenharmony_cistatic const struct iio_buffer_setup_ops sca3000_ring_setup_ops = {
136862306a36Sopenharmony_ci	.preenable = &sca3000_hw_ring_preenable,
136962306a36Sopenharmony_ci	.postdisable = &sca3000_hw_ring_postdisable,
137062306a36Sopenharmony_ci};
137162306a36Sopenharmony_ci
137262306a36Sopenharmony_ci/**
137362306a36Sopenharmony_ci * sca3000_clean_setup() - get the device into a predictable state
137462306a36Sopenharmony_ci * @st: Device instance specific private data structure
137562306a36Sopenharmony_ci *
137662306a36Sopenharmony_ci * Devices use flash memory to store many of the register values
137762306a36Sopenharmony_ci * and hence can come up in somewhat unpredictable states.
137862306a36Sopenharmony_ci * Hence reset everything on driver load.
137962306a36Sopenharmony_ci */
138062306a36Sopenharmony_cistatic int sca3000_clean_setup(struct sca3000_state *st)
138162306a36Sopenharmony_ci{
138262306a36Sopenharmony_ci	int ret;
138362306a36Sopenharmony_ci
138462306a36Sopenharmony_ci	mutex_lock(&st->lock);
138562306a36Sopenharmony_ci	/* Ensure all interrupts have been acknowledged */
138662306a36Sopenharmony_ci	ret = sca3000_read_data_short(st, SCA3000_REG_INT_STATUS_ADDR, 1);
138762306a36Sopenharmony_ci	if (ret)
138862306a36Sopenharmony_ci		goto error_ret;
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_ci	/* Turn off all motion detection channels */
139162306a36Sopenharmony_ci	ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL);
139262306a36Sopenharmony_ci	if (ret < 0)
139362306a36Sopenharmony_ci		goto error_ret;
139462306a36Sopenharmony_ci	ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL,
139562306a36Sopenharmony_ci				     ret & SCA3000_MD_CTRL_PROT_MASK);
139662306a36Sopenharmony_ci	if (ret)
139762306a36Sopenharmony_ci		goto error_ret;
139862306a36Sopenharmony_ci
139962306a36Sopenharmony_ci	/* Disable ring buffer */
140062306a36Sopenharmony_ci	ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL);
140162306a36Sopenharmony_ci	if (ret < 0)
140262306a36Sopenharmony_ci		goto error_ret;
140362306a36Sopenharmony_ci	ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL,
140462306a36Sopenharmony_ci				     (ret & SCA3000_REG_OUT_CTRL_PROT_MASK)
140562306a36Sopenharmony_ci				     | SCA3000_REG_OUT_CTRL_BUF_X_EN
140662306a36Sopenharmony_ci				     | SCA3000_REG_OUT_CTRL_BUF_Y_EN
140762306a36Sopenharmony_ci				     | SCA3000_REG_OUT_CTRL_BUF_Z_EN
140862306a36Sopenharmony_ci				     | SCA3000_REG_OUT_CTRL_BUF_DIV_4);
140962306a36Sopenharmony_ci	if (ret)
141062306a36Sopenharmony_ci		goto error_ret;
141162306a36Sopenharmony_ci	/* Enable interrupts, relevant to mode and set up as active low */
141262306a36Sopenharmony_ci	ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1);
141362306a36Sopenharmony_ci	if (ret)
141462306a36Sopenharmony_ci		goto error_ret;
141562306a36Sopenharmony_ci	ret = sca3000_write_reg(st,
141662306a36Sopenharmony_ci				SCA3000_REG_INT_MASK_ADDR,
141762306a36Sopenharmony_ci				(ret & SCA3000_REG_INT_MASK_PROT_MASK)
141862306a36Sopenharmony_ci				| SCA3000_REG_INT_MASK_ACTIVE_LOW);
141962306a36Sopenharmony_ci	if (ret)
142062306a36Sopenharmony_ci		goto error_ret;
142162306a36Sopenharmony_ci	/*
142262306a36Sopenharmony_ci	 * Select normal measurement mode, free fall off, ring off
142362306a36Sopenharmony_ci	 * Ring in 12 bit mode - it is fine to overwrite reserved bits 3,5
142462306a36Sopenharmony_ci	 * as that occurs in one of the example on the datasheet
142562306a36Sopenharmony_ci	 */
142662306a36Sopenharmony_ci	ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
142762306a36Sopenharmony_ci	if (ret)
142862306a36Sopenharmony_ci		goto error_ret;
142962306a36Sopenharmony_ci	ret = sca3000_write_reg(st, SCA3000_REG_MODE_ADDR,
143062306a36Sopenharmony_ci				(st->rx[0] & SCA3000_MODE_PROT_MASK));
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_cierror_ret:
143362306a36Sopenharmony_ci	mutex_unlock(&st->lock);
143462306a36Sopenharmony_ci	return ret;
143562306a36Sopenharmony_ci}
143662306a36Sopenharmony_ci
143762306a36Sopenharmony_cistatic const struct iio_info sca3000_info = {
143862306a36Sopenharmony_ci	.attrs = &sca3000_attribute_group,
143962306a36Sopenharmony_ci	.read_raw = &sca3000_read_raw,
144062306a36Sopenharmony_ci	.write_raw = &sca3000_write_raw,
144162306a36Sopenharmony_ci	.read_event_value = &sca3000_read_event_value,
144262306a36Sopenharmony_ci	.write_event_value = &sca3000_write_event_value,
144362306a36Sopenharmony_ci	.read_event_config = &sca3000_read_event_config,
144462306a36Sopenharmony_ci	.write_event_config = &sca3000_write_event_config,
144562306a36Sopenharmony_ci};
144662306a36Sopenharmony_ci
144762306a36Sopenharmony_cistatic int sca3000_probe(struct spi_device *spi)
144862306a36Sopenharmony_ci{
144962306a36Sopenharmony_ci	int ret;
145062306a36Sopenharmony_ci	struct sca3000_state *st;
145162306a36Sopenharmony_ci	struct iio_dev *indio_dev;
145262306a36Sopenharmony_ci
145362306a36Sopenharmony_ci	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
145462306a36Sopenharmony_ci	if (!indio_dev)
145562306a36Sopenharmony_ci		return -ENOMEM;
145662306a36Sopenharmony_ci
145762306a36Sopenharmony_ci	st = iio_priv(indio_dev);
145862306a36Sopenharmony_ci	spi_set_drvdata(spi, indio_dev);
145962306a36Sopenharmony_ci	st->us = spi;
146062306a36Sopenharmony_ci	mutex_init(&st->lock);
146162306a36Sopenharmony_ci	st->info = &sca3000_spi_chip_info_tbl[spi_get_device_id(spi)
146262306a36Sopenharmony_ci					      ->driver_data];
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_ci	indio_dev->name = spi_get_device_id(spi)->name;
146562306a36Sopenharmony_ci	indio_dev->info = &sca3000_info;
146662306a36Sopenharmony_ci	if (st->info->temp_output) {
146762306a36Sopenharmony_ci		indio_dev->channels = sca3000_channels_with_temp;
146862306a36Sopenharmony_ci		indio_dev->num_channels =
146962306a36Sopenharmony_ci			ARRAY_SIZE(sca3000_channels_with_temp);
147062306a36Sopenharmony_ci	} else {
147162306a36Sopenharmony_ci		indio_dev->channels = sca3000_channels;
147262306a36Sopenharmony_ci		indio_dev->num_channels = ARRAY_SIZE(sca3000_channels);
147362306a36Sopenharmony_ci	}
147462306a36Sopenharmony_ci	indio_dev->modes = INDIO_DIRECT_MODE;
147562306a36Sopenharmony_ci
147662306a36Sopenharmony_ci	ret = devm_iio_kfifo_buffer_setup(&spi->dev, indio_dev,
147762306a36Sopenharmony_ci					  &sca3000_ring_setup_ops);
147862306a36Sopenharmony_ci	if (ret)
147962306a36Sopenharmony_ci		return ret;
148062306a36Sopenharmony_ci
148162306a36Sopenharmony_ci	if (spi->irq) {
148262306a36Sopenharmony_ci		ret = request_threaded_irq(spi->irq,
148362306a36Sopenharmony_ci					   NULL,
148462306a36Sopenharmony_ci					   &sca3000_event_handler,
148562306a36Sopenharmony_ci					   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
148662306a36Sopenharmony_ci					   "sca3000",
148762306a36Sopenharmony_ci					   indio_dev);
148862306a36Sopenharmony_ci		if (ret)
148962306a36Sopenharmony_ci			return ret;
149062306a36Sopenharmony_ci	}
149162306a36Sopenharmony_ci	ret = sca3000_clean_setup(st);
149262306a36Sopenharmony_ci	if (ret)
149362306a36Sopenharmony_ci		goto error_free_irq;
149462306a36Sopenharmony_ci
149562306a36Sopenharmony_ci	ret = sca3000_print_rev(indio_dev);
149662306a36Sopenharmony_ci	if (ret)
149762306a36Sopenharmony_ci		goto error_free_irq;
149862306a36Sopenharmony_ci
149962306a36Sopenharmony_ci	return iio_device_register(indio_dev);
150062306a36Sopenharmony_ci
150162306a36Sopenharmony_cierror_free_irq:
150262306a36Sopenharmony_ci	if (spi->irq)
150362306a36Sopenharmony_ci		free_irq(spi->irq, indio_dev);
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci	return ret;
150662306a36Sopenharmony_ci}
150762306a36Sopenharmony_ci
150862306a36Sopenharmony_cistatic int sca3000_stop_all_interrupts(struct sca3000_state *st)
150962306a36Sopenharmony_ci{
151062306a36Sopenharmony_ci	int ret;
151162306a36Sopenharmony_ci
151262306a36Sopenharmony_ci	mutex_lock(&st->lock);
151362306a36Sopenharmony_ci	ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1);
151462306a36Sopenharmony_ci	if (ret)
151562306a36Sopenharmony_ci		goto error_ret;
151662306a36Sopenharmony_ci	ret = sca3000_write_reg(st, SCA3000_REG_INT_MASK_ADDR,
151762306a36Sopenharmony_ci				(st->rx[0] &
151862306a36Sopenharmony_ci				 ~(SCA3000_REG_INT_MASK_RING_THREE_QUARTER |
151962306a36Sopenharmony_ci				   SCA3000_REG_INT_MASK_RING_HALF |
152062306a36Sopenharmony_ci				   SCA3000_REG_INT_MASK_ALL_INTS)));
152162306a36Sopenharmony_cierror_ret:
152262306a36Sopenharmony_ci	mutex_unlock(&st->lock);
152362306a36Sopenharmony_ci	return ret;
152462306a36Sopenharmony_ci}
152562306a36Sopenharmony_ci
152662306a36Sopenharmony_cistatic void sca3000_remove(struct spi_device *spi)
152762306a36Sopenharmony_ci{
152862306a36Sopenharmony_ci	struct iio_dev *indio_dev = spi_get_drvdata(spi);
152962306a36Sopenharmony_ci	struct sca3000_state *st = iio_priv(indio_dev);
153062306a36Sopenharmony_ci
153162306a36Sopenharmony_ci	iio_device_unregister(indio_dev);
153262306a36Sopenharmony_ci
153362306a36Sopenharmony_ci	/* Must ensure no interrupts can be generated after this! */
153462306a36Sopenharmony_ci	sca3000_stop_all_interrupts(st);
153562306a36Sopenharmony_ci	if (spi->irq)
153662306a36Sopenharmony_ci		free_irq(spi->irq, indio_dev);
153762306a36Sopenharmony_ci}
153862306a36Sopenharmony_ci
153962306a36Sopenharmony_cistatic const struct spi_device_id sca3000_id[] = {
154062306a36Sopenharmony_ci	{"sca3000_d01", d01},
154162306a36Sopenharmony_ci	{"sca3000_e02", e02},
154262306a36Sopenharmony_ci	{"sca3000_e04", e04},
154362306a36Sopenharmony_ci	{"sca3000_e05", e05},
154462306a36Sopenharmony_ci	{}
154562306a36Sopenharmony_ci};
154662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, sca3000_id);
154762306a36Sopenharmony_ci
154862306a36Sopenharmony_cistatic struct spi_driver sca3000_driver = {
154962306a36Sopenharmony_ci	.driver = {
155062306a36Sopenharmony_ci		.name = "sca3000",
155162306a36Sopenharmony_ci	},
155262306a36Sopenharmony_ci	.probe = sca3000_probe,
155362306a36Sopenharmony_ci	.remove = sca3000_remove,
155462306a36Sopenharmony_ci	.id_table = sca3000_id,
155562306a36Sopenharmony_ci};
155662306a36Sopenharmony_cimodule_spi_driver(sca3000_driver);
155762306a36Sopenharmony_ci
155862306a36Sopenharmony_ciMODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
155962306a36Sopenharmony_ciMODULE_DESCRIPTION("VTI SCA3000 Series Accelerometers SPI driver");
156062306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
1561