linux/drivers/iio/accel/sca3000.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * sca3000_core.c -- support VTI sca3000 series accelerometers via SPI
 *
 * Copyright (c) 2009 Jonathan Cameron <[email protected]>
 *
 * See industrialio/accels/sca3000.h for comments.
 */

#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/sysfs.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
#include <linux/iio/buffer.h>
#include <linux/iio/kfifo_buf.h>

#define SCA3000_WRITE_REG(a)
#define SCA3000_READ_REG(a)

#define SCA3000_REG_REVID_ADDR
#define SCA3000_REG_REVID_MAJOR_MASK
#define SCA3000_REG_REVID_MINOR_MASK

#define SCA3000_REG_STATUS_ADDR
#define SCA3000_LOCKED
#define SCA3000_EEPROM_CS_ERROR
#define SCA3000_SPI_FRAME_ERROR

/* All reads done using register decrement so no need to directly access LSBs */
#define SCA3000_REG_X_MSB_ADDR
#define SCA3000_REG_Y_MSB_ADDR
#define SCA3000_REG_Z_MSB_ADDR

#define SCA3000_REG_RING_OUT_ADDR

/* Temp read untested - the e05 doesn't have the sensor */
#define SCA3000_REG_TEMP_MSB_ADDR

#define SCA3000_REG_MODE_ADDR
#define SCA3000_MODE_PROT_MASK
#define SCA3000_REG_MODE_RING_BUF_ENABLE
#define SCA3000_REG_MODE_RING_BUF_8BIT

/*
 * Free fall detection triggers an interrupt if the acceleration
 * is below a threshold for equivalent of 25cm drop
 */
#define SCA3000_REG_MODE_FREE_FALL_DETECT
#define SCA3000_REG_MODE_MEAS_MODE_NORMAL
#define SCA3000_REG_MODE_MEAS_MODE_OP_1
#define SCA3000_REG_MODE_MEAS_MODE_OP_2

/*
 * In motion detection mode the accelerations are band pass filtered
 * (approx 1 - 25Hz) and then a programmable threshold used to trigger
 * and interrupt.
 */
#define SCA3000_REG_MODE_MEAS_MODE_MOT_DET
#define SCA3000_REG_MODE_MODE_MASK

#define SCA3000_REG_BUF_COUNT_ADDR

#define SCA3000_REG_INT_STATUS_ADDR
#define SCA3000_REG_INT_STATUS_THREE_QUARTERS
#define SCA3000_REG_INT_STATUS_HALF

#define SCA3000_INT_STATUS_FREE_FALL
#define SCA3000_INT_STATUS_Y_TRIGGER
#define SCA3000_INT_STATUS_X_TRIGGER
#define SCA3000_INT_STATUS_Z_TRIGGER

/* Used to allow access to multiplexed registers */
#define SCA3000_REG_CTRL_SEL_ADDR
/* Only available for SCA3000-D03 and SCA3000-D01 */
#define SCA3000_REG_CTRL_SEL_I2C_DISABLE
#define SCA3000_REG_CTRL_SEL_MD_CTRL
#define SCA3000_REG_CTRL_SEL_MD_Y_TH
#define SCA3000_REG_CTRL_SEL_MD_X_TH
#define SCA3000_REG_CTRL_SEL_MD_Z_TH
/*
 * BE VERY CAREFUL WITH THIS, IF 3 BITS ARE NOT SET the device
 * will not function
 */
#define SCA3000_REG_CTRL_SEL_OUT_CTRL

#define SCA3000_REG_OUT_CTRL_PROT_MASK
#define SCA3000_REG_OUT_CTRL_BUF_X_EN
#define SCA3000_REG_OUT_CTRL_BUF_Y_EN
#define SCA3000_REG_OUT_CTRL_BUF_Z_EN
#define SCA3000_REG_OUT_CTRL_BUF_DIV_MASK
#define SCA3000_REG_OUT_CTRL_BUF_DIV_4
#define SCA3000_REG_OUT_CTRL_BUF_DIV_2


/*
 * Control which motion detector interrupts are on.
 * For now only OR combinations are supported.
 */
#define SCA3000_MD_CTRL_PROT_MASK
#define SCA3000_MD_CTRL_OR_Y
#define SCA3000_MD_CTRL_OR_X
#define SCA3000_MD_CTRL_OR_Z
/* Currently unsupported */
#define SCA3000_MD_CTRL_AND_Y
#define SCA3000_MD_CTRL_AND_X
#define SCA3000_MD_CTRL_AND_Z

/*
 * Some control registers of complex access methods requiring this register to
 * be used to remove a lock.
 */
#define SCA3000_REG_UNLOCK_ADDR

#define SCA3000_REG_INT_MASK_ADDR
#define SCA3000_REG_INT_MASK_PROT_MASK

#define SCA3000_REG_INT_MASK_RING_THREE_QUARTER
#define SCA3000_REG_INT_MASK_RING_HALF

#define SCA3000_REG_INT_MASK_ALL_INTS
#define SCA3000_REG_INT_MASK_ACTIVE_HIGH
#define SCA3000_REG_INT_MASK_ACTIVE_LOW
/* Values of multiplexed registers (write to ctrl_data after select) */
#define SCA3000_REG_CTRL_DATA_ADDR

/*
 * Measurement modes available on some sca3000 series chips. Code assumes others
 * may become available in the future.
 *
 * Bypass - Bypass the low-pass filter in the signal channel so as to increase
 *          signal bandwidth.
 *
 * Narrow - Narrow low-pass filtering of the signal channel and half output
 *          data rate by decimation.
 *
 * Wide - Widen low-pass filtering of signal channel to increase bandwidth
 */
#define SCA3000_OP_MODE_BYPASS
#define SCA3000_OP_MODE_NARROW
#define SCA3000_OP_MODE_WIDE
#define SCA3000_MAX_TX
#define SCA3000_MAX_RX

/**
 * struct sca3000_state - device instance state information
 * @us:			the associated spi device
 * @info:			chip variant information
 * @last_timestamp:		the timestamp of the last event
 * @mo_det_use_count:		reference counter for the motion detection unit
 * @lock:			lock used to protect elements of sca3000_state
 *				and the underlying device state.
 * @tx:			dma-able transmit buffer
 * @rx:			dma-able receive buffer
 **/
struct sca3000_state {};

/**
 * struct sca3000_chip_info - model dependent parameters
 * @scale:			scale * 10^-6
 * @temp_output:		some devices have temperature sensors.
 * @measurement_mode_freq:	normal mode sampling frequency
 * @measurement_mode_3db_freq:	3db cutoff frequency of the low pass filter for
 * the normal measurement mode.
 * @option_mode_1:		first optional mode. Not all models have one
 * @option_mode_1_freq:		option mode 1 sampling frequency
 * @option_mode_1_3db_freq:	3db cutoff frequency of the low pass filter for
 * the first option mode.
 * @option_mode_2:		second optional mode. Not all chips have one
 * @option_mode_2_freq:		option mode 2 sampling frequency
 * @option_mode_2_3db_freq:	3db cutoff frequency of the low pass filter for
 * the second option mode.
 * @mot_det_mult_xz:		Bit wise multipliers to calculate the threshold
 * for motion detection in the x and z axis.
 * @mot_det_mult_y:		Bit wise multipliers to calculate the threshold
 * for motion detection in the y axis.
 *
 * This structure is used to hold information about the functionality of a given
 * sca3000 variant.
 **/
struct sca3000_chip_info {};

enum sca3000_variant {};

/*
 * Note where option modes are not defined, the chip simply does not
 * support any.
 * Other chips in the sca3000 series use i2c and are not included here.
 *
 * Some of these devices are only listed in the family data sheet and
 * do not actually appear to be available.
 */
static const struct sca3000_chip_info sca3000_spi_chip_info_tbl[] =;

static int sca3000_write_reg(struct sca3000_state *st, u8 address, u8 val)
{}

static int sca3000_read_data_short(struct sca3000_state *st,
				   u8 reg_address_high,
				   int len)
{}

/**
 * sca3000_reg_lock_on() - test if the ctrl register lock is on
 * @st: Driver specific device instance data.
 *
 * Lock must be held.
 **/
static int sca3000_reg_lock_on(struct sca3000_state *st)
{}

/**
 * __sca3000_unlock_reg_lock() - unlock the control registers
 * @st: Driver specific device instance data.
 *
 * Note the device does not appear to support doing this in a single transfer.
 * This should only ever be used as part of ctrl reg read.
 * Lock must be held before calling this
 */
static int __sca3000_unlock_reg_lock(struct sca3000_state *st)
{}

/**
 * sca3000_write_ctrl_reg() - write to a lock protect ctrl register
 * @st: Driver specific device instance data.
 * @sel: selects which registers we wish to write to
 * @val: the value to be written
 *
 * Certain control registers are protected against overwriting by the lock
 * register and use a shared write address. This function allows writing of
 * these registers.
 * Lock must be held.
 */
static int sca3000_write_ctrl_reg(struct sca3000_state *st,
				  u8 sel,
				  uint8_t val)
{}

/**
 * sca3000_read_ctrl_reg() - read from lock protected control register.
 * @st: Driver specific device instance data.
 * @ctrl_reg: Which ctrl register do we want to read.
 *
 * Lock must be held.
 */
static int sca3000_read_ctrl_reg(struct sca3000_state *st,
				 u8 ctrl_reg)
{}

/**
 * sca3000_print_rev() - sysfs interface to read the chip revision number
 * @indio_dev: Device instance specific generic IIO data.
 * Driver specific device instance data can be obtained via
 * iio_priv(indio_dev)
 */
static int sca3000_print_rev(struct iio_dev *indio_dev)
{}

static ssize_t
sca3000_show_available_3db_freqs(struct device *dev,
				 struct device_attribute *attr,
				 char *buf)
{}

static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available,
		       S_IRUGO, sca3000_show_available_3db_freqs,
		       NULL, 0);

static const struct iio_event_spec sca3000_event =;

/*
 * Note the hack in the number of bits to pretend we have 2 more than
 * we do in the fifo.
 */
#define SCA3000_CHAN(index, mod)

static const struct iio_event_spec sca3000_freefall_event_spec =;

static const struct iio_chan_spec sca3000_channels[] =;

static const struct iio_chan_spec sca3000_channels_with_temp[] =;

static u8 sca3000_addresses[3][3] =;

/**
 * __sca3000_get_base_freq() - obtain mode specific base frequency
 * @st: Private driver specific device instance specific state.
 * @info: chip type specific information.
 * @base_freq: Base frequency for the current measurement mode.
 *
 * lock must be held
 */
static inline int __sca3000_get_base_freq(struct sca3000_state *st,
					  const struct sca3000_chip_info *info,
					  int *base_freq)
{}

/**
 * sca3000_read_raw_samp_freq() - read_raw handler for IIO_CHAN_INFO_SAMP_FREQ
 * @st: Private driver specific device instance specific state.
 * @val: The frequency read back.
 *
 * lock must be held
 **/
static int sca3000_read_raw_samp_freq(struct sca3000_state *st, int *val)
{}

/**
 * sca3000_write_raw_samp_freq() - write_raw handler for IIO_CHAN_INFO_SAMP_FREQ
 * @st: Private driver specific device instance specific state.
 * @val: The frequency desired.
 *
 * lock must be held
 */
static int sca3000_write_raw_samp_freq(struct sca3000_state *st, int val)
{}

static int sca3000_read_3db_freq(struct sca3000_state *st, int *val)
{}

static int sca3000_write_3db_freq(struct sca3000_state *st, int val)
{}

static int sca3000_read_raw(struct iio_dev *indio_dev,
			    struct iio_chan_spec const *chan,
			    int *val,
			    int *val2,
			    long mask)
{}

static int sca3000_write_raw(struct iio_dev *indio_dev,
			     struct iio_chan_spec const *chan,
			     int val, int val2, long mask)
{}

/**
 * sca3000_read_av_freq() - sysfs function to get available frequencies
 * @dev: Device structure for this device.
 * @attr: Description of the attribute.
 * @buf: Incoming string
 *
 * The later modes are only relevant to the ring buffer - and depend on current
 * mode. Note that data sheet gives rather wide tolerances for these so integer
 * division will give good enough answer and not all chips have them specified
 * at all.
 **/
static ssize_t sca3000_read_av_freq(struct device *dev,
				    struct device_attribute *attr,
				    char *buf)
{}

/*
 * Should only really be registered if ring buffer support is compiled in.
 * Does no harm however and doing it right would add a fair bit of complexity
 */
static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(sca3000_read_av_freq);

/*
 * sca3000_read_event_value() - query of a threshold or period
 */
static int 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)
{}

/**
 * sca3000_write_event_value() - control of threshold and period
 * @indio_dev: Device instance specific IIO information.
 * @chan: Description of the channel for which the event is being
 * configured.
 * @type: The type of event being configured, here magnitude rising
 * as everything else is read only.
 * @dir: Direction of the event (here rising)
 * @info: What information about the event are we configuring.
 * Here the threshold only.
 * @val: Integer part of the value being written..
 * @val2: Non integer part of the value being written. Here always 0.
 */
static int 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)
{}

static struct attribute *sca3000_attributes[] =;

static const struct attribute_group sca3000_attribute_group =;

static int sca3000_read_data(struct sca3000_state *st,
			     u8 reg_address_high,
			     u8 *rx,
			     int len)
{}

/**
 * sca3000_ring_int_process() - ring specific interrupt handling.
 * @val: Value of the interrupt status register.
 * @indio_dev: Device instance specific IIO device structure.
 */
static void sca3000_ring_int_process(u8 val, struct iio_dev *indio_dev)
{}

/**
 * sca3000_event_handler() - handling ring and non ring events
 * @irq: The irq being handled.
 * @private: struct iio_device pointer for the device.
 *
 * Ring related interrupt handler. Depending on event, push to
 * the ring buffer event chrdev or the event one.
 *
 * This function is complicated by the fact that the devices can signify ring
 * and non ring events via the same interrupt line and they can only
 * be distinguished via a read of the relevant status register.
 */
static irqreturn_t sca3000_event_handler(int irq, void *private)
{}

/*
 * sca3000_read_event_config() what events are enabled
 */
static int 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)
{}

static int sca3000_freefall_set_state(struct iio_dev *indio_dev, int state)
{}

static int sca3000_motion_detect_set_state(struct iio_dev *indio_dev, int axis,
					   int state)
{}

/**
 * sca3000_write_event_config() - simple on off control for motion detector
 * @indio_dev: IIO device instance specific structure. Data specific to this
 * particular driver may be accessed via iio_priv(indio_dev).
 * @chan: Description of the channel whose event we are configuring.
 * @type: The type of event.
 * @dir: The direction of the event.
 * @state: Desired state of event being configured.
 *
 * This is a per axis control, but enabling any will result in the
 * motion detector unit being enabled.
 * N.B. enabling motion detector stops normal data acquisition.
 * There is a complexity in knowing which mode to return to when
 * this mode is disabled.  Currently normal mode is assumed.
 **/
static int 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)
{}

static inline
int __sca3000_hw_ring_state_set(struct iio_dev *indio_dev, bool state)
{}

/**
 * sca3000_hw_ring_preenable() - hw ring buffer preenable function
 * @indio_dev: structure representing the IIO device. Device instance
 * specific state can be accessed via iio_priv(indio_dev).
 *
 * Very simple enable function as the chip will allows normal reads
 * during ring buffer operation so as long as it is indeed running
 * before we notify the core, the precise ordering does not matter.
 */
static int sca3000_hw_ring_preenable(struct iio_dev *indio_dev)
{}

static int sca3000_hw_ring_postdisable(struct iio_dev *indio_dev)
{}

static const struct iio_buffer_setup_ops sca3000_ring_setup_ops =;

/**
 * sca3000_clean_setup() - get the device into a predictable state
 * @st: Device instance specific private data structure
 *
 * Devices use flash memory to store many of the register values
 * and hence can come up in somewhat unpredictable states.
 * Hence reset everything on driver load.
 */
static int sca3000_clean_setup(struct sca3000_state *st)
{}

static const struct iio_info sca3000_info =;

static int sca3000_probe(struct spi_device *spi)
{}

static int sca3000_stop_all_interrupts(struct sca3000_state *st)
{}

static void sca3000_remove(struct spi_device *spi)
{}

static const struct spi_device_id sca3000_id[] =;
MODULE_DEVICE_TABLE(spi, sca3000_id);

static struct spi_driver sca3000_driver =;
module_spi_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();