linux/drivers/iio/pressure/zpa2326.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Murata ZPA2326 pressure and temperature sensor IIO driver
 *
 * Copyright (c) 2016 Parrot S.A.
 *
 * Author: Gregor Boirie <[email protected]>
 */

/**
 * DOC: ZPA2326 theory of operations
 *
 * This driver supports %INDIO_DIRECT_MODE and %INDIO_BUFFER_TRIGGERED IIO
 * modes.
 * A internal hardware trigger is also implemented to dispatch registered IIO
 * trigger consumers upon "sample ready" interrupts.
 *
 * ZPA2326 hardware supports 2 sampling mode: one shot and continuous.
 *
 * A complete one shot sampling cycle gets device out of low power mode,
 * performs pressure and temperature measurements, then automatically switches
 * back to low power mode. It is meant for on demand sampling with optimal power
 * saving at the cost of lower sampling rate and higher software overhead.
 * This is a natural candidate for IIO read_raw hook implementation
 * (%INDIO_DIRECT_MODE). It is also used for triggered buffering support to
 * ensure explicit synchronization with external trigger events
 * (%INDIO_BUFFER_TRIGGERED).
 *
 * The continuous mode works according to a periodic hardware measurement
 * process continuously pushing samples into an internal hardware FIFO (for
 * pressure samples only). Measurement cycle completion may be signaled by a
 * "sample ready" interrupt.
 * Typical software sequence of operations :
 * - get device out of low power mode,
 * - setup hardware sampling period,
 * - at end of period, upon data ready interrupt: pop pressure samples out of
 *   hardware FIFO and fetch temperature sample
 * - when no longer needed, stop sampling process by putting device into
 *   low power mode.
 * This mode is used to implement %INDIO_BUFFER_TRIGGERED mode if device tree
 * declares a valid interrupt line. In this case, the internal hardware trigger
 * drives acquisition.
 *
 * Note that hardware sampling frequency is taken into account only when
 * internal hardware trigger is attached as the highest sampling rate seems to
 * be the most energy efficient.
 *
 * TODO:
 *   preset pressure threshold crossing / IIO events ;
 *   differential pressure sampling ;
 *   hardware samples averaging.
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/unaligned.h>
#include "zpa2326.h"

/* 200 ms should be enough for the longest conversion time in one-shot mode. */
#define ZPA2326_CONVERSION_JIFFIES

/* There should be a 1 ms delay (Tpup) after getting out of reset. */
#define ZPA2326_TPUP_USEC_MIN
#define ZPA2326_TPUP_USEC_MAX

/**
 * struct zpa2326_frequency - Hardware sampling frequency descriptor
 * @hz : Frequency in Hertz.
 * @odr: Output Data Rate word as expected by %ZPA2326_CTRL_REG3_REG.
 */
struct zpa2326_frequency {};

/*
 * Keep these in strict ascending order: last array entry is expected to
 * correspond to the highest sampling frequency.
 */
static const struct zpa2326_frequency zpa2326_sampling_frequencies[] =;

/* Return the highest hardware sampling frequency available. */
static const struct zpa2326_frequency *zpa2326_highest_frequency(void)
{}

/**
 * struct zpa2326_private - Per-device internal private state
 * @timestamp:  Buffered samples ready datum.
 * @regmap:     Underlying I2C / SPI bus adapter used to abstract slave register
 *              accesses.
 * @result:     Allows sampling logic to get completion status of operations
 *              that interrupt handlers perform asynchronously.
 * @data_ready: Interrupt handler uses this to wake user context up at sampling
 *              operation completion.
 * @trigger:    Optional hardware / interrupt driven trigger used to notify
 *              external devices a new sample is ready.
 * @waken:      Flag indicating whether or not device has just been powered on.
 * @irq:        Optional interrupt line: negative or zero if not declared into
 *              DT, in which case sampling logic keeps polling status register
 *              to detect completion.
 * @frequency:  Current hardware sampling frequency.
 * @vref:       Power / voltage reference.
 * @vdd:        Power supply.
 */
struct zpa2326_private {};

#define zpa2326_err(idev, fmt, ...)

#define zpa2326_warn(idev, fmt, ...)

#define zpa2326_dbg(idev, fmt, ...)

bool zpa2326_isreg_writeable(struct device *dev, unsigned int reg)
{}
EXPORT_SYMBOL_NS_GPL();

bool zpa2326_isreg_readable(struct device *dev, unsigned int reg)
{}
EXPORT_SYMBOL_NS_GPL();

bool zpa2326_isreg_precious(struct device *dev, unsigned int reg)
{}
EXPORT_SYMBOL_NS_GPL();

/**
 * zpa2326_enable_device() - Enable device, i.e. get out of low power mode.
 * @indio_dev: The IIO device associated with the hardware to enable.
 *
 * Required to access complete register space and to perform any sampling
 * or control operations.
 *
 * Return: Zero when successful, a negative error code otherwise.
 */
static int zpa2326_enable_device(const struct iio_dev *indio_dev)
{}

/**
 * zpa2326_sleep() - Disable device, i.e. switch to low power mode.
 * @indio_dev: The IIO device associated with the hardware to disable.
 *
 * Only %ZPA2326_DEVICE_ID_REG and %ZPA2326_CTRL_REG0_REG registers may be
 * accessed once device is in the disabled state.
 *
 * Return: Zero when successful, a negative error code otherwise.
 */
static int zpa2326_sleep(const struct iio_dev *indio_dev)
{}

/**
 * zpa2326_reset_device() - Reset device to default hardware state.
 * @indio_dev: The IIO device associated with the hardware to reset.
 *
 * Disable sampling and empty hardware FIFO.
 * Device must be enabled before reset, i.e. not in low power mode.
 *
 * Return: Zero when successful, a negative error code otherwise.
 */
static int zpa2326_reset_device(const struct iio_dev *indio_dev)
{}

/**
 * zpa2326_start_oneshot() - Start a single sampling cycle, i.e. in one shot
 *                           mode.
 * @indio_dev: The IIO device associated with the sampling hardware.
 *
 * Device must have been previously enabled and configured for one shot mode.
 * Device will be switched back to low power mode at end of cycle.
 *
 * Return: Zero when successful, a negative error code otherwise.
 */
static int zpa2326_start_oneshot(const struct iio_dev *indio_dev)
{}

/**
 * zpa2326_power_on() - Power on device to allow subsequent configuration.
 * @indio_dev: The IIO device associated with the sampling hardware.
 * @private:   Internal private state related to @indio_dev.
 *
 * Sampling will be disabled, preventing strange things from happening in our
 * back. Hardware FIFO content will be cleared.
 * When successful, device will be left in the enabled state to allow further
 * configuration.
 *
 * Return: Zero when successful, a negative error code otherwise.
 */
static int zpa2326_power_on(const struct iio_dev         *indio_dev,
			    const struct zpa2326_private *private)
{}

/**
 * zpa2326_power_off() - Power off device, i.e. disable attached power
 *                       regulators.
 * @indio_dev: The IIO device associated with the sampling hardware.
 * @private:   Internal private state related to @indio_dev.
 *
 * Return: Zero when successful, a negative error code otherwise.
 */
static void zpa2326_power_off(const struct iio_dev         *indio_dev,
			      const struct zpa2326_private *private)
{}

/**
 * zpa2326_config_oneshot() - Setup device for one shot / on demand mode.
 * @indio_dev: The IIO device associated with the sampling hardware.
 * @irq:       Optional interrupt line the hardware uses to notify new data
 *             samples are ready. Negative or zero values indicate no interrupts
 *             are available, meaning polling is required.
 *
 * Output Data Rate is configured for the highest possible rate so that
 * conversion time and power consumption are reduced to a minimum.
 * Note that hardware internal averaging machinery (not implemented in this
 * driver) is not applicable in this mode.
 *
 * Device must have been previously enabled before calling
 * zpa2326_config_oneshot().
 *
 * Return: Zero when successful, a negative error code otherwise.
 */
static int zpa2326_config_oneshot(const struct iio_dev *indio_dev,
				  int                   irq)
{}

/**
 * zpa2326_clear_fifo() - Clear remaining entries in hardware FIFO.
 * @indio_dev: The IIO device associated with the sampling hardware.
 * @min_count: Number of samples present within hardware FIFO.
 *
 * @min_count argument is a hint corresponding to the known minimum number of
 * samples currently living in the FIFO. This allows to reduce the number of bus
 * accesses by skipping status register read operation as long as we know for
 * sure there are still entries left.
 *
 * Return: Zero when successful, a negative error code otherwise.
 */
static int zpa2326_clear_fifo(const struct iio_dev *indio_dev,
			      unsigned int          min_count)
{}

/**
 * zpa2326_dequeue_pressure() - Retrieve the most recent pressure sample from
 *                              hardware FIFO.
 * @indio_dev: The IIO device associated with the sampling hardware.
 * @pressure:  Sampled pressure output.
 *
 * Note that ZPA2326 hardware FIFO stores pressure samples only.
 *
 * Return: Zero when successful, a negative error code otherwise.
 */
static int zpa2326_dequeue_pressure(const struct iio_dev *indio_dev,
				    u32                  *pressure)
{}

/**
 * zpa2326_fill_sample_buffer() - Enqueue new channel samples to IIO buffer.
 * @indio_dev: The IIO device associated with the sampling hardware.
 * @private:   Internal private state related to @indio_dev.
 *
 * Return: Zero when successful, a negative error code otherwise.
 */
static int zpa2326_fill_sample_buffer(struct iio_dev               *indio_dev,
				      const struct zpa2326_private *private)
{}

#ifdef CONFIG_PM
static int zpa2326_runtime_suspend(struct device *parent)
{}

static int zpa2326_runtime_resume(struct device *parent)
{}

const struct dev_pm_ops zpa2326_pm_ops =;
EXPORT_SYMBOL_NS_GPL();

/**
 * zpa2326_resume() - Request the PM layer to power supply the device.
 * @indio_dev: The IIO device associated with the sampling hardware.
 *
 * Return:
 *  < 0 - a negative error code meaning failure ;
 *    0 - success, device has just been powered up ;
 *    1 - success, device was already powered.
 */
static int zpa2326_resume(const struct iio_dev *indio_dev)
{}

/**
 * zpa2326_suspend() - Schedule a power down using autosuspend feature of PM
 *                     layer.
 * @indio_dev: The IIO device associated with the sampling hardware.
 *
 * Device is switched to low power mode at first to save power even when
 * attached regulator is a "dummy" one.
 */
static void zpa2326_suspend(struct iio_dev *indio_dev)
{}

static void zpa2326_init_runtime(struct device *parent)
{}

static void zpa2326_fini_runtime(struct device *parent)
{}
#else /* !CONFIG_PM */
static int zpa2326_resume(const struct iio_dev *indio_dev)
{
	zpa2326_enable_device(indio_dev);

	return 0;
}

static void zpa2326_suspend(struct iio_dev *indio_dev)
{
	zpa2326_sleep(indio_dev);
}

#define zpa2326_init_runtime
#define zpa2326_fini_runtime
#endif /* !CONFIG_PM */

/**
 * zpa2326_handle_irq() - Process hardware interrupts.
 * @irq:  Interrupt line the hardware uses to notify new data has arrived.
 * @data: The IIO device associated with the sampling hardware.
 *
 * Timestamp buffered samples as soon as possible then schedule threaded bottom
 * half.
 *
 * Return: Always successful.
 */
static irqreturn_t zpa2326_handle_irq(int irq, void *data)
{}

/**
 * zpa2326_handle_threaded_irq() - Interrupt bottom-half handler.
 * @irq:  Interrupt line the hardware uses to notify new data has arrived.
 * @data: The IIO device associated with the sampling hardware.
 *
 * Mainly ensures interrupt is caused by a real "new sample available"
 * condition. This relies upon the ability to perform blocking / sleeping bus
 * accesses to slave's registers. This is why zpa2326_handle_threaded_irq() is
 * called from within a thread, i.e. not called from hard interrupt context.
 *
 * When device is using its own internal hardware trigger in continuous sampling
 * mode, data are available into hardware FIFO once interrupt has occurred. All
 * we have to do is to dispatch the trigger, which in turn will fetch data and
 * fill IIO buffer.
 *
 * When not using its own internal hardware trigger, the device has been
 * configured in one-shot mode either by an external trigger or the IIO read_raw
 * hook. This means one of the latter is currently waiting for sampling
 * completion, in which case we must simply wake it up.
 *
 * See zpa2326_trigger_handler().
 *
 * Return:
 *   %IRQ_NONE - no consistent interrupt happened ;
 *   %IRQ_HANDLED - there was new samples available.
 */
static irqreturn_t zpa2326_handle_threaded_irq(int irq, void *data)
{}

/**
 * zpa2326_wait_oneshot_completion() - Wait for oneshot data ready interrupt.
 * @indio_dev: The IIO device associated with the sampling hardware.
 * @private:   Internal private state related to @indio_dev.
 *
 * Return: Zero when successful, a negative error code otherwise.
 */
static int zpa2326_wait_oneshot_completion(const struct iio_dev   *indio_dev,
					   struct zpa2326_private *private)
{}

static int zpa2326_init_managed_irq(struct device          *parent,
				    struct iio_dev         *indio_dev,
				    struct zpa2326_private *private,
				    int                     irq)
{}

/**
 * zpa2326_poll_oneshot_completion() - Actively poll for one shot data ready.
 * @indio_dev: The IIO device associated with the sampling hardware.
 *
 * Loop over registers content to detect end of sampling cycle. Used when DT
 * declared no valid interrupt lines.
 *
 * Return: Zero when successful, a negative error code otherwise.
 */
static int zpa2326_poll_oneshot_completion(const struct iio_dev *indio_dev)
{}

/**
 * zpa2326_fetch_raw_sample() - Retrieve a raw sample and convert it to CPU
 *                              endianness.
 * @indio_dev: The IIO device associated with the sampling hardware.
 * @type:      Type of measurement / channel to fetch from.
 * @value:     Sample output.
 *
 * Return: Zero when successful, a negative error code otherwise.
 */
static int zpa2326_fetch_raw_sample(const struct iio_dev *indio_dev,
				    enum iio_chan_type    type,
				    int                  *value)
{}

/**
 * zpa2326_sample_oneshot() - Perform a complete one shot sampling cycle.
 * @indio_dev: The IIO device associated with the sampling hardware.
 * @type:      Type of measurement / channel to fetch from.
 * @value:     Sample output.
 *
 * Return: Zero when successful, a negative error code otherwise.
 */
static int zpa2326_sample_oneshot(struct iio_dev     *indio_dev,
				  enum iio_chan_type  type,
				  int                *value)
{}

/**
 * zpa2326_trigger_handler() - Perform an IIO buffered sampling round in one
 *                             shot mode.
 * @irq:  The software interrupt assigned to @data
 * @data: The IIO poll function dispatched by external trigger our device is
 *        attached to.
 *
 * Bottom-half handler called by the IIO trigger to which our device is
 * currently attached. Allows us to synchronize this device buffered sampling
 * either with external events (such as timer expiration, external device sample
 * ready, etc...) or with its own interrupt (internal hardware trigger).
 *
 * When using an external trigger, basically run the same sequence of operations
 * as for zpa2326_sample_oneshot() with the following hereafter. Hardware FIFO
 * is not cleared since already done at buffering enable time and samples
 * dequeueing always retrieves the most recent value.
 *
 * Otherwise, when internal hardware trigger has dispatched us, just fetch data
 * from hardware FIFO.
 *
 * Fetched data will pushed unprocessed to IIO buffer since samples conversion
 * is delegated to userspace in buffered mode (endianness, etc...).
 *
 * Return:
 *   %IRQ_NONE - no consistent interrupt happened ;
 *   %IRQ_HANDLED - there was new samples available.
 */
static irqreturn_t zpa2326_trigger_handler(int irq, void *data)
{}

/**
 * zpa2326_preenable_buffer() - Prepare device for configuring triggered
 *                              sampling
 * modes.
 * @indio_dev: The IIO device associated with the sampling hardware.
 *
 * Basically power up device.
 * Called with IIO device's lock held.
 *
 * Return: Zero when successful, a negative error code otherwise.
 */
static int zpa2326_preenable_buffer(struct iio_dev *indio_dev)
{}

/**
 * zpa2326_postenable_buffer() - Configure device for triggered sampling.
 * @indio_dev: The IIO device associated with the sampling hardware.
 *
 * Basically setup one-shot mode if plugging external trigger.
 * Otherwise, let internal trigger configure continuous sampling :
 * see zpa2326_set_trigger_state().
 *
 * If an error is returned, IIO layer will call our postdisable hook for us,
 * i.e. no need to explicitly power device off here.
 * Called with IIO device's lock held.
 *
 * Called with IIO device's lock held.
 *
 * Return: Zero when successful, a negative error code otherwise.
 */
static int zpa2326_postenable_buffer(struct iio_dev *indio_dev)
{}

static int zpa2326_postdisable_buffer(struct iio_dev *indio_dev)
{}

static const struct iio_buffer_setup_ops zpa2326_buffer_setup_ops =;

/**
 * zpa2326_set_trigger_state() - Start / stop continuous sampling.
 * @trig:  The trigger being attached to IIO device associated with the sampling
 *         hardware.
 * @state: Tell whether to start (true) or stop (false)
 *
 * Basically enable / disable hardware continuous sampling mode.
 *
 * Called with IIO device's lock held at postenable() or predisable() time.
 *
 * Return: Zero when successful, a negative error code otherwise.
 */
static int zpa2326_set_trigger_state(struct iio_trigger *trig, bool state)
{}

static const struct iio_trigger_ops zpa2326_trigger_ops =;

/**
 * zpa2326_init_managed_trigger() - Create interrupt driven / hardware trigger
 *                          allowing to notify external devices a new sample is
 *                          ready.
 * @parent:    Hardware sampling device @indio_dev is a child of.
 * @indio_dev: The IIO device associated with the sampling hardware.
 * @private:   Internal private state related to @indio_dev.
 * @irq:       Optional interrupt line the hardware uses to notify new data
 *             samples are ready. Negative or zero values indicate no interrupts
 *             are available, meaning polling is required.
 *
 * Only relevant when DT declares a valid interrupt line.
 *
 * Return: Zero when successful, a negative error code otherwise.
 */
static int zpa2326_init_managed_trigger(struct device          *parent,
					struct iio_dev         *indio_dev,
					struct zpa2326_private *private,
					int                     irq)
{}

static int zpa2326_get_frequency(const struct iio_dev *indio_dev)
{}

static int zpa2326_set_frequency(struct iio_dev *indio_dev, int hz)
{}

/* Expose supported hardware sampling frequencies (Hz) through sysfs. */
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("1 5 11 23");

static struct attribute *zpa2326_attributes[] =;

static const struct attribute_group zpa2326_attribute_group =;

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

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

static const struct iio_chan_spec zpa2326_channels[] =;

static const struct iio_info zpa2326_info =;

static struct iio_dev *zpa2326_create_managed_iiodev(struct device *device,
						     const char    *name,
						     struct regmap *regmap)
{}

int zpa2326_probe(struct device *parent,
		  const char    *name,
		  int            irq,
		  unsigned int   hwid,
		  struct regmap *regmap)
{}
EXPORT_SYMBOL_NS_GPL();

void zpa2326_remove(const struct device *parent)
{}
EXPORT_SYMBOL_NS_GPL();

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