18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Murata ZPA2326 pressure and temperature sensor IIO driver
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2016 Parrot S.A.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Author: Gregor Boirie <gregor.boirie@parrot.com>
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci/**
118c2ecf20Sopenharmony_ci * DOC: ZPA2326 theory of operations
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * This driver supports %INDIO_DIRECT_MODE and %INDIO_BUFFER_TRIGGERED IIO
148c2ecf20Sopenharmony_ci * modes.
158c2ecf20Sopenharmony_ci * A internal hardware trigger is also implemented to dispatch registered IIO
168c2ecf20Sopenharmony_ci * trigger consumers upon "sample ready" interrupts.
178c2ecf20Sopenharmony_ci *
188c2ecf20Sopenharmony_ci * ZPA2326 hardware supports 2 sampling mode: one shot and continuous.
198c2ecf20Sopenharmony_ci *
208c2ecf20Sopenharmony_ci * A complete one shot sampling cycle gets device out of low power mode,
218c2ecf20Sopenharmony_ci * performs pressure and temperature measurements, then automatically switches
228c2ecf20Sopenharmony_ci * back to low power mode. It is meant for on demand sampling with optimal power
238c2ecf20Sopenharmony_ci * saving at the cost of lower sampling rate and higher software overhead.
248c2ecf20Sopenharmony_ci * This is a natural candidate for IIO read_raw hook implementation
258c2ecf20Sopenharmony_ci * (%INDIO_DIRECT_MODE). It is also used for triggered buffering support to
268c2ecf20Sopenharmony_ci * ensure explicit synchronization with external trigger events
278c2ecf20Sopenharmony_ci * (%INDIO_BUFFER_TRIGGERED).
288c2ecf20Sopenharmony_ci *
298c2ecf20Sopenharmony_ci * The continuous mode works according to a periodic hardware measurement
308c2ecf20Sopenharmony_ci * process continuously pushing samples into an internal hardware FIFO (for
318c2ecf20Sopenharmony_ci * pressure samples only). Measurement cycle completion may be signaled by a
328c2ecf20Sopenharmony_ci * "sample ready" interrupt.
338c2ecf20Sopenharmony_ci * Typical software sequence of operations :
348c2ecf20Sopenharmony_ci * - get device out of low power mode,
358c2ecf20Sopenharmony_ci * - setup hardware sampling period,
368c2ecf20Sopenharmony_ci * - at end of period, upon data ready interrupt: pop pressure samples out of
378c2ecf20Sopenharmony_ci *   hardware FIFO and fetch temperature sample
388c2ecf20Sopenharmony_ci * - when no longer needed, stop sampling process by putting device into
398c2ecf20Sopenharmony_ci *   low power mode.
408c2ecf20Sopenharmony_ci * This mode is used to implement %INDIO_BUFFER_TRIGGERED mode if device tree
418c2ecf20Sopenharmony_ci * declares a valid interrupt line. In this case, the internal hardware trigger
428c2ecf20Sopenharmony_ci * drives acquisition.
438c2ecf20Sopenharmony_ci *
448c2ecf20Sopenharmony_ci * Note that hardware sampling frequency is taken into account only when
458c2ecf20Sopenharmony_ci * internal hardware trigger is attached as the highest sampling rate seems to
468c2ecf20Sopenharmony_ci * be the most energy efficient.
478c2ecf20Sopenharmony_ci *
488c2ecf20Sopenharmony_ci * TODO:
498c2ecf20Sopenharmony_ci *   preset pressure threshold crossing / IIO events ;
508c2ecf20Sopenharmony_ci *   differential pressure sampling ;
518c2ecf20Sopenharmony_ci *   hardware samples averaging.
528c2ecf20Sopenharmony_ci */
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci#include <linux/module.h>
558c2ecf20Sopenharmony_ci#include <linux/kernel.h>
568c2ecf20Sopenharmony_ci#include <linux/delay.h>
578c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
588c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h>
598c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h>
608c2ecf20Sopenharmony_ci#include <linux/regmap.h>
618c2ecf20Sopenharmony_ci#include <linux/iio/iio.h>
628c2ecf20Sopenharmony_ci#include <linux/iio/sysfs.h>
638c2ecf20Sopenharmony_ci#include <linux/iio/buffer.h>
648c2ecf20Sopenharmony_ci#include <linux/iio/trigger.h>
658c2ecf20Sopenharmony_ci#include <linux/iio/trigger_consumer.h>
668c2ecf20Sopenharmony_ci#include <linux/iio/triggered_buffer.h>
678c2ecf20Sopenharmony_ci#include <asm/unaligned.h>
688c2ecf20Sopenharmony_ci#include "zpa2326.h"
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci/* 200 ms should be enough for the longest conversion time in one-shot mode. */
718c2ecf20Sopenharmony_ci#define ZPA2326_CONVERSION_JIFFIES (HZ / 5)
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci/* There should be a 1 ms delay (Tpup) after getting out of reset. */
748c2ecf20Sopenharmony_ci#define ZPA2326_TPUP_USEC_MIN      (1000)
758c2ecf20Sopenharmony_ci#define ZPA2326_TPUP_USEC_MAX      (2000)
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci/**
788c2ecf20Sopenharmony_ci * struct zpa2326_frequency - Hardware sampling frequency descriptor
798c2ecf20Sopenharmony_ci * @hz : Frequency in Hertz.
808c2ecf20Sopenharmony_ci * @odr: Output Data Rate word as expected by %ZPA2326_CTRL_REG3_REG.
818c2ecf20Sopenharmony_ci */
828c2ecf20Sopenharmony_cistruct zpa2326_frequency {
838c2ecf20Sopenharmony_ci	int hz;
848c2ecf20Sopenharmony_ci	u16 odr;
858c2ecf20Sopenharmony_ci};
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci/*
888c2ecf20Sopenharmony_ci * Keep these in strict ascending order: last array entry is expected to
898c2ecf20Sopenharmony_ci * correspond to the highest sampling frequency.
908c2ecf20Sopenharmony_ci */
918c2ecf20Sopenharmony_cistatic const struct zpa2326_frequency zpa2326_sampling_frequencies[] = {
928c2ecf20Sopenharmony_ci	{ .hz = 1,  .odr = 1 << ZPA2326_CTRL_REG3_ODR_SHIFT },
938c2ecf20Sopenharmony_ci	{ .hz = 5,  .odr = 5 << ZPA2326_CTRL_REG3_ODR_SHIFT },
948c2ecf20Sopenharmony_ci	{ .hz = 11, .odr = 6 << ZPA2326_CTRL_REG3_ODR_SHIFT },
958c2ecf20Sopenharmony_ci	{ .hz = 23, .odr = 7 << ZPA2326_CTRL_REG3_ODR_SHIFT },
968c2ecf20Sopenharmony_ci};
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci/* Return the highest hardware sampling frequency available. */
998c2ecf20Sopenharmony_cistatic const struct zpa2326_frequency *zpa2326_highest_frequency(void)
1008c2ecf20Sopenharmony_ci{
1018c2ecf20Sopenharmony_ci	return &zpa2326_sampling_frequencies[
1028c2ecf20Sopenharmony_ci		ARRAY_SIZE(zpa2326_sampling_frequencies) - 1];
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci/**
1068c2ecf20Sopenharmony_ci * struct zpa_private - Per-device internal private state
1078c2ecf20Sopenharmony_ci * @timestamp:  Buffered samples ready datum.
1088c2ecf20Sopenharmony_ci * @regmap:     Underlying I2C / SPI bus adapter used to abstract slave register
1098c2ecf20Sopenharmony_ci *              accesses.
1108c2ecf20Sopenharmony_ci * @result:     Allows sampling logic to get completion status of operations
1118c2ecf20Sopenharmony_ci *              that interrupt handlers perform asynchronously.
1128c2ecf20Sopenharmony_ci * @data_ready: Interrupt handler uses this to wake user context up at sampling
1138c2ecf20Sopenharmony_ci *              operation completion.
1148c2ecf20Sopenharmony_ci * @trigger:    Optional hardware / interrupt driven trigger used to notify
1158c2ecf20Sopenharmony_ci *              external devices a new sample is ready.
1168c2ecf20Sopenharmony_ci * @waken:      Flag indicating whether or not device has just been powered on.
1178c2ecf20Sopenharmony_ci * @irq:        Optional interrupt line: negative or zero if not declared into
1188c2ecf20Sopenharmony_ci *              DT, in which case sampling logic keeps polling status register
1198c2ecf20Sopenharmony_ci *              to detect completion.
1208c2ecf20Sopenharmony_ci * @frequency:  Current hardware sampling frequency.
1218c2ecf20Sopenharmony_ci * @vref:       Power / voltage reference.
1228c2ecf20Sopenharmony_ci * @vdd:        Power supply.
1238c2ecf20Sopenharmony_ci */
1248c2ecf20Sopenharmony_cistruct zpa2326_private {
1258c2ecf20Sopenharmony_ci	s64                             timestamp;
1268c2ecf20Sopenharmony_ci	struct regmap                  *regmap;
1278c2ecf20Sopenharmony_ci	int                             result;
1288c2ecf20Sopenharmony_ci	struct completion               data_ready;
1298c2ecf20Sopenharmony_ci	struct iio_trigger             *trigger;
1308c2ecf20Sopenharmony_ci	bool                            waken;
1318c2ecf20Sopenharmony_ci	int                             irq;
1328c2ecf20Sopenharmony_ci	const struct zpa2326_frequency *frequency;
1338c2ecf20Sopenharmony_ci	struct regulator               *vref;
1348c2ecf20Sopenharmony_ci	struct regulator               *vdd;
1358c2ecf20Sopenharmony_ci};
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci#define zpa2326_err(idev, fmt, ...)					\
1388c2ecf20Sopenharmony_ci	dev_err(idev->dev.parent, fmt "\n", ##__VA_ARGS__)
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci#define zpa2326_warn(idev, fmt, ...)					\
1418c2ecf20Sopenharmony_ci	dev_warn(idev->dev.parent, fmt "\n", ##__VA_ARGS__)
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci#define zpa2326_dbg(idev, fmt, ...)					\
1448c2ecf20Sopenharmony_ci	dev_dbg(idev->dev.parent, fmt "\n", ##__VA_ARGS__)
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_cibool zpa2326_isreg_writeable(struct device *dev, unsigned int reg)
1478c2ecf20Sopenharmony_ci{
1488c2ecf20Sopenharmony_ci	switch (reg) {
1498c2ecf20Sopenharmony_ci	case ZPA2326_REF_P_XL_REG:
1508c2ecf20Sopenharmony_ci	case ZPA2326_REF_P_L_REG:
1518c2ecf20Sopenharmony_ci	case ZPA2326_REF_P_H_REG:
1528c2ecf20Sopenharmony_ci	case ZPA2326_RES_CONF_REG:
1538c2ecf20Sopenharmony_ci	case ZPA2326_CTRL_REG0_REG:
1548c2ecf20Sopenharmony_ci	case ZPA2326_CTRL_REG1_REG:
1558c2ecf20Sopenharmony_ci	case ZPA2326_CTRL_REG2_REG:
1568c2ecf20Sopenharmony_ci	case ZPA2326_CTRL_REG3_REG:
1578c2ecf20Sopenharmony_ci	case ZPA2326_THS_P_LOW_REG:
1588c2ecf20Sopenharmony_ci	case ZPA2326_THS_P_HIGH_REG:
1598c2ecf20Sopenharmony_ci		return true;
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	default:
1628c2ecf20Sopenharmony_ci		return false;
1638c2ecf20Sopenharmony_ci	}
1648c2ecf20Sopenharmony_ci}
1658c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(zpa2326_isreg_writeable);
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_cibool zpa2326_isreg_readable(struct device *dev, unsigned int reg)
1688c2ecf20Sopenharmony_ci{
1698c2ecf20Sopenharmony_ci	switch (reg) {
1708c2ecf20Sopenharmony_ci	case ZPA2326_REF_P_XL_REG:
1718c2ecf20Sopenharmony_ci	case ZPA2326_REF_P_L_REG:
1728c2ecf20Sopenharmony_ci	case ZPA2326_REF_P_H_REG:
1738c2ecf20Sopenharmony_ci	case ZPA2326_DEVICE_ID_REG:
1748c2ecf20Sopenharmony_ci	case ZPA2326_RES_CONF_REG:
1758c2ecf20Sopenharmony_ci	case ZPA2326_CTRL_REG0_REG:
1768c2ecf20Sopenharmony_ci	case ZPA2326_CTRL_REG1_REG:
1778c2ecf20Sopenharmony_ci	case ZPA2326_CTRL_REG2_REG:
1788c2ecf20Sopenharmony_ci	case ZPA2326_CTRL_REG3_REG:
1798c2ecf20Sopenharmony_ci	case ZPA2326_INT_SOURCE_REG:
1808c2ecf20Sopenharmony_ci	case ZPA2326_THS_P_LOW_REG:
1818c2ecf20Sopenharmony_ci	case ZPA2326_THS_P_HIGH_REG:
1828c2ecf20Sopenharmony_ci	case ZPA2326_STATUS_REG:
1838c2ecf20Sopenharmony_ci	case ZPA2326_PRESS_OUT_XL_REG:
1848c2ecf20Sopenharmony_ci	case ZPA2326_PRESS_OUT_L_REG:
1858c2ecf20Sopenharmony_ci	case ZPA2326_PRESS_OUT_H_REG:
1868c2ecf20Sopenharmony_ci	case ZPA2326_TEMP_OUT_L_REG:
1878c2ecf20Sopenharmony_ci	case ZPA2326_TEMP_OUT_H_REG:
1888c2ecf20Sopenharmony_ci		return true;
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	default:
1918c2ecf20Sopenharmony_ci		return false;
1928c2ecf20Sopenharmony_ci	}
1938c2ecf20Sopenharmony_ci}
1948c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(zpa2326_isreg_readable);
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_cibool zpa2326_isreg_precious(struct device *dev, unsigned int reg)
1978c2ecf20Sopenharmony_ci{
1988c2ecf20Sopenharmony_ci	switch (reg) {
1998c2ecf20Sopenharmony_ci	case ZPA2326_INT_SOURCE_REG:
2008c2ecf20Sopenharmony_ci	case ZPA2326_PRESS_OUT_H_REG:
2018c2ecf20Sopenharmony_ci		return true;
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	default:
2048c2ecf20Sopenharmony_ci		return false;
2058c2ecf20Sopenharmony_ci	}
2068c2ecf20Sopenharmony_ci}
2078c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(zpa2326_isreg_precious);
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci/**
2108c2ecf20Sopenharmony_ci * zpa2326_enable_device() - Enable device, i.e. get out of low power mode.
2118c2ecf20Sopenharmony_ci * @indio_dev: The IIO device associated with the hardware to enable.
2128c2ecf20Sopenharmony_ci *
2138c2ecf20Sopenharmony_ci * Required to access complete register space and to perform any sampling
2148c2ecf20Sopenharmony_ci * or control operations.
2158c2ecf20Sopenharmony_ci *
2168c2ecf20Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise.
2178c2ecf20Sopenharmony_ci */
2188c2ecf20Sopenharmony_cistatic int zpa2326_enable_device(const struct iio_dev *indio_dev)
2198c2ecf20Sopenharmony_ci{
2208c2ecf20Sopenharmony_ci	int err;
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	err = regmap_write(((struct zpa2326_private *)
2238c2ecf20Sopenharmony_ci			    iio_priv(indio_dev))->regmap,
2248c2ecf20Sopenharmony_ci			    ZPA2326_CTRL_REG0_REG, ZPA2326_CTRL_REG0_ENABLE);
2258c2ecf20Sopenharmony_ci	if (err) {
2268c2ecf20Sopenharmony_ci		zpa2326_err(indio_dev, "failed to enable device (%d)", err);
2278c2ecf20Sopenharmony_ci		return err;
2288c2ecf20Sopenharmony_ci	}
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	zpa2326_dbg(indio_dev, "enabled");
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	return 0;
2338c2ecf20Sopenharmony_ci}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci/**
2368c2ecf20Sopenharmony_ci * zpa2326_sleep() - Disable device, i.e. switch to low power mode.
2378c2ecf20Sopenharmony_ci * @indio_dev: The IIO device associated with the hardware to disable.
2388c2ecf20Sopenharmony_ci *
2398c2ecf20Sopenharmony_ci * Only %ZPA2326_DEVICE_ID_REG and %ZPA2326_CTRL_REG0_REG registers may be
2408c2ecf20Sopenharmony_ci * accessed once device is in the disabled state.
2418c2ecf20Sopenharmony_ci *
2428c2ecf20Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise.
2438c2ecf20Sopenharmony_ci */
2448c2ecf20Sopenharmony_cistatic int zpa2326_sleep(const struct iio_dev *indio_dev)
2458c2ecf20Sopenharmony_ci{
2468c2ecf20Sopenharmony_ci	int err;
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	err = regmap_write(((struct zpa2326_private *)
2498c2ecf20Sopenharmony_ci			    iio_priv(indio_dev))->regmap,
2508c2ecf20Sopenharmony_ci			    ZPA2326_CTRL_REG0_REG, 0);
2518c2ecf20Sopenharmony_ci	if (err) {
2528c2ecf20Sopenharmony_ci		zpa2326_err(indio_dev, "failed to sleep (%d)", err);
2538c2ecf20Sopenharmony_ci		return err;
2548c2ecf20Sopenharmony_ci	}
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	zpa2326_dbg(indio_dev, "sleeping");
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	return 0;
2598c2ecf20Sopenharmony_ci}
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci/**
2628c2ecf20Sopenharmony_ci * zpa2326_reset_device() - Reset device to default hardware state.
2638c2ecf20Sopenharmony_ci * @indio_dev: The IIO device associated with the hardware to reset.
2648c2ecf20Sopenharmony_ci *
2658c2ecf20Sopenharmony_ci * Disable sampling and empty hardware FIFO.
2668c2ecf20Sopenharmony_ci * Device must be enabled before reset, i.e. not in low power mode.
2678c2ecf20Sopenharmony_ci *
2688c2ecf20Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise.
2698c2ecf20Sopenharmony_ci */
2708c2ecf20Sopenharmony_cistatic int zpa2326_reset_device(const struct iio_dev *indio_dev)
2718c2ecf20Sopenharmony_ci{
2728c2ecf20Sopenharmony_ci	int err;
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	err = regmap_write(((struct zpa2326_private *)
2758c2ecf20Sopenharmony_ci			    iio_priv(indio_dev))->regmap,
2768c2ecf20Sopenharmony_ci			    ZPA2326_CTRL_REG2_REG, ZPA2326_CTRL_REG2_SWRESET);
2778c2ecf20Sopenharmony_ci	if (err) {
2788c2ecf20Sopenharmony_ci		zpa2326_err(indio_dev, "failed to reset device (%d)", err);
2798c2ecf20Sopenharmony_ci		return err;
2808c2ecf20Sopenharmony_ci	}
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	usleep_range(ZPA2326_TPUP_USEC_MIN, ZPA2326_TPUP_USEC_MAX);
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	zpa2326_dbg(indio_dev, "reset");
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	return 0;
2878c2ecf20Sopenharmony_ci}
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci/**
2908c2ecf20Sopenharmony_ci * zpa2326_start_oneshot() - Start a single sampling cycle, i.e. in one shot
2918c2ecf20Sopenharmony_ci *                           mode.
2928c2ecf20Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware.
2938c2ecf20Sopenharmony_ci *
2948c2ecf20Sopenharmony_ci * Device must have been previously enabled and configured for one shot mode.
2958c2ecf20Sopenharmony_ci * Device will be switched back to low power mode at end of cycle.
2968c2ecf20Sopenharmony_ci *
2978c2ecf20Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise.
2988c2ecf20Sopenharmony_ci */
2998c2ecf20Sopenharmony_cistatic int zpa2326_start_oneshot(const struct iio_dev *indio_dev)
3008c2ecf20Sopenharmony_ci{
3018c2ecf20Sopenharmony_ci	int err;
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	err = regmap_write(((struct zpa2326_private *)
3048c2ecf20Sopenharmony_ci			    iio_priv(indio_dev))->regmap,
3058c2ecf20Sopenharmony_ci			    ZPA2326_CTRL_REG0_REG,
3068c2ecf20Sopenharmony_ci			    ZPA2326_CTRL_REG0_ENABLE |
3078c2ecf20Sopenharmony_ci			    ZPA2326_CTRL_REG0_ONE_SHOT);
3088c2ecf20Sopenharmony_ci	if (err) {
3098c2ecf20Sopenharmony_ci		zpa2326_err(indio_dev, "failed to start one shot cycle (%d)",
3108c2ecf20Sopenharmony_ci			    err);
3118c2ecf20Sopenharmony_ci		return err;
3128c2ecf20Sopenharmony_ci	}
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	zpa2326_dbg(indio_dev, "one shot cycle started");
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	return 0;
3178c2ecf20Sopenharmony_ci}
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci/**
3208c2ecf20Sopenharmony_ci * zpa2326_power_on() - Power on device to allow subsequent configuration.
3218c2ecf20Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware.
3228c2ecf20Sopenharmony_ci * @private:   Internal private state related to @indio_dev.
3238c2ecf20Sopenharmony_ci *
3248c2ecf20Sopenharmony_ci * Sampling will be disabled, preventing strange things from happening in our
3258c2ecf20Sopenharmony_ci * back. Hardware FIFO content will be cleared.
3268c2ecf20Sopenharmony_ci * When successful, device will be left in the enabled state to allow further
3278c2ecf20Sopenharmony_ci * configuration.
3288c2ecf20Sopenharmony_ci *
3298c2ecf20Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise.
3308c2ecf20Sopenharmony_ci */
3318c2ecf20Sopenharmony_cistatic int zpa2326_power_on(const struct iio_dev         *indio_dev,
3328c2ecf20Sopenharmony_ci			    const struct zpa2326_private *private)
3338c2ecf20Sopenharmony_ci{
3348c2ecf20Sopenharmony_ci	int err;
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	err = regulator_enable(private->vref);
3378c2ecf20Sopenharmony_ci	if (err)
3388c2ecf20Sopenharmony_ci		return err;
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	err = regulator_enable(private->vdd);
3418c2ecf20Sopenharmony_ci	if (err)
3428c2ecf20Sopenharmony_ci		goto vref;
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci	zpa2326_dbg(indio_dev, "powered on");
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	err = zpa2326_enable_device(indio_dev);
3478c2ecf20Sopenharmony_ci	if (err)
3488c2ecf20Sopenharmony_ci		goto vdd;
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	err = zpa2326_reset_device(indio_dev);
3518c2ecf20Sopenharmony_ci	if (err)
3528c2ecf20Sopenharmony_ci		goto sleep;
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	return 0;
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_cisleep:
3578c2ecf20Sopenharmony_ci	zpa2326_sleep(indio_dev);
3588c2ecf20Sopenharmony_civdd:
3598c2ecf20Sopenharmony_ci	regulator_disable(private->vdd);
3608c2ecf20Sopenharmony_civref:
3618c2ecf20Sopenharmony_ci	regulator_disable(private->vref);
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci	zpa2326_dbg(indio_dev, "powered off");
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	return err;
3668c2ecf20Sopenharmony_ci}
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci/**
3698c2ecf20Sopenharmony_ci * zpa2326_power_off() - Power off device, i.e. disable attached power
3708c2ecf20Sopenharmony_ci *                       regulators.
3718c2ecf20Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware.
3728c2ecf20Sopenharmony_ci * @private:   Internal private state related to @indio_dev.
3738c2ecf20Sopenharmony_ci *
3748c2ecf20Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise.
3758c2ecf20Sopenharmony_ci */
3768c2ecf20Sopenharmony_cistatic void zpa2326_power_off(const struct iio_dev         *indio_dev,
3778c2ecf20Sopenharmony_ci			      const struct zpa2326_private *private)
3788c2ecf20Sopenharmony_ci{
3798c2ecf20Sopenharmony_ci	regulator_disable(private->vdd);
3808c2ecf20Sopenharmony_ci	regulator_disable(private->vref);
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	zpa2326_dbg(indio_dev, "powered off");
3838c2ecf20Sopenharmony_ci}
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci/**
3868c2ecf20Sopenharmony_ci * zpa2326_config_oneshot() - Setup device for one shot / on demand mode.
3878c2ecf20Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware.
3888c2ecf20Sopenharmony_ci * @irq:       Optional interrupt line the hardware uses to notify new data
3898c2ecf20Sopenharmony_ci *             samples are ready. Negative or zero values indicate no interrupts
3908c2ecf20Sopenharmony_ci *             are available, meaning polling is required.
3918c2ecf20Sopenharmony_ci *
3928c2ecf20Sopenharmony_ci * Output Data Rate is configured for the highest possible rate so that
3938c2ecf20Sopenharmony_ci * conversion time and power consumption are reduced to a minimum.
3948c2ecf20Sopenharmony_ci * Note that hardware internal averaging machinery (not implemented in this
3958c2ecf20Sopenharmony_ci * driver) is not applicable in this mode.
3968c2ecf20Sopenharmony_ci *
3978c2ecf20Sopenharmony_ci * Device must have been previously enabled before calling
3988c2ecf20Sopenharmony_ci * zpa2326_config_oneshot().
3998c2ecf20Sopenharmony_ci *
4008c2ecf20Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise.
4018c2ecf20Sopenharmony_ci */
4028c2ecf20Sopenharmony_cistatic int zpa2326_config_oneshot(const struct iio_dev *indio_dev,
4038c2ecf20Sopenharmony_ci				  int                   irq)
4048c2ecf20Sopenharmony_ci{
4058c2ecf20Sopenharmony_ci	struct regmap                  *regs = ((struct zpa2326_private *)
4068c2ecf20Sopenharmony_ci						iio_priv(indio_dev))->regmap;
4078c2ecf20Sopenharmony_ci	const struct zpa2326_frequency *freq = zpa2326_highest_frequency();
4088c2ecf20Sopenharmony_ci	int                             err;
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	/* Setup highest available Output Data Rate for one shot mode. */
4118c2ecf20Sopenharmony_ci	err = regmap_write(regs, ZPA2326_CTRL_REG3_REG, freq->odr);
4128c2ecf20Sopenharmony_ci	if (err)
4138c2ecf20Sopenharmony_ci		return err;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	if (irq > 0) {
4168c2ecf20Sopenharmony_ci		/* Request interrupt when new sample is available. */
4178c2ecf20Sopenharmony_ci		err = regmap_write(regs, ZPA2326_CTRL_REG1_REG,
4188c2ecf20Sopenharmony_ci				   (u8)~ZPA2326_CTRL_REG1_MASK_DATA_READY);
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci		if (err) {
4218c2ecf20Sopenharmony_ci			dev_err(indio_dev->dev.parent,
4228c2ecf20Sopenharmony_ci				"failed to setup one shot mode (%d)", err);
4238c2ecf20Sopenharmony_ci			return err;
4248c2ecf20Sopenharmony_ci		}
4258c2ecf20Sopenharmony_ci	}
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	zpa2326_dbg(indio_dev, "one shot mode setup @%dHz", freq->hz);
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	return 0;
4308c2ecf20Sopenharmony_ci}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci/**
4338c2ecf20Sopenharmony_ci * zpa2326_clear_fifo() - Clear remaining entries in hardware FIFO.
4348c2ecf20Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware.
4358c2ecf20Sopenharmony_ci * @min_count: Number of samples present within hardware FIFO.
4368c2ecf20Sopenharmony_ci *
4378c2ecf20Sopenharmony_ci * @min_count argument is a hint corresponding to the known minimum number of
4388c2ecf20Sopenharmony_ci * samples currently living in the FIFO. This allows to reduce the number of bus
4398c2ecf20Sopenharmony_ci * accesses by skipping status register read operation as long as we know for
4408c2ecf20Sopenharmony_ci * sure there are still entries left.
4418c2ecf20Sopenharmony_ci *
4428c2ecf20Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise.
4438c2ecf20Sopenharmony_ci */
4448c2ecf20Sopenharmony_cistatic int zpa2326_clear_fifo(const struct iio_dev *indio_dev,
4458c2ecf20Sopenharmony_ci			      unsigned int          min_count)
4468c2ecf20Sopenharmony_ci{
4478c2ecf20Sopenharmony_ci	struct regmap *regs = ((struct zpa2326_private *)
4488c2ecf20Sopenharmony_ci			       iio_priv(indio_dev))->regmap;
4498c2ecf20Sopenharmony_ci	int            err;
4508c2ecf20Sopenharmony_ci	unsigned int   val;
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci	if (!min_count) {
4538c2ecf20Sopenharmony_ci		/*
4548c2ecf20Sopenharmony_ci		 * No hint: read status register to determine whether FIFO is
4558c2ecf20Sopenharmony_ci		 * empty or not.
4568c2ecf20Sopenharmony_ci		 */
4578c2ecf20Sopenharmony_ci		err = regmap_read(regs, ZPA2326_STATUS_REG, &val);
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci		if (err < 0)
4608c2ecf20Sopenharmony_ci			goto err;
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci		if (val & ZPA2326_STATUS_FIFO_E)
4638c2ecf20Sopenharmony_ci			/* Fifo is empty: nothing to trash. */
4648c2ecf20Sopenharmony_ci			return 0;
4658c2ecf20Sopenharmony_ci	}
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	/* Clear FIFO. */
4688c2ecf20Sopenharmony_ci	do {
4698c2ecf20Sopenharmony_ci		/*
4708c2ecf20Sopenharmony_ci		 * A single fetch from pressure MSB register is enough to pop
4718c2ecf20Sopenharmony_ci		 * values out of FIFO.
4728c2ecf20Sopenharmony_ci		 */
4738c2ecf20Sopenharmony_ci		err = regmap_read(regs, ZPA2326_PRESS_OUT_H_REG, &val);
4748c2ecf20Sopenharmony_ci		if (err < 0)
4758c2ecf20Sopenharmony_ci			goto err;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci		if (min_count) {
4788c2ecf20Sopenharmony_ci			/*
4798c2ecf20Sopenharmony_ci			 * We know for sure there are at least min_count entries
4808c2ecf20Sopenharmony_ci			 * left in FIFO. Skip status register read.
4818c2ecf20Sopenharmony_ci			 */
4828c2ecf20Sopenharmony_ci			min_count--;
4838c2ecf20Sopenharmony_ci			continue;
4848c2ecf20Sopenharmony_ci		}
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci		err = regmap_read(regs, ZPA2326_STATUS_REG, &val);
4878c2ecf20Sopenharmony_ci		if (err < 0)
4888c2ecf20Sopenharmony_ci			goto err;
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	} while (!(val & ZPA2326_STATUS_FIFO_E));
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	zpa2326_dbg(indio_dev, "FIFO cleared");
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	return 0;
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_cierr:
4978c2ecf20Sopenharmony_ci	zpa2326_err(indio_dev, "failed to clear FIFO (%d)", err);
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	return err;
5008c2ecf20Sopenharmony_ci}
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci/**
5038c2ecf20Sopenharmony_ci * zpa2326_dequeue_pressure() - Retrieve the most recent pressure sample from
5048c2ecf20Sopenharmony_ci *                              hardware FIFO.
5058c2ecf20Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware.
5068c2ecf20Sopenharmony_ci * @pressure:  Sampled pressure output.
5078c2ecf20Sopenharmony_ci *
5088c2ecf20Sopenharmony_ci * Note that ZPA2326 hardware FIFO stores pressure samples only.
5098c2ecf20Sopenharmony_ci *
5108c2ecf20Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise.
5118c2ecf20Sopenharmony_ci */
5128c2ecf20Sopenharmony_cistatic int zpa2326_dequeue_pressure(const struct iio_dev *indio_dev,
5138c2ecf20Sopenharmony_ci				    u32                  *pressure)
5148c2ecf20Sopenharmony_ci{
5158c2ecf20Sopenharmony_ci	struct regmap *regs = ((struct zpa2326_private *)
5168c2ecf20Sopenharmony_ci			       iio_priv(indio_dev))->regmap;
5178c2ecf20Sopenharmony_ci	unsigned int   val;
5188c2ecf20Sopenharmony_ci	int            err;
5198c2ecf20Sopenharmony_ci	int            cleared = -1;
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	err = regmap_read(regs, ZPA2326_STATUS_REG, &val);
5228c2ecf20Sopenharmony_ci	if (err < 0)
5238c2ecf20Sopenharmony_ci		return err;
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci	*pressure = 0;
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	if (val & ZPA2326_STATUS_P_OR) {
5288c2ecf20Sopenharmony_ci		/*
5298c2ecf20Sopenharmony_ci		 * Fifo overrun : first sample dequeued from FIFO is the
5308c2ecf20Sopenharmony_ci		 * newest.
5318c2ecf20Sopenharmony_ci		 */
5328c2ecf20Sopenharmony_ci		zpa2326_warn(indio_dev, "FIFO overflow");
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci		err = regmap_bulk_read(regs, ZPA2326_PRESS_OUT_XL_REG, pressure,
5358c2ecf20Sopenharmony_ci				       3);
5368c2ecf20Sopenharmony_ci		if (err)
5378c2ecf20Sopenharmony_ci			return err;
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci#define ZPA2326_FIFO_DEPTH (16U)
5408c2ecf20Sopenharmony_ci		/* Hardware FIFO may hold no more than 16 pressure samples. */
5418c2ecf20Sopenharmony_ci		return zpa2326_clear_fifo(indio_dev, ZPA2326_FIFO_DEPTH - 1);
5428c2ecf20Sopenharmony_ci	}
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci	/*
5458c2ecf20Sopenharmony_ci	 * Fifo has not overflown : retrieve newest sample. We need to pop
5468c2ecf20Sopenharmony_ci	 * values out until FIFO is empty : last fetched pressure is the newest.
5478c2ecf20Sopenharmony_ci	 * In nominal cases, we should find a single queued sample only.
5488c2ecf20Sopenharmony_ci	 */
5498c2ecf20Sopenharmony_ci	do {
5508c2ecf20Sopenharmony_ci		err = regmap_bulk_read(regs, ZPA2326_PRESS_OUT_XL_REG, pressure,
5518c2ecf20Sopenharmony_ci				       3);
5528c2ecf20Sopenharmony_ci		if (err)
5538c2ecf20Sopenharmony_ci			return err;
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci		err = regmap_read(regs, ZPA2326_STATUS_REG, &val);
5568c2ecf20Sopenharmony_ci		if (err < 0)
5578c2ecf20Sopenharmony_ci			return err;
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci		cleared++;
5608c2ecf20Sopenharmony_ci	} while (!(val & ZPA2326_STATUS_FIFO_E));
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	if (cleared)
5638c2ecf20Sopenharmony_ci		/*
5648c2ecf20Sopenharmony_ci		 * Samples were pushed by hardware during previous rounds but we
5658c2ecf20Sopenharmony_ci		 * didn't consume them fast enough: inform user.
5668c2ecf20Sopenharmony_ci		 */
5678c2ecf20Sopenharmony_ci		zpa2326_dbg(indio_dev, "cleared %d FIFO entries", cleared);
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	return 0;
5708c2ecf20Sopenharmony_ci}
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci/**
5738c2ecf20Sopenharmony_ci * zpa2326_fill_sample_buffer() - Enqueue new channel samples to IIO buffer.
5748c2ecf20Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware.
5758c2ecf20Sopenharmony_ci * @private:   Internal private state related to @indio_dev.
5768c2ecf20Sopenharmony_ci *
5778c2ecf20Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise.
5788c2ecf20Sopenharmony_ci */
5798c2ecf20Sopenharmony_cistatic int zpa2326_fill_sample_buffer(struct iio_dev               *indio_dev,
5808c2ecf20Sopenharmony_ci				      const struct zpa2326_private *private)
5818c2ecf20Sopenharmony_ci{
5828c2ecf20Sopenharmony_ci	struct {
5838c2ecf20Sopenharmony_ci		u32 pressure;
5848c2ecf20Sopenharmony_ci		u16 temperature;
5858c2ecf20Sopenharmony_ci		u64 timestamp;
5868c2ecf20Sopenharmony_ci	}   sample;
5878c2ecf20Sopenharmony_ci	int err;
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	if (test_bit(0, indio_dev->active_scan_mask)) {
5908c2ecf20Sopenharmony_ci		/* Get current pressure from hardware FIFO. */
5918c2ecf20Sopenharmony_ci		err = zpa2326_dequeue_pressure(indio_dev, &sample.pressure);
5928c2ecf20Sopenharmony_ci		if (err) {
5938c2ecf20Sopenharmony_ci			zpa2326_warn(indio_dev, "failed to fetch pressure (%d)",
5948c2ecf20Sopenharmony_ci				     err);
5958c2ecf20Sopenharmony_ci			return err;
5968c2ecf20Sopenharmony_ci		}
5978c2ecf20Sopenharmony_ci	}
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	if (test_bit(1, indio_dev->active_scan_mask)) {
6008c2ecf20Sopenharmony_ci		/* Get current temperature. */
6018c2ecf20Sopenharmony_ci		err = regmap_bulk_read(private->regmap, ZPA2326_TEMP_OUT_L_REG,
6028c2ecf20Sopenharmony_ci				       &sample.temperature, 2);
6038c2ecf20Sopenharmony_ci		if (err) {
6048c2ecf20Sopenharmony_ci			zpa2326_warn(indio_dev,
6058c2ecf20Sopenharmony_ci				     "failed to fetch temperature (%d)", err);
6068c2ecf20Sopenharmony_ci			return err;
6078c2ecf20Sopenharmony_ci		}
6088c2ecf20Sopenharmony_ci	}
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	/*
6118c2ecf20Sopenharmony_ci	 * Now push samples using timestamp stored either :
6128c2ecf20Sopenharmony_ci	 *   - by hardware interrupt handler if interrupt is available: see
6138c2ecf20Sopenharmony_ci	 *     zpa2326_handle_irq(),
6148c2ecf20Sopenharmony_ci	 *   - or oneshot completion polling machinery : see
6158c2ecf20Sopenharmony_ci	 *     zpa2326_trigger_handler().
6168c2ecf20Sopenharmony_ci	 */
6178c2ecf20Sopenharmony_ci	zpa2326_dbg(indio_dev, "filling raw samples buffer");
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	iio_push_to_buffers_with_timestamp(indio_dev, &sample,
6208c2ecf20Sopenharmony_ci					   private->timestamp);
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	return 0;
6238c2ecf20Sopenharmony_ci}
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
6268c2ecf20Sopenharmony_cistatic int zpa2326_runtime_suspend(struct device *parent)
6278c2ecf20Sopenharmony_ci{
6288c2ecf20Sopenharmony_ci	const struct iio_dev *indio_dev = dev_get_drvdata(parent);
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	if (pm_runtime_autosuspend_expiration(parent))
6318c2ecf20Sopenharmony_ci		/* Userspace changed autosuspend delay. */
6328c2ecf20Sopenharmony_ci		return -EAGAIN;
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	zpa2326_power_off(indio_dev, iio_priv(indio_dev));
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci	return 0;
6378c2ecf20Sopenharmony_ci}
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_cistatic int zpa2326_runtime_resume(struct device *parent)
6408c2ecf20Sopenharmony_ci{
6418c2ecf20Sopenharmony_ci	const struct iio_dev *indio_dev = dev_get_drvdata(parent);
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_ci	return zpa2326_power_on(indio_dev, iio_priv(indio_dev));
6448c2ecf20Sopenharmony_ci}
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ciconst struct dev_pm_ops zpa2326_pm_ops = {
6478c2ecf20Sopenharmony_ci	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
6488c2ecf20Sopenharmony_ci				pm_runtime_force_resume)
6498c2ecf20Sopenharmony_ci	SET_RUNTIME_PM_OPS(zpa2326_runtime_suspend, zpa2326_runtime_resume,
6508c2ecf20Sopenharmony_ci			   NULL)
6518c2ecf20Sopenharmony_ci};
6528c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(zpa2326_pm_ops);
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_ci/**
6558c2ecf20Sopenharmony_ci * zpa2326_resume() - Request the PM layer to power supply the device.
6568c2ecf20Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware.
6578c2ecf20Sopenharmony_ci *
6588c2ecf20Sopenharmony_ci * Return:
6598c2ecf20Sopenharmony_ci *  < 0 - a negative error code meaning failure ;
6608c2ecf20Sopenharmony_ci *    0 - success, device has just been powered up ;
6618c2ecf20Sopenharmony_ci *    1 - success, device was already powered.
6628c2ecf20Sopenharmony_ci */
6638c2ecf20Sopenharmony_cistatic int zpa2326_resume(const struct iio_dev *indio_dev)
6648c2ecf20Sopenharmony_ci{
6658c2ecf20Sopenharmony_ci	int err;
6668c2ecf20Sopenharmony_ci
6678c2ecf20Sopenharmony_ci	err = pm_runtime_get_sync(indio_dev->dev.parent);
6688c2ecf20Sopenharmony_ci	if (err < 0) {
6698c2ecf20Sopenharmony_ci		pm_runtime_put(indio_dev->dev.parent);
6708c2ecf20Sopenharmony_ci		return err;
6718c2ecf20Sopenharmony_ci	}
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci	if (err > 0) {
6748c2ecf20Sopenharmony_ci		/*
6758c2ecf20Sopenharmony_ci		 * Device was already power supplied: get it out of low power
6768c2ecf20Sopenharmony_ci		 * mode and inform caller.
6778c2ecf20Sopenharmony_ci		 */
6788c2ecf20Sopenharmony_ci		zpa2326_enable_device(indio_dev);
6798c2ecf20Sopenharmony_ci		return 1;
6808c2ecf20Sopenharmony_ci	}
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ci	/* Inform caller device has just been brought back to life. */
6838c2ecf20Sopenharmony_ci	return 0;
6848c2ecf20Sopenharmony_ci}
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_ci/**
6878c2ecf20Sopenharmony_ci * zpa2326_suspend() - Schedule a power down using autosuspend feature of PM
6888c2ecf20Sopenharmony_ci *                     layer.
6898c2ecf20Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware.
6908c2ecf20Sopenharmony_ci *
6918c2ecf20Sopenharmony_ci * Device is switched to low power mode at first to save power even when
6928c2ecf20Sopenharmony_ci * attached regulator is a "dummy" one.
6938c2ecf20Sopenharmony_ci */
6948c2ecf20Sopenharmony_cistatic void zpa2326_suspend(struct iio_dev *indio_dev)
6958c2ecf20Sopenharmony_ci{
6968c2ecf20Sopenharmony_ci	struct device *parent = indio_dev->dev.parent;
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci	zpa2326_sleep(indio_dev);
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	pm_runtime_mark_last_busy(parent);
7018c2ecf20Sopenharmony_ci	pm_runtime_put_autosuspend(parent);
7028c2ecf20Sopenharmony_ci}
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_cistatic void zpa2326_init_runtime(struct device *parent)
7058c2ecf20Sopenharmony_ci{
7068c2ecf20Sopenharmony_ci	pm_runtime_get_noresume(parent);
7078c2ecf20Sopenharmony_ci	pm_runtime_set_active(parent);
7088c2ecf20Sopenharmony_ci	pm_runtime_enable(parent);
7098c2ecf20Sopenharmony_ci	pm_runtime_set_autosuspend_delay(parent, 1000);
7108c2ecf20Sopenharmony_ci	pm_runtime_use_autosuspend(parent);
7118c2ecf20Sopenharmony_ci	pm_runtime_mark_last_busy(parent);
7128c2ecf20Sopenharmony_ci	pm_runtime_put_autosuspend(parent);
7138c2ecf20Sopenharmony_ci}
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_cistatic void zpa2326_fini_runtime(struct device *parent)
7168c2ecf20Sopenharmony_ci{
7178c2ecf20Sopenharmony_ci	pm_runtime_disable(parent);
7188c2ecf20Sopenharmony_ci	pm_runtime_set_suspended(parent);
7198c2ecf20Sopenharmony_ci}
7208c2ecf20Sopenharmony_ci#else /* !CONFIG_PM */
7218c2ecf20Sopenharmony_cistatic int zpa2326_resume(const struct iio_dev *indio_dev)
7228c2ecf20Sopenharmony_ci{
7238c2ecf20Sopenharmony_ci	zpa2326_enable_device(indio_dev);
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci	return 0;
7268c2ecf20Sopenharmony_ci}
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_cistatic void zpa2326_suspend(struct iio_dev *indio_dev)
7298c2ecf20Sopenharmony_ci{
7308c2ecf20Sopenharmony_ci	zpa2326_sleep(indio_dev);
7318c2ecf20Sopenharmony_ci}
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci#define zpa2326_init_runtime(_parent)
7348c2ecf20Sopenharmony_ci#define zpa2326_fini_runtime(_parent)
7358c2ecf20Sopenharmony_ci#endif /* !CONFIG_PM */
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci/**
7388c2ecf20Sopenharmony_ci * zpa2326_handle_irq() - Process hardware interrupts.
7398c2ecf20Sopenharmony_ci * @irq:  Interrupt line the hardware uses to notify new data has arrived.
7408c2ecf20Sopenharmony_ci * @data: The IIO device associated with the sampling hardware.
7418c2ecf20Sopenharmony_ci *
7428c2ecf20Sopenharmony_ci * Timestamp buffered samples as soon as possible then schedule threaded bottom
7438c2ecf20Sopenharmony_ci * half.
7448c2ecf20Sopenharmony_ci *
7458c2ecf20Sopenharmony_ci * Return: Always successful.
7468c2ecf20Sopenharmony_ci */
7478c2ecf20Sopenharmony_cistatic irqreturn_t zpa2326_handle_irq(int irq, void *data)
7488c2ecf20Sopenharmony_ci{
7498c2ecf20Sopenharmony_ci	struct iio_dev *indio_dev = data;
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci	if (iio_buffer_enabled(indio_dev)) {
7528c2ecf20Sopenharmony_ci		/* Timestamping needed for buffered sampling only. */
7538c2ecf20Sopenharmony_ci		((struct zpa2326_private *)
7548c2ecf20Sopenharmony_ci		 iio_priv(indio_dev))->timestamp = iio_get_time_ns(indio_dev);
7558c2ecf20Sopenharmony_ci	}
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	return IRQ_WAKE_THREAD;
7588c2ecf20Sopenharmony_ci}
7598c2ecf20Sopenharmony_ci
7608c2ecf20Sopenharmony_ci/**
7618c2ecf20Sopenharmony_ci * zpa2326_handle_threaded_irq() - Interrupt bottom-half handler.
7628c2ecf20Sopenharmony_ci * @irq:  Interrupt line the hardware uses to notify new data has arrived.
7638c2ecf20Sopenharmony_ci * @data: The IIO device associated with the sampling hardware.
7648c2ecf20Sopenharmony_ci *
7658c2ecf20Sopenharmony_ci * Mainly ensures interrupt is caused by a real "new sample available"
7668c2ecf20Sopenharmony_ci * condition. This relies upon the ability to perform blocking / sleeping bus
7678c2ecf20Sopenharmony_ci * accesses to slave's registers. This is why zpa2326_handle_threaded_irq() is
7688c2ecf20Sopenharmony_ci * called from within a thread, i.e. not called from hard interrupt context.
7698c2ecf20Sopenharmony_ci *
7708c2ecf20Sopenharmony_ci * When device is using its own internal hardware trigger in continuous sampling
7718c2ecf20Sopenharmony_ci * mode, data are available into hardware FIFO once interrupt has occurred. All
7728c2ecf20Sopenharmony_ci * we have to do is to dispatch the trigger, which in turn will fetch data and
7738c2ecf20Sopenharmony_ci * fill IIO buffer.
7748c2ecf20Sopenharmony_ci *
7758c2ecf20Sopenharmony_ci * When not using its own internal hardware trigger, the device has been
7768c2ecf20Sopenharmony_ci * configured in one-shot mode either by an external trigger or the IIO read_raw
7778c2ecf20Sopenharmony_ci * hook. This means one of the latter is currently waiting for sampling
7788c2ecf20Sopenharmony_ci * completion, in which case we must simply wake it up.
7798c2ecf20Sopenharmony_ci *
7808c2ecf20Sopenharmony_ci * See zpa2326_trigger_handler().
7818c2ecf20Sopenharmony_ci *
7828c2ecf20Sopenharmony_ci * Return:
7838c2ecf20Sopenharmony_ci *   %IRQ_NONE - no consistent interrupt happened ;
7848c2ecf20Sopenharmony_ci *   %IRQ_HANDLED - there was new samples available.
7858c2ecf20Sopenharmony_ci */
7868c2ecf20Sopenharmony_cistatic irqreturn_t zpa2326_handle_threaded_irq(int irq, void *data)
7878c2ecf20Sopenharmony_ci{
7888c2ecf20Sopenharmony_ci	struct iio_dev         *indio_dev = data;
7898c2ecf20Sopenharmony_ci	struct zpa2326_private *priv = iio_priv(indio_dev);
7908c2ecf20Sopenharmony_ci	unsigned int            val;
7918c2ecf20Sopenharmony_ci	bool                    cont;
7928c2ecf20Sopenharmony_ci	irqreturn_t             ret = IRQ_NONE;
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_ci	/*
7958c2ecf20Sopenharmony_ci	 * Are we using our own internal trigger in triggered buffer mode, i.e.,
7968c2ecf20Sopenharmony_ci	 * currently working in continuous sampling mode ?
7978c2ecf20Sopenharmony_ci	 */
7988c2ecf20Sopenharmony_ci	cont = (iio_buffer_enabled(indio_dev) &&
7998c2ecf20Sopenharmony_ci		iio_trigger_using_own(indio_dev));
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci	/*
8028c2ecf20Sopenharmony_ci	 * Device works according to a level interrupt scheme: reading interrupt
8038c2ecf20Sopenharmony_ci	 * status de-asserts interrupt line.
8048c2ecf20Sopenharmony_ci	 */
8058c2ecf20Sopenharmony_ci	priv->result = regmap_read(priv->regmap, ZPA2326_INT_SOURCE_REG, &val);
8068c2ecf20Sopenharmony_ci	if (priv->result < 0) {
8078c2ecf20Sopenharmony_ci		if (cont)
8088c2ecf20Sopenharmony_ci			return IRQ_NONE;
8098c2ecf20Sopenharmony_ci
8108c2ecf20Sopenharmony_ci		goto complete;
8118c2ecf20Sopenharmony_ci	}
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci	/* Data ready is the only interrupt source we requested. */
8148c2ecf20Sopenharmony_ci	if (!(val & ZPA2326_INT_SOURCE_DATA_READY)) {
8158c2ecf20Sopenharmony_ci		/*
8168c2ecf20Sopenharmony_ci		 * Interrupt happened but no new sample available: likely caused
8178c2ecf20Sopenharmony_ci		 * by spurious interrupts, in which case, returning IRQ_NONE
8188c2ecf20Sopenharmony_ci		 * allows to benefit from the generic spurious interrupts
8198c2ecf20Sopenharmony_ci		 * handling.
8208c2ecf20Sopenharmony_ci		 */
8218c2ecf20Sopenharmony_ci		zpa2326_warn(indio_dev, "unexpected interrupt status %02x",
8228c2ecf20Sopenharmony_ci			     val);
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci		if (cont)
8258c2ecf20Sopenharmony_ci			return IRQ_NONE;
8268c2ecf20Sopenharmony_ci
8278c2ecf20Sopenharmony_ci		priv->result = -ENODATA;
8288c2ecf20Sopenharmony_ci		goto complete;
8298c2ecf20Sopenharmony_ci	}
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci	/* New sample available: dispatch internal trigger consumers. */
8328c2ecf20Sopenharmony_ci	iio_trigger_poll_chained(priv->trigger);
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_ci	if (cont)
8358c2ecf20Sopenharmony_ci		/*
8368c2ecf20Sopenharmony_ci		 * Internal hardware trigger has been scheduled above : it will
8378c2ecf20Sopenharmony_ci		 * fetch data on its own.
8388c2ecf20Sopenharmony_ci		 */
8398c2ecf20Sopenharmony_ci		return IRQ_HANDLED;
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci	ret = IRQ_HANDLED;
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_cicomplete:
8448c2ecf20Sopenharmony_ci	/*
8458c2ecf20Sopenharmony_ci	 * Wake up direct or externaly triggered buffer mode waiters: see
8468c2ecf20Sopenharmony_ci	 * zpa2326_sample_oneshot() and zpa2326_trigger_handler().
8478c2ecf20Sopenharmony_ci	 */
8488c2ecf20Sopenharmony_ci	complete(&priv->data_ready);
8498c2ecf20Sopenharmony_ci
8508c2ecf20Sopenharmony_ci	return ret;
8518c2ecf20Sopenharmony_ci}
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_ci/**
8548c2ecf20Sopenharmony_ci * zpa2326_wait_oneshot_completion() - Wait for oneshot data ready interrupt.
8558c2ecf20Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware.
8568c2ecf20Sopenharmony_ci * @private:   Internal private state related to @indio_dev.
8578c2ecf20Sopenharmony_ci *
8588c2ecf20Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise.
8598c2ecf20Sopenharmony_ci */
8608c2ecf20Sopenharmony_cistatic int zpa2326_wait_oneshot_completion(const struct iio_dev   *indio_dev,
8618c2ecf20Sopenharmony_ci					   struct zpa2326_private *private)
8628c2ecf20Sopenharmony_ci{
8638c2ecf20Sopenharmony_ci	unsigned int val;
8648c2ecf20Sopenharmony_ci	long     timeout;
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci	zpa2326_dbg(indio_dev, "waiting for one shot completion interrupt");
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_ci	timeout = wait_for_completion_interruptible_timeout(
8698c2ecf20Sopenharmony_ci		&private->data_ready, ZPA2326_CONVERSION_JIFFIES);
8708c2ecf20Sopenharmony_ci	if (timeout > 0)
8718c2ecf20Sopenharmony_ci		/*
8728c2ecf20Sopenharmony_ci		 * Interrupt handler completed before timeout: return operation
8738c2ecf20Sopenharmony_ci		 * status.
8748c2ecf20Sopenharmony_ci		 */
8758c2ecf20Sopenharmony_ci		return private->result;
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci	/* Clear all interrupts just to be sure. */
8788c2ecf20Sopenharmony_ci	regmap_read(private->regmap, ZPA2326_INT_SOURCE_REG, &val);
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_ci	if (!timeout) {
8818c2ecf20Sopenharmony_ci		/* Timed out. */
8828c2ecf20Sopenharmony_ci		zpa2326_warn(indio_dev, "no one shot interrupt occurred (%ld)",
8838c2ecf20Sopenharmony_ci			     timeout);
8848c2ecf20Sopenharmony_ci		return -ETIME;
8858c2ecf20Sopenharmony_ci	}
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ci	zpa2326_warn(indio_dev, "wait for one shot interrupt cancelled");
8888c2ecf20Sopenharmony_ci	return -ERESTARTSYS;
8898c2ecf20Sopenharmony_ci}
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_cistatic int zpa2326_init_managed_irq(struct device          *parent,
8928c2ecf20Sopenharmony_ci				    struct iio_dev         *indio_dev,
8938c2ecf20Sopenharmony_ci				    struct zpa2326_private *private,
8948c2ecf20Sopenharmony_ci				    int                     irq)
8958c2ecf20Sopenharmony_ci{
8968c2ecf20Sopenharmony_ci	int err;
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_ci	private->irq = irq;
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_ci	if (irq <= 0) {
9018c2ecf20Sopenharmony_ci		/*
9028c2ecf20Sopenharmony_ci		 * Platform declared no interrupt line: device will be polled
9038c2ecf20Sopenharmony_ci		 * for data availability.
9048c2ecf20Sopenharmony_ci		 */
9058c2ecf20Sopenharmony_ci		dev_info(parent, "no interrupt found, running in polling mode");
9068c2ecf20Sopenharmony_ci		return 0;
9078c2ecf20Sopenharmony_ci	}
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci	init_completion(&private->data_ready);
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci	/* Request handler to be scheduled into threaded interrupt context. */
9128c2ecf20Sopenharmony_ci	err = devm_request_threaded_irq(parent, irq, zpa2326_handle_irq,
9138c2ecf20Sopenharmony_ci					zpa2326_handle_threaded_irq,
9148c2ecf20Sopenharmony_ci					IRQF_TRIGGER_RISING | IRQF_ONESHOT,
9158c2ecf20Sopenharmony_ci					dev_name(parent), indio_dev);
9168c2ecf20Sopenharmony_ci	if (err) {
9178c2ecf20Sopenharmony_ci		dev_err(parent, "failed to request interrupt %d (%d)", irq,
9188c2ecf20Sopenharmony_ci			err);
9198c2ecf20Sopenharmony_ci		return err;
9208c2ecf20Sopenharmony_ci	}
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci	dev_info(parent, "using interrupt %d", irq);
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_ci	return 0;
9258c2ecf20Sopenharmony_ci}
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_ci/**
9288c2ecf20Sopenharmony_ci * zpa2326_poll_oneshot_completion() - Actively poll for one shot data ready.
9298c2ecf20Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware.
9308c2ecf20Sopenharmony_ci *
9318c2ecf20Sopenharmony_ci * Loop over registers content to detect end of sampling cycle. Used when DT
9328c2ecf20Sopenharmony_ci * declared no valid interrupt lines.
9338c2ecf20Sopenharmony_ci *
9348c2ecf20Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise.
9358c2ecf20Sopenharmony_ci */
9368c2ecf20Sopenharmony_cistatic int zpa2326_poll_oneshot_completion(const struct iio_dev *indio_dev)
9378c2ecf20Sopenharmony_ci{
9388c2ecf20Sopenharmony_ci	unsigned long  tmout = jiffies + ZPA2326_CONVERSION_JIFFIES;
9398c2ecf20Sopenharmony_ci	struct regmap *regs = ((struct zpa2326_private *)
9408c2ecf20Sopenharmony_ci			       iio_priv(indio_dev))->regmap;
9418c2ecf20Sopenharmony_ci	unsigned int   val;
9428c2ecf20Sopenharmony_ci	int            err;
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_ci	zpa2326_dbg(indio_dev, "polling for one shot completion");
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_ci	/*
9478c2ecf20Sopenharmony_ci	 * At least, 100 ms is needed for the device to complete its one-shot
9488c2ecf20Sopenharmony_ci	 * cycle.
9498c2ecf20Sopenharmony_ci	 */
9508c2ecf20Sopenharmony_ci	if (msleep_interruptible(100))
9518c2ecf20Sopenharmony_ci		return -ERESTARTSYS;
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci	/* Poll for conversion completion in hardware. */
9548c2ecf20Sopenharmony_ci	while (true) {
9558c2ecf20Sopenharmony_ci		err = regmap_read(regs, ZPA2326_CTRL_REG0_REG, &val);
9568c2ecf20Sopenharmony_ci		if (err < 0)
9578c2ecf20Sopenharmony_ci			goto err;
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci		if (!(val & ZPA2326_CTRL_REG0_ONE_SHOT))
9608c2ecf20Sopenharmony_ci			/* One-shot bit self clears at conversion end. */
9618c2ecf20Sopenharmony_ci			break;
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_ci		if (time_after(jiffies, tmout)) {
9648c2ecf20Sopenharmony_ci			/* Prevent from waiting forever : let's time out. */
9658c2ecf20Sopenharmony_ci			err = -ETIME;
9668c2ecf20Sopenharmony_ci			goto err;
9678c2ecf20Sopenharmony_ci		}
9688c2ecf20Sopenharmony_ci
9698c2ecf20Sopenharmony_ci		usleep_range(10000, 20000);
9708c2ecf20Sopenharmony_ci	}
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci	/*
9738c2ecf20Sopenharmony_ci	 * In oneshot mode, pressure sample availability guarantees that
9748c2ecf20Sopenharmony_ci	 * temperature conversion has also completed : just check pressure
9758c2ecf20Sopenharmony_ci	 * status bit to keep things simple.
9768c2ecf20Sopenharmony_ci	 */
9778c2ecf20Sopenharmony_ci	err = regmap_read(regs, ZPA2326_STATUS_REG, &val);
9788c2ecf20Sopenharmony_ci	if (err < 0)
9798c2ecf20Sopenharmony_ci		goto err;
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_ci	if (!(val & ZPA2326_STATUS_P_DA)) {
9828c2ecf20Sopenharmony_ci		/* No sample available. */
9838c2ecf20Sopenharmony_ci		err = -ENODATA;
9848c2ecf20Sopenharmony_ci		goto err;
9858c2ecf20Sopenharmony_ci	}
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_ci	return 0;
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_cierr:
9908c2ecf20Sopenharmony_ci	zpa2326_warn(indio_dev, "failed to poll one shot completion (%d)", err);
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci	return err;
9938c2ecf20Sopenharmony_ci}
9948c2ecf20Sopenharmony_ci
9958c2ecf20Sopenharmony_ci/**
9968c2ecf20Sopenharmony_ci * zpa2326_fetch_raw_sample() - Retrieve a raw sample and convert it to CPU
9978c2ecf20Sopenharmony_ci *                              endianness.
9988c2ecf20Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware.
9998c2ecf20Sopenharmony_ci * @type:      Type of measurement / channel to fetch from.
10008c2ecf20Sopenharmony_ci * @value:     Sample output.
10018c2ecf20Sopenharmony_ci *
10028c2ecf20Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise.
10038c2ecf20Sopenharmony_ci */
10048c2ecf20Sopenharmony_cistatic int zpa2326_fetch_raw_sample(const struct iio_dev *indio_dev,
10058c2ecf20Sopenharmony_ci				    enum iio_chan_type    type,
10068c2ecf20Sopenharmony_ci				    int                  *value)
10078c2ecf20Sopenharmony_ci{
10088c2ecf20Sopenharmony_ci	struct regmap *regs = ((struct zpa2326_private *)
10098c2ecf20Sopenharmony_ci			       iio_priv(indio_dev))->regmap;
10108c2ecf20Sopenharmony_ci	int            err;
10118c2ecf20Sopenharmony_ci	u8             v[3];
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci	switch (type) {
10148c2ecf20Sopenharmony_ci	case IIO_PRESSURE:
10158c2ecf20Sopenharmony_ci		zpa2326_dbg(indio_dev, "fetching raw pressure sample");
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_ci		err = regmap_bulk_read(regs, ZPA2326_PRESS_OUT_XL_REG, v, sizeof(v));
10188c2ecf20Sopenharmony_ci		if (err) {
10198c2ecf20Sopenharmony_ci			zpa2326_warn(indio_dev, "failed to fetch pressure (%d)",
10208c2ecf20Sopenharmony_ci				     err);
10218c2ecf20Sopenharmony_ci			return err;
10228c2ecf20Sopenharmony_ci		}
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_ci		*value = get_unaligned_le24(&v[0]);
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_ci		return IIO_VAL_INT;
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ci	case IIO_TEMP:
10298c2ecf20Sopenharmony_ci		zpa2326_dbg(indio_dev, "fetching raw temperature sample");
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ci		err = regmap_bulk_read(regs, ZPA2326_TEMP_OUT_L_REG, value, 2);
10328c2ecf20Sopenharmony_ci		if (err) {
10338c2ecf20Sopenharmony_ci			zpa2326_warn(indio_dev,
10348c2ecf20Sopenharmony_ci				     "failed to fetch temperature (%d)", err);
10358c2ecf20Sopenharmony_ci			return err;
10368c2ecf20Sopenharmony_ci		}
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_ci		/* Temperature is a 16 bits wide little-endian signed int. */
10398c2ecf20Sopenharmony_ci		*value = (int)le16_to_cpup((__le16 *)value);
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci		return IIO_VAL_INT;
10428c2ecf20Sopenharmony_ci
10438c2ecf20Sopenharmony_ci	default:
10448c2ecf20Sopenharmony_ci		return -EINVAL;
10458c2ecf20Sopenharmony_ci	}
10468c2ecf20Sopenharmony_ci}
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_ci/**
10498c2ecf20Sopenharmony_ci * zpa2326_sample_oneshot() - Perform a complete one shot sampling cycle.
10508c2ecf20Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware.
10518c2ecf20Sopenharmony_ci * @type:      Type of measurement / channel to fetch from.
10528c2ecf20Sopenharmony_ci * @value:     Sample output.
10538c2ecf20Sopenharmony_ci *
10548c2ecf20Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise.
10558c2ecf20Sopenharmony_ci */
10568c2ecf20Sopenharmony_cistatic int zpa2326_sample_oneshot(struct iio_dev     *indio_dev,
10578c2ecf20Sopenharmony_ci				  enum iio_chan_type  type,
10588c2ecf20Sopenharmony_ci				  int                *value)
10598c2ecf20Sopenharmony_ci{
10608c2ecf20Sopenharmony_ci	int                     ret;
10618c2ecf20Sopenharmony_ci	struct zpa2326_private *priv;
10628c2ecf20Sopenharmony_ci
10638c2ecf20Sopenharmony_ci	ret = iio_device_claim_direct_mode(indio_dev);
10648c2ecf20Sopenharmony_ci	if (ret)
10658c2ecf20Sopenharmony_ci		return ret;
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_ci	ret = zpa2326_resume(indio_dev);
10688c2ecf20Sopenharmony_ci	if (ret < 0)
10698c2ecf20Sopenharmony_ci		goto release;
10708c2ecf20Sopenharmony_ci
10718c2ecf20Sopenharmony_ci	priv = iio_priv(indio_dev);
10728c2ecf20Sopenharmony_ci
10738c2ecf20Sopenharmony_ci	if (ret > 0) {
10748c2ecf20Sopenharmony_ci		/*
10758c2ecf20Sopenharmony_ci		 * We were already power supplied. Just clear hardware FIFO to
10768c2ecf20Sopenharmony_ci		 * get rid of samples acquired during previous rounds (if any).
10778c2ecf20Sopenharmony_ci		 * Sampling operation always generates both temperature and
10788c2ecf20Sopenharmony_ci		 * pressure samples. The latter are always enqueued into
10798c2ecf20Sopenharmony_ci		 * hardware FIFO. This may lead to situations were pressure
10808c2ecf20Sopenharmony_ci		 * samples still sit into FIFO when previous cycle(s) fetched
10818c2ecf20Sopenharmony_ci		 * temperature data only.
10828c2ecf20Sopenharmony_ci		 * Hence, we need to clear hardware FIFO content to prevent from
10838c2ecf20Sopenharmony_ci		 * getting outdated values at the end of current cycle.
10848c2ecf20Sopenharmony_ci		 */
10858c2ecf20Sopenharmony_ci		if (type == IIO_PRESSURE) {
10868c2ecf20Sopenharmony_ci			ret = zpa2326_clear_fifo(indio_dev, 0);
10878c2ecf20Sopenharmony_ci			if (ret)
10888c2ecf20Sopenharmony_ci				goto suspend;
10898c2ecf20Sopenharmony_ci		}
10908c2ecf20Sopenharmony_ci	} else {
10918c2ecf20Sopenharmony_ci		/*
10928c2ecf20Sopenharmony_ci		 * We have just been power supplied, i.e. device is in default
10938c2ecf20Sopenharmony_ci		 * "out of reset" state, meaning we need to reconfigure it
10948c2ecf20Sopenharmony_ci		 * entirely.
10958c2ecf20Sopenharmony_ci		 */
10968c2ecf20Sopenharmony_ci		ret = zpa2326_config_oneshot(indio_dev, priv->irq);
10978c2ecf20Sopenharmony_ci		if (ret)
10988c2ecf20Sopenharmony_ci			goto suspend;
10998c2ecf20Sopenharmony_ci	}
11008c2ecf20Sopenharmony_ci
11018c2ecf20Sopenharmony_ci	/* Start a sampling cycle in oneshot mode. */
11028c2ecf20Sopenharmony_ci	ret = zpa2326_start_oneshot(indio_dev);
11038c2ecf20Sopenharmony_ci	if (ret)
11048c2ecf20Sopenharmony_ci		goto suspend;
11058c2ecf20Sopenharmony_ci
11068c2ecf20Sopenharmony_ci	/* Wait for sampling cycle to complete. */
11078c2ecf20Sopenharmony_ci	if (priv->irq > 0)
11088c2ecf20Sopenharmony_ci		ret = zpa2326_wait_oneshot_completion(indio_dev, priv);
11098c2ecf20Sopenharmony_ci	else
11108c2ecf20Sopenharmony_ci		ret = zpa2326_poll_oneshot_completion(indio_dev);
11118c2ecf20Sopenharmony_ci
11128c2ecf20Sopenharmony_ci	if (ret)
11138c2ecf20Sopenharmony_ci		goto suspend;
11148c2ecf20Sopenharmony_ci
11158c2ecf20Sopenharmony_ci	/* Retrieve raw sample value and convert it to CPU endianness. */
11168c2ecf20Sopenharmony_ci	ret = zpa2326_fetch_raw_sample(indio_dev, type, value);
11178c2ecf20Sopenharmony_ci
11188c2ecf20Sopenharmony_cisuspend:
11198c2ecf20Sopenharmony_ci	zpa2326_suspend(indio_dev);
11208c2ecf20Sopenharmony_cirelease:
11218c2ecf20Sopenharmony_ci	iio_device_release_direct_mode(indio_dev);
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci	return ret;
11248c2ecf20Sopenharmony_ci}
11258c2ecf20Sopenharmony_ci
11268c2ecf20Sopenharmony_ci/**
11278c2ecf20Sopenharmony_ci * zpa2326_trigger_handler() - Perform an IIO buffered sampling round in one
11288c2ecf20Sopenharmony_ci *                             shot mode.
11298c2ecf20Sopenharmony_ci * @irq:  The software interrupt assigned to @data
11308c2ecf20Sopenharmony_ci * @data: The IIO poll function dispatched by external trigger our device is
11318c2ecf20Sopenharmony_ci *        attached to.
11328c2ecf20Sopenharmony_ci *
11338c2ecf20Sopenharmony_ci * Bottom-half handler called by the IIO trigger to which our device is
11348c2ecf20Sopenharmony_ci * currently attached. Allows us to synchronize this device buffered sampling
11358c2ecf20Sopenharmony_ci * either with external events (such as timer expiration, external device sample
11368c2ecf20Sopenharmony_ci * ready, etc...) or with its own interrupt (internal hardware trigger).
11378c2ecf20Sopenharmony_ci *
11388c2ecf20Sopenharmony_ci * When using an external trigger, basically run the same sequence of operations
11398c2ecf20Sopenharmony_ci * as for zpa2326_sample_oneshot() with the following hereafter. Hardware FIFO
11408c2ecf20Sopenharmony_ci * is not cleared since already done at buffering enable time and samples
11418c2ecf20Sopenharmony_ci * dequeueing always retrieves the most recent value.
11428c2ecf20Sopenharmony_ci *
11438c2ecf20Sopenharmony_ci * Otherwise, when internal hardware trigger has dispatched us, just fetch data
11448c2ecf20Sopenharmony_ci * from hardware FIFO.
11458c2ecf20Sopenharmony_ci *
11468c2ecf20Sopenharmony_ci * Fetched data will pushed unprocessed to IIO buffer since samples conversion
11478c2ecf20Sopenharmony_ci * is delegated to userspace in buffered mode (endianness, etc...).
11488c2ecf20Sopenharmony_ci *
11498c2ecf20Sopenharmony_ci * Return:
11508c2ecf20Sopenharmony_ci *   %IRQ_NONE - no consistent interrupt happened ;
11518c2ecf20Sopenharmony_ci *   %IRQ_HANDLED - there was new samples available.
11528c2ecf20Sopenharmony_ci */
11538c2ecf20Sopenharmony_cistatic irqreturn_t zpa2326_trigger_handler(int irq, void *data)
11548c2ecf20Sopenharmony_ci{
11558c2ecf20Sopenharmony_ci	struct iio_dev         *indio_dev = ((struct iio_poll_func *)
11568c2ecf20Sopenharmony_ci					     data)->indio_dev;
11578c2ecf20Sopenharmony_ci	struct zpa2326_private *priv = iio_priv(indio_dev);
11588c2ecf20Sopenharmony_ci	bool                    cont;
11598c2ecf20Sopenharmony_ci
11608c2ecf20Sopenharmony_ci	/*
11618c2ecf20Sopenharmony_ci	 * We have been dispatched, meaning we are in triggered buffer mode.
11628c2ecf20Sopenharmony_ci	 * Using our own internal trigger implies we are currently in continuous
11638c2ecf20Sopenharmony_ci	 * hardware sampling mode.
11648c2ecf20Sopenharmony_ci	 */
11658c2ecf20Sopenharmony_ci	cont = iio_trigger_using_own(indio_dev);
11668c2ecf20Sopenharmony_ci
11678c2ecf20Sopenharmony_ci	if (!cont) {
11688c2ecf20Sopenharmony_ci		/* On demand sampling : start a one shot cycle. */
11698c2ecf20Sopenharmony_ci		if (zpa2326_start_oneshot(indio_dev))
11708c2ecf20Sopenharmony_ci			goto out;
11718c2ecf20Sopenharmony_ci
11728c2ecf20Sopenharmony_ci		/* Wait for sampling cycle to complete. */
11738c2ecf20Sopenharmony_ci		if (priv->irq <= 0) {
11748c2ecf20Sopenharmony_ci			/* No interrupt available: poll for completion. */
11758c2ecf20Sopenharmony_ci			if (zpa2326_poll_oneshot_completion(indio_dev))
11768c2ecf20Sopenharmony_ci				goto out;
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_ci			/* Only timestamp sample once it is ready. */
11798c2ecf20Sopenharmony_ci			priv->timestamp = iio_get_time_ns(indio_dev);
11808c2ecf20Sopenharmony_ci		} else {
11818c2ecf20Sopenharmony_ci			/* Interrupt handlers will timestamp for us. */
11828c2ecf20Sopenharmony_ci			if (zpa2326_wait_oneshot_completion(indio_dev, priv))
11838c2ecf20Sopenharmony_ci				goto out;
11848c2ecf20Sopenharmony_ci		}
11858c2ecf20Sopenharmony_ci	}
11868c2ecf20Sopenharmony_ci
11878c2ecf20Sopenharmony_ci	/* Enqueue to IIO buffer / userspace. */
11888c2ecf20Sopenharmony_ci	zpa2326_fill_sample_buffer(indio_dev, priv);
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_ciout:
11918c2ecf20Sopenharmony_ci	if (!cont)
11928c2ecf20Sopenharmony_ci		/* Don't switch to low power if sampling continuously. */
11938c2ecf20Sopenharmony_ci		zpa2326_sleep(indio_dev);
11948c2ecf20Sopenharmony_ci
11958c2ecf20Sopenharmony_ci	/* Inform attached trigger we are done. */
11968c2ecf20Sopenharmony_ci	iio_trigger_notify_done(indio_dev->trig);
11978c2ecf20Sopenharmony_ci
11988c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
11998c2ecf20Sopenharmony_ci}
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_ci/**
12028c2ecf20Sopenharmony_ci * zpa2326_preenable_buffer() - Prepare device for configuring triggered
12038c2ecf20Sopenharmony_ci *                              sampling
12048c2ecf20Sopenharmony_ci * modes.
12058c2ecf20Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware.
12068c2ecf20Sopenharmony_ci *
12078c2ecf20Sopenharmony_ci * Basically power up device.
12088c2ecf20Sopenharmony_ci * Called with IIO device's lock held.
12098c2ecf20Sopenharmony_ci *
12108c2ecf20Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise.
12118c2ecf20Sopenharmony_ci */
12128c2ecf20Sopenharmony_cistatic int zpa2326_preenable_buffer(struct iio_dev *indio_dev)
12138c2ecf20Sopenharmony_ci{
12148c2ecf20Sopenharmony_ci	int ret = zpa2326_resume(indio_dev);
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_ci	if (ret < 0)
12178c2ecf20Sopenharmony_ci		return ret;
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ci	/* Tell zpa2326_postenable_buffer() if we have just been powered on. */
12208c2ecf20Sopenharmony_ci	((struct zpa2326_private *)
12218c2ecf20Sopenharmony_ci	 iio_priv(indio_dev))->waken = iio_priv(indio_dev);
12228c2ecf20Sopenharmony_ci
12238c2ecf20Sopenharmony_ci	return 0;
12248c2ecf20Sopenharmony_ci}
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_ci/**
12278c2ecf20Sopenharmony_ci * zpa2326_postenable_buffer() - Configure device for triggered sampling.
12288c2ecf20Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware.
12298c2ecf20Sopenharmony_ci *
12308c2ecf20Sopenharmony_ci * Basically setup one-shot mode if plugging external trigger.
12318c2ecf20Sopenharmony_ci * Otherwise, let internal trigger configure continuous sampling :
12328c2ecf20Sopenharmony_ci * see zpa2326_set_trigger_state().
12338c2ecf20Sopenharmony_ci *
12348c2ecf20Sopenharmony_ci * If an error is returned, IIO layer will call our postdisable hook for us,
12358c2ecf20Sopenharmony_ci * i.e. no need to explicitly power device off here.
12368c2ecf20Sopenharmony_ci * Called with IIO device's lock held.
12378c2ecf20Sopenharmony_ci *
12388c2ecf20Sopenharmony_ci * Called with IIO device's lock held.
12398c2ecf20Sopenharmony_ci *
12408c2ecf20Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise.
12418c2ecf20Sopenharmony_ci */
12428c2ecf20Sopenharmony_cistatic int zpa2326_postenable_buffer(struct iio_dev *indio_dev)
12438c2ecf20Sopenharmony_ci{
12448c2ecf20Sopenharmony_ci	const struct zpa2326_private *priv = iio_priv(indio_dev);
12458c2ecf20Sopenharmony_ci	int                           err;
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_ci	if (!priv->waken) {
12488c2ecf20Sopenharmony_ci		/*
12498c2ecf20Sopenharmony_ci		 * We were already power supplied. Just clear hardware FIFO to
12508c2ecf20Sopenharmony_ci		 * get rid of samples acquired during previous rounds (if any).
12518c2ecf20Sopenharmony_ci		 */
12528c2ecf20Sopenharmony_ci		err = zpa2326_clear_fifo(indio_dev, 0);
12538c2ecf20Sopenharmony_ci		if (err) {
12548c2ecf20Sopenharmony_ci			zpa2326_err(indio_dev,
12558c2ecf20Sopenharmony_ci				    "failed to enable buffering (%d)", err);
12568c2ecf20Sopenharmony_ci			return err;
12578c2ecf20Sopenharmony_ci		}
12588c2ecf20Sopenharmony_ci	}
12598c2ecf20Sopenharmony_ci
12608c2ecf20Sopenharmony_ci	if (!iio_trigger_using_own(indio_dev) && priv->waken) {
12618c2ecf20Sopenharmony_ci		/*
12628c2ecf20Sopenharmony_ci		 * We are using an external trigger and we have just been
12638c2ecf20Sopenharmony_ci		 * powered up: reconfigure one-shot mode.
12648c2ecf20Sopenharmony_ci		 */
12658c2ecf20Sopenharmony_ci		err = zpa2326_config_oneshot(indio_dev, priv->irq);
12668c2ecf20Sopenharmony_ci		if (err) {
12678c2ecf20Sopenharmony_ci			zpa2326_err(indio_dev,
12688c2ecf20Sopenharmony_ci				    "failed to enable buffering (%d)", err);
12698c2ecf20Sopenharmony_ci			return err;
12708c2ecf20Sopenharmony_ci		}
12718c2ecf20Sopenharmony_ci	}
12728c2ecf20Sopenharmony_ci
12738c2ecf20Sopenharmony_ci	return 0;
12748c2ecf20Sopenharmony_ci}
12758c2ecf20Sopenharmony_ci
12768c2ecf20Sopenharmony_cistatic int zpa2326_postdisable_buffer(struct iio_dev *indio_dev)
12778c2ecf20Sopenharmony_ci{
12788c2ecf20Sopenharmony_ci	zpa2326_suspend(indio_dev);
12798c2ecf20Sopenharmony_ci
12808c2ecf20Sopenharmony_ci	return 0;
12818c2ecf20Sopenharmony_ci}
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_cistatic const struct iio_buffer_setup_ops zpa2326_buffer_setup_ops = {
12848c2ecf20Sopenharmony_ci	.preenable   = zpa2326_preenable_buffer,
12858c2ecf20Sopenharmony_ci	.postenable  = zpa2326_postenable_buffer,
12868c2ecf20Sopenharmony_ci	.postdisable = zpa2326_postdisable_buffer
12878c2ecf20Sopenharmony_ci};
12888c2ecf20Sopenharmony_ci
12898c2ecf20Sopenharmony_ci/**
12908c2ecf20Sopenharmony_ci * zpa2326_set_trigger_state() - Start / stop continuous sampling.
12918c2ecf20Sopenharmony_ci * @trig:  The trigger being attached to IIO device associated with the sampling
12928c2ecf20Sopenharmony_ci *         hardware.
12938c2ecf20Sopenharmony_ci * @state: Tell whether to start (true) or stop (false)
12948c2ecf20Sopenharmony_ci *
12958c2ecf20Sopenharmony_ci * Basically enable / disable hardware continuous sampling mode.
12968c2ecf20Sopenharmony_ci *
12978c2ecf20Sopenharmony_ci * Called with IIO device's lock held at postenable() or predisable() time.
12988c2ecf20Sopenharmony_ci *
12998c2ecf20Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise.
13008c2ecf20Sopenharmony_ci */
13018c2ecf20Sopenharmony_cistatic int zpa2326_set_trigger_state(struct iio_trigger *trig, bool state)
13028c2ecf20Sopenharmony_ci{
13038c2ecf20Sopenharmony_ci	const struct iio_dev         *indio_dev = dev_get_drvdata(
13048c2ecf20Sopenharmony_ci							trig->dev.parent);
13058c2ecf20Sopenharmony_ci	const struct zpa2326_private *priv = iio_priv(indio_dev);
13068c2ecf20Sopenharmony_ci	int                           err;
13078c2ecf20Sopenharmony_ci
13088c2ecf20Sopenharmony_ci	if (!state) {
13098c2ecf20Sopenharmony_ci		/*
13108c2ecf20Sopenharmony_ci		 * Switch trigger off : in case of failure, interrupt is left
13118c2ecf20Sopenharmony_ci		 * disabled in order to prevent handler from accessing released
13128c2ecf20Sopenharmony_ci		 * resources.
13138c2ecf20Sopenharmony_ci		 */
13148c2ecf20Sopenharmony_ci		unsigned int val;
13158c2ecf20Sopenharmony_ci
13168c2ecf20Sopenharmony_ci		/*
13178c2ecf20Sopenharmony_ci		 * As device is working in continuous mode, handlers may be
13188c2ecf20Sopenharmony_ci		 * accessing resources we are currently freeing...
13198c2ecf20Sopenharmony_ci		 * Prevent this by disabling interrupt handlers and ensure
13208c2ecf20Sopenharmony_ci		 * the device will generate no more interrupts unless explicitly
13218c2ecf20Sopenharmony_ci		 * required to, i.e. by restoring back to default one shot mode.
13228c2ecf20Sopenharmony_ci		 */
13238c2ecf20Sopenharmony_ci		disable_irq(priv->irq);
13248c2ecf20Sopenharmony_ci
13258c2ecf20Sopenharmony_ci		/*
13268c2ecf20Sopenharmony_ci		 * Disable continuous sampling mode to restore settings for
13278c2ecf20Sopenharmony_ci		 * one shot / direct sampling operations.
13288c2ecf20Sopenharmony_ci		 */
13298c2ecf20Sopenharmony_ci		err = regmap_write(priv->regmap, ZPA2326_CTRL_REG3_REG,
13308c2ecf20Sopenharmony_ci				   zpa2326_highest_frequency()->odr);
13318c2ecf20Sopenharmony_ci		if (err)
13328c2ecf20Sopenharmony_ci			return err;
13338c2ecf20Sopenharmony_ci
13348c2ecf20Sopenharmony_ci		/*
13358c2ecf20Sopenharmony_ci		 * Now that device won't generate interrupts on its own,
13368c2ecf20Sopenharmony_ci		 * acknowledge any currently active interrupts (may happen on
13378c2ecf20Sopenharmony_ci		 * rare occasions while stopping continuous mode).
13388c2ecf20Sopenharmony_ci		 */
13398c2ecf20Sopenharmony_ci		err = regmap_read(priv->regmap, ZPA2326_INT_SOURCE_REG, &val);
13408c2ecf20Sopenharmony_ci		if (err < 0)
13418c2ecf20Sopenharmony_ci			return err;
13428c2ecf20Sopenharmony_ci
13438c2ecf20Sopenharmony_ci		/*
13448c2ecf20Sopenharmony_ci		 * Re-enable interrupts only if we can guarantee the device will
13458c2ecf20Sopenharmony_ci		 * generate no more interrupts to prevent handlers from
13468c2ecf20Sopenharmony_ci		 * accessing released resources.
13478c2ecf20Sopenharmony_ci		 */
13488c2ecf20Sopenharmony_ci		enable_irq(priv->irq);
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ci		zpa2326_dbg(indio_dev, "continuous mode stopped");
13518c2ecf20Sopenharmony_ci	} else {
13528c2ecf20Sopenharmony_ci		/*
13538c2ecf20Sopenharmony_ci		 * Switch trigger on : start continuous sampling at required
13548c2ecf20Sopenharmony_ci		 * frequency.
13558c2ecf20Sopenharmony_ci		 */
13568c2ecf20Sopenharmony_ci
13578c2ecf20Sopenharmony_ci		if (priv->waken) {
13588c2ecf20Sopenharmony_ci			/* Enable interrupt if getting out of reset. */
13598c2ecf20Sopenharmony_ci			err = regmap_write(priv->regmap, ZPA2326_CTRL_REG1_REG,
13608c2ecf20Sopenharmony_ci					   (u8)
13618c2ecf20Sopenharmony_ci					   ~ZPA2326_CTRL_REG1_MASK_DATA_READY);
13628c2ecf20Sopenharmony_ci			if (err)
13638c2ecf20Sopenharmony_ci				return err;
13648c2ecf20Sopenharmony_ci		}
13658c2ecf20Sopenharmony_ci
13668c2ecf20Sopenharmony_ci		/* Enable continuous sampling at specified frequency. */
13678c2ecf20Sopenharmony_ci		err = regmap_write(priv->regmap, ZPA2326_CTRL_REG3_REG,
13688c2ecf20Sopenharmony_ci				   ZPA2326_CTRL_REG3_ENABLE_MEAS |
13698c2ecf20Sopenharmony_ci				   priv->frequency->odr);
13708c2ecf20Sopenharmony_ci		if (err)
13718c2ecf20Sopenharmony_ci			return err;
13728c2ecf20Sopenharmony_ci
13738c2ecf20Sopenharmony_ci		zpa2326_dbg(indio_dev, "continuous mode setup @%dHz",
13748c2ecf20Sopenharmony_ci			    priv->frequency->hz);
13758c2ecf20Sopenharmony_ci	}
13768c2ecf20Sopenharmony_ci
13778c2ecf20Sopenharmony_ci	return 0;
13788c2ecf20Sopenharmony_ci}
13798c2ecf20Sopenharmony_ci
13808c2ecf20Sopenharmony_cistatic const struct iio_trigger_ops zpa2326_trigger_ops = {
13818c2ecf20Sopenharmony_ci	.set_trigger_state = zpa2326_set_trigger_state,
13828c2ecf20Sopenharmony_ci};
13838c2ecf20Sopenharmony_ci
13848c2ecf20Sopenharmony_ci/**
13858c2ecf20Sopenharmony_ci * zpa2326_init_trigger() - Create an interrupt driven / hardware trigger
13868c2ecf20Sopenharmony_ci *                          allowing to notify external devices a new sample is
13878c2ecf20Sopenharmony_ci *                          ready.
13888c2ecf20Sopenharmony_ci * @parent:    Hardware sampling device @indio_dev is a child of.
13898c2ecf20Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware.
13908c2ecf20Sopenharmony_ci * @private:   Internal private state related to @indio_dev.
13918c2ecf20Sopenharmony_ci * @irq:       Optional interrupt line the hardware uses to notify new data
13928c2ecf20Sopenharmony_ci *             samples are ready. Negative or zero values indicate no interrupts
13938c2ecf20Sopenharmony_ci *             are available, meaning polling is required.
13948c2ecf20Sopenharmony_ci *
13958c2ecf20Sopenharmony_ci * Only relevant when DT declares a valid interrupt line.
13968c2ecf20Sopenharmony_ci *
13978c2ecf20Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise.
13988c2ecf20Sopenharmony_ci */
13998c2ecf20Sopenharmony_cistatic int zpa2326_init_managed_trigger(struct device          *parent,
14008c2ecf20Sopenharmony_ci					struct iio_dev         *indio_dev,
14018c2ecf20Sopenharmony_ci					struct zpa2326_private *private,
14028c2ecf20Sopenharmony_ci					int                     irq)
14038c2ecf20Sopenharmony_ci{
14048c2ecf20Sopenharmony_ci	struct iio_trigger *trigger;
14058c2ecf20Sopenharmony_ci	int                 ret;
14068c2ecf20Sopenharmony_ci
14078c2ecf20Sopenharmony_ci	if (irq <= 0)
14088c2ecf20Sopenharmony_ci		return 0;
14098c2ecf20Sopenharmony_ci
14108c2ecf20Sopenharmony_ci	trigger = devm_iio_trigger_alloc(parent, "%s-dev%d",
14118c2ecf20Sopenharmony_ci					 indio_dev->name, indio_dev->id);
14128c2ecf20Sopenharmony_ci	if (!trigger)
14138c2ecf20Sopenharmony_ci		return -ENOMEM;
14148c2ecf20Sopenharmony_ci
14158c2ecf20Sopenharmony_ci	/* Basic setup. */
14168c2ecf20Sopenharmony_ci	trigger->dev.parent = parent;
14178c2ecf20Sopenharmony_ci	trigger->ops = &zpa2326_trigger_ops;
14188c2ecf20Sopenharmony_ci
14198c2ecf20Sopenharmony_ci	private->trigger = trigger;
14208c2ecf20Sopenharmony_ci
14218c2ecf20Sopenharmony_ci	/* Register to triggers space. */
14228c2ecf20Sopenharmony_ci	ret = devm_iio_trigger_register(parent, trigger);
14238c2ecf20Sopenharmony_ci	if (ret)
14248c2ecf20Sopenharmony_ci		dev_err(parent, "failed to register hardware trigger (%d)",
14258c2ecf20Sopenharmony_ci			ret);
14268c2ecf20Sopenharmony_ci
14278c2ecf20Sopenharmony_ci	return ret;
14288c2ecf20Sopenharmony_ci}
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_cistatic int zpa2326_get_frequency(const struct iio_dev *indio_dev)
14318c2ecf20Sopenharmony_ci{
14328c2ecf20Sopenharmony_ci	return ((struct zpa2326_private *)iio_priv(indio_dev))->frequency->hz;
14338c2ecf20Sopenharmony_ci}
14348c2ecf20Sopenharmony_ci
14358c2ecf20Sopenharmony_cistatic int zpa2326_set_frequency(struct iio_dev *indio_dev, int hz)
14368c2ecf20Sopenharmony_ci{
14378c2ecf20Sopenharmony_ci	struct zpa2326_private *priv = iio_priv(indio_dev);
14388c2ecf20Sopenharmony_ci	int                     freq;
14398c2ecf20Sopenharmony_ci	int                     err;
14408c2ecf20Sopenharmony_ci
14418c2ecf20Sopenharmony_ci	/* Check if requested frequency is supported. */
14428c2ecf20Sopenharmony_ci	for (freq = 0; freq < ARRAY_SIZE(zpa2326_sampling_frequencies); freq++)
14438c2ecf20Sopenharmony_ci		if (zpa2326_sampling_frequencies[freq].hz == hz)
14448c2ecf20Sopenharmony_ci			break;
14458c2ecf20Sopenharmony_ci	if (freq == ARRAY_SIZE(zpa2326_sampling_frequencies))
14468c2ecf20Sopenharmony_ci		return -EINVAL;
14478c2ecf20Sopenharmony_ci
14488c2ecf20Sopenharmony_ci	/* Don't allow changing frequency if buffered sampling is ongoing. */
14498c2ecf20Sopenharmony_ci	err = iio_device_claim_direct_mode(indio_dev);
14508c2ecf20Sopenharmony_ci	if (err)
14518c2ecf20Sopenharmony_ci		return err;
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_ci	priv->frequency = &zpa2326_sampling_frequencies[freq];
14548c2ecf20Sopenharmony_ci
14558c2ecf20Sopenharmony_ci	iio_device_release_direct_mode(indio_dev);
14568c2ecf20Sopenharmony_ci
14578c2ecf20Sopenharmony_ci	return 0;
14588c2ecf20Sopenharmony_ci}
14598c2ecf20Sopenharmony_ci
14608c2ecf20Sopenharmony_ci/* Expose supported hardware sampling frequencies (Hz) through sysfs. */
14618c2ecf20Sopenharmony_cistatic IIO_CONST_ATTR_SAMP_FREQ_AVAIL("1 5 11 23");
14628c2ecf20Sopenharmony_ci
14638c2ecf20Sopenharmony_cistatic struct attribute *zpa2326_attributes[] = {
14648c2ecf20Sopenharmony_ci	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
14658c2ecf20Sopenharmony_ci	NULL
14668c2ecf20Sopenharmony_ci};
14678c2ecf20Sopenharmony_ci
14688c2ecf20Sopenharmony_cistatic const struct attribute_group zpa2326_attribute_group = {
14698c2ecf20Sopenharmony_ci	.attrs = zpa2326_attributes,
14708c2ecf20Sopenharmony_ci};
14718c2ecf20Sopenharmony_ci
14728c2ecf20Sopenharmony_cistatic int zpa2326_read_raw(struct iio_dev             *indio_dev,
14738c2ecf20Sopenharmony_ci			    struct iio_chan_spec const *chan,
14748c2ecf20Sopenharmony_ci			    int                        *val,
14758c2ecf20Sopenharmony_ci			    int                        *val2,
14768c2ecf20Sopenharmony_ci			    long                        mask)
14778c2ecf20Sopenharmony_ci{
14788c2ecf20Sopenharmony_ci	switch (mask) {
14798c2ecf20Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
14808c2ecf20Sopenharmony_ci		return zpa2326_sample_oneshot(indio_dev, chan->type, val);
14818c2ecf20Sopenharmony_ci
14828c2ecf20Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
14838c2ecf20Sopenharmony_ci		switch (chan->type) {
14848c2ecf20Sopenharmony_ci		case IIO_PRESSURE:
14858c2ecf20Sopenharmony_ci			/*
14868c2ecf20Sopenharmony_ci			 * Pressure resolution is 1/64 Pascal. Scale to kPascal
14878c2ecf20Sopenharmony_ci			 * as required by IIO ABI.
14888c2ecf20Sopenharmony_ci			 */
14898c2ecf20Sopenharmony_ci			*val = 1;
14908c2ecf20Sopenharmony_ci			*val2 = 64000;
14918c2ecf20Sopenharmony_ci			return IIO_VAL_FRACTIONAL;
14928c2ecf20Sopenharmony_ci
14938c2ecf20Sopenharmony_ci		case IIO_TEMP:
14948c2ecf20Sopenharmony_ci			/*
14958c2ecf20Sopenharmony_ci			 * Temperature follows the equation:
14968c2ecf20Sopenharmony_ci			 *     Temp[degC] = Tempcode * 0.00649 - 176.83
14978c2ecf20Sopenharmony_ci			 * where:
14988c2ecf20Sopenharmony_ci			 *     Tempcode is composed the raw sampled 16 bits.
14998c2ecf20Sopenharmony_ci			 *
15008c2ecf20Sopenharmony_ci			 * Hence, to produce a temperature in milli-degrees
15018c2ecf20Sopenharmony_ci			 * Celsius according to IIO ABI, we need to apply the
15028c2ecf20Sopenharmony_ci			 * following equation to raw samples:
15038c2ecf20Sopenharmony_ci			 *     Temp[milli degC] = (Tempcode + Offset) * Scale
15048c2ecf20Sopenharmony_ci			 * where:
15058c2ecf20Sopenharmony_ci			 *     Offset = -176.83 / 0.00649
15068c2ecf20Sopenharmony_ci			 *     Scale = 0.00649 * 1000
15078c2ecf20Sopenharmony_ci			 */
15088c2ecf20Sopenharmony_ci			*val = 6;
15098c2ecf20Sopenharmony_ci			*val2 = 490000;
15108c2ecf20Sopenharmony_ci			return IIO_VAL_INT_PLUS_MICRO;
15118c2ecf20Sopenharmony_ci
15128c2ecf20Sopenharmony_ci		default:
15138c2ecf20Sopenharmony_ci			return -EINVAL;
15148c2ecf20Sopenharmony_ci		}
15158c2ecf20Sopenharmony_ci
15168c2ecf20Sopenharmony_ci	case IIO_CHAN_INFO_OFFSET:
15178c2ecf20Sopenharmony_ci		switch (chan->type) {
15188c2ecf20Sopenharmony_ci		case IIO_TEMP:
15198c2ecf20Sopenharmony_ci			*val = -17683000;
15208c2ecf20Sopenharmony_ci			*val2 = 649;
15218c2ecf20Sopenharmony_ci			return IIO_VAL_FRACTIONAL;
15228c2ecf20Sopenharmony_ci
15238c2ecf20Sopenharmony_ci		default:
15248c2ecf20Sopenharmony_ci			return -EINVAL;
15258c2ecf20Sopenharmony_ci		}
15268c2ecf20Sopenharmony_ci
15278c2ecf20Sopenharmony_ci	case IIO_CHAN_INFO_SAMP_FREQ:
15288c2ecf20Sopenharmony_ci		*val = zpa2326_get_frequency(indio_dev);
15298c2ecf20Sopenharmony_ci		return IIO_VAL_INT;
15308c2ecf20Sopenharmony_ci
15318c2ecf20Sopenharmony_ci	default:
15328c2ecf20Sopenharmony_ci		return -EINVAL;
15338c2ecf20Sopenharmony_ci	}
15348c2ecf20Sopenharmony_ci}
15358c2ecf20Sopenharmony_ci
15368c2ecf20Sopenharmony_cistatic int zpa2326_write_raw(struct iio_dev             *indio_dev,
15378c2ecf20Sopenharmony_ci			     const struct iio_chan_spec *chan,
15388c2ecf20Sopenharmony_ci			     int                         val,
15398c2ecf20Sopenharmony_ci			     int                         val2,
15408c2ecf20Sopenharmony_ci			     long                        mask)
15418c2ecf20Sopenharmony_ci{
15428c2ecf20Sopenharmony_ci	if ((mask != IIO_CHAN_INFO_SAMP_FREQ) || val2)
15438c2ecf20Sopenharmony_ci		return -EINVAL;
15448c2ecf20Sopenharmony_ci
15458c2ecf20Sopenharmony_ci	return zpa2326_set_frequency(indio_dev, val);
15468c2ecf20Sopenharmony_ci}
15478c2ecf20Sopenharmony_ci
15488c2ecf20Sopenharmony_cistatic const struct iio_chan_spec zpa2326_channels[] = {
15498c2ecf20Sopenharmony_ci	[0] = {
15508c2ecf20Sopenharmony_ci		.type                    = IIO_PRESSURE,
15518c2ecf20Sopenharmony_ci		.scan_index              = 0,
15528c2ecf20Sopenharmony_ci		.scan_type               = {
15538c2ecf20Sopenharmony_ci			.sign                   = 'u',
15548c2ecf20Sopenharmony_ci			.realbits               = 24,
15558c2ecf20Sopenharmony_ci			.storagebits            = 32,
15568c2ecf20Sopenharmony_ci			.endianness             = IIO_LE,
15578c2ecf20Sopenharmony_ci		},
15588c2ecf20Sopenharmony_ci		.info_mask_separate      = BIT(IIO_CHAN_INFO_RAW) |
15598c2ecf20Sopenharmony_ci					   BIT(IIO_CHAN_INFO_SCALE),
15608c2ecf20Sopenharmony_ci		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
15618c2ecf20Sopenharmony_ci	},
15628c2ecf20Sopenharmony_ci	[1] = {
15638c2ecf20Sopenharmony_ci		.type                    = IIO_TEMP,
15648c2ecf20Sopenharmony_ci		.scan_index              = 1,
15658c2ecf20Sopenharmony_ci		.scan_type               = {
15668c2ecf20Sopenharmony_ci			.sign                   = 's',
15678c2ecf20Sopenharmony_ci			.realbits               = 16,
15688c2ecf20Sopenharmony_ci			.storagebits            = 16,
15698c2ecf20Sopenharmony_ci			.endianness             = IIO_LE,
15708c2ecf20Sopenharmony_ci		},
15718c2ecf20Sopenharmony_ci		.info_mask_separate      = BIT(IIO_CHAN_INFO_RAW) |
15728c2ecf20Sopenharmony_ci					   BIT(IIO_CHAN_INFO_SCALE) |
15738c2ecf20Sopenharmony_ci					   BIT(IIO_CHAN_INFO_OFFSET),
15748c2ecf20Sopenharmony_ci		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
15758c2ecf20Sopenharmony_ci	},
15768c2ecf20Sopenharmony_ci	[2] = IIO_CHAN_SOFT_TIMESTAMP(2),
15778c2ecf20Sopenharmony_ci};
15788c2ecf20Sopenharmony_ci
15798c2ecf20Sopenharmony_cistatic const struct iio_info zpa2326_info = {
15808c2ecf20Sopenharmony_ci	.attrs         = &zpa2326_attribute_group,
15818c2ecf20Sopenharmony_ci	.read_raw      = zpa2326_read_raw,
15828c2ecf20Sopenharmony_ci	.write_raw     = zpa2326_write_raw,
15838c2ecf20Sopenharmony_ci};
15848c2ecf20Sopenharmony_ci
15858c2ecf20Sopenharmony_cistatic struct iio_dev *zpa2326_create_managed_iiodev(struct device *device,
15868c2ecf20Sopenharmony_ci						     const char    *name,
15878c2ecf20Sopenharmony_ci						     struct regmap *regmap)
15888c2ecf20Sopenharmony_ci{
15898c2ecf20Sopenharmony_ci	struct iio_dev *indio_dev;
15908c2ecf20Sopenharmony_ci
15918c2ecf20Sopenharmony_ci	/* Allocate space to hold IIO device internal state. */
15928c2ecf20Sopenharmony_ci	indio_dev = devm_iio_device_alloc(device,
15938c2ecf20Sopenharmony_ci					  sizeof(struct zpa2326_private));
15948c2ecf20Sopenharmony_ci	if (!indio_dev)
15958c2ecf20Sopenharmony_ci		return NULL;
15968c2ecf20Sopenharmony_ci
15978c2ecf20Sopenharmony_ci	/* Setup for userspace synchronous on demand sampling. */
15988c2ecf20Sopenharmony_ci	indio_dev->modes = INDIO_DIRECT_MODE;
15998c2ecf20Sopenharmony_ci	indio_dev->channels = zpa2326_channels;
16008c2ecf20Sopenharmony_ci	indio_dev->num_channels = ARRAY_SIZE(zpa2326_channels);
16018c2ecf20Sopenharmony_ci	indio_dev->name = name;
16028c2ecf20Sopenharmony_ci	indio_dev->info = &zpa2326_info;
16038c2ecf20Sopenharmony_ci
16048c2ecf20Sopenharmony_ci	return indio_dev;
16058c2ecf20Sopenharmony_ci}
16068c2ecf20Sopenharmony_ci
16078c2ecf20Sopenharmony_ciint zpa2326_probe(struct device *parent,
16088c2ecf20Sopenharmony_ci		  const char    *name,
16098c2ecf20Sopenharmony_ci		  int            irq,
16108c2ecf20Sopenharmony_ci		  unsigned int   hwid,
16118c2ecf20Sopenharmony_ci		  struct regmap *regmap)
16128c2ecf20Sopenharmony_ci{
16138c2ecf20Sopenharmony_ci	struct iio_dev         *indio_dev;
16148c2ecf20Sopenharmony_ci	struct zpa2326_private *priv;
16158c2ecf20Sopenharmony_ci	int                     err;
16168c2ecf20Sopenharmony_ci	unsigned int            id;
16178c2ecf20Sopenharmony_ci
16188c2ecf20Sopenharmony_ci	indio_dev = zpa2326_create_managed_iiodev(parent, name, regmap);
16198c2ecf20Sopenharmony_ci	if (!indio_dev)
16208c2ecf20Sopenharmony_ci		return -ENOMEM;
16218c2ecf20Sopenharmony_ci
16228c2ecf20Sopenharmony_ci	priv = iio_priv(indio_dev);
16238c2ecf20Sopenharmony_ci
16248c2ecf20Sopenharmony_ci	priv->vref = devm_regulator_get(parent, "vref");
16258c2ecf20Sopenharmony_ci	if (IS_ERR(priv->vref))
16268c2ecf20Sopenharmony_ci		return PTR_ERR(priv->vref);
16278c2ecf20Sopenharmony_ci
16288c2ecf20Sopenharmony_ci	priv->vdd = devm_regulator_get(parent, "vdd");
16298c2ecf20Sopenharmony_ci	if (IS_ERR(priv->vdd))
16308c2ecf20Sopenharmony_ci		return PTR_ERR(priv->vdd);
16318c2ecf20Sopenharmony_ci
16328c2ecf20Sopenharmony_ci	/* Set default hardware sampling frequency to highest rate supported. */
16338c2ecf20Sopenharmony_ci	priv->frequency = zpa2326_highest_frequency();
16348c2ecf20Sopenharmony_ci
16358c2ecf20Sopenharmony_ci	/*
16368c2ecf20Sopenharmony_ci	 * Plug device's underlying bus abstraction : this MUST be set before
16378c2ecf20Sopenharmony_ci	 * registering interrupt handlers since an interrupt might happen if
16388c2ecf20Sopenharmony_ci	 * power up sequence is not properly applied.
16398c2ecf20Sopenharmony_ci	 */
16408c2ecf20Sopenharmony_ci	priv->regmap = regmap;
16418c2ecf20Sopenharmony_ci
16428c2ecf20Sopenharmony_ci	err = devm_iio_triggered_buffer_setup(parent, indio_dev, NULL,
16438c2ecf20Sopenharmony_ci					      zpa2326_trigger_handler,
16448c2ecf20Sopenharmony_ci					      &zpa2326_buffer_setup_ops);
16458c2ecf20Sopenharmony_ci	if (err)
16468c2ecf20Sopenharmony_ci		return err;
16478c2ecf20Sopenharmony_ci
16488c2ecf20Sopenharmony_ci	err = zpa2326_init_managed_trigger(parent, indio_dev, priv, irq);
16498c2ecf20Sopenharmony_ci	if (err)
16508c2ecf20Sopenharmony_ci		return err;
16518c2ecf20Sopenharmony_ci
16528c2ecf20Sopenharmony_ci	err = zpa2326_init_managed_irq(parent, indio_dev, priv, irq);
16538c2ecf20Sopenharmony_ci	if (err)
16548c2ecf20Sopenharmony_ci		return err;
16558c2ecf20Sopenharmony_ci
16568c2ecf20Sopenharmony_ci	/* Power up to check device ID and perform initial hardware setup. */
16578c2ecf20Sopenharmony_ci	err = zpa2326_power_on(indio_dev, priv);
16588c2ecf20Sopenharmony_ci	if (err)
16598c2ecf20Sopenharmony_ci		return err;
16608c2ecf20Sopenharmony_ci
16618c2ecf20Sopenharmony_ci	/* Read id register to check we are talking to the right slave. */
16628c2ecf20Sopenharmony_ci	err = regmap_read(regmap, ZPA2326_DEVICE_ID_REG, &id);
16638c2ecf20Sopenharmony_ci	if (err)
16648c2ecf20Sopenharmony_ci		goto sleep;
16658c2ecf20Sopenharmony_ci
16668c2ecf20Sopenharmony_ci	if (id != hwid) {
16678c2ecf20Sopenharmony_ci		dev_err(parent, "found device with unexpected id %02x", id);
16688c2ecf20Sopenharmony_ci		err = -ENODEV;
16698c2ecf20Sopenharmony_ci		goto sleep;
16708c2ecf20Sopenharmony_ci	}
16718c2ecf20Sopenharmony_ci
16728c2ecf20Sopenharmony_ci	err = zpa2326_config_oneshot(indio_dev, irq);
16738c2ecf20Sopenharmony_ci	if (err)
16748c2ecf20Sopenharmony_ci		goto sleep;
16758c2ecf20Sopenharmony_ci
16768c2ecf20Sopenharmony_ci	/* Setup done : go sleeping. Device will be awaken upon user request. */
16778c2ecf20Sopenharmony_ci	err = zpa2326_sleep(indio_dev);
16788c2ecf20Sopenharmony_ci	if (err)
16798c2ecf20Sopenharmony_ci		goto poweroff;
16808c2ecf20Sopenharmony_ci
16818c2ecf20Sopenharmony_ci	dev_set_drvdata(parent, indio_dev);
16828c2ecf20Sopenharmony_ci
16838c2ecf20Sopenharmony_ci	zpa2326_init_runtime(parent);
16848c2ecf20Sopenharmony_ci
16858c2ecf20Sopenharmony_ci	err = iio_device_register(indio_dev);
16868c2ecf20Sopenharmony_ci	if (err) {
16878c2ecf20Sopenharmony_ci		zpa2326_fini_runtime(parent);
16888c2ecf20Sopenharmony_ci		goto poweroff;
16898c2ecf20Sopenharmony_ci	}
16908c2ecf20Sopenharmony_ci
16918c2ecf20Sopenharmony_ci	return 0;
16928c2ecf20Sopenharmony_ci
16938c2ecf20Sopenharmony_cisleep:
16948c2ecf20Sopenharmony_ci	/* Put to sleep just in case power regulators are "dummy" ones. */
16958c2ecf20Sopenharmony_ci	zpa2326_sleep(indio_dev);
16968c2ecf20Sopenharmony_cipoweroff:
16978c2ecf20Sopenharmony_ci	zpa2326_power_off(indio_dev, priv);
16988c2ecf20Sopenharmony_ci
16998c2ecf20Sopenharmony_ci	return err;
17008c2ecf20Sopenharmony_ci}
17018c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(zpa2326_probe);
17028c2ecf20Sopenharmony_ci
17038c2ecf20Sopenharmony_civoid zpa2326_remove(const struct device *parent)
17048c2ecf20Sopenharmony_ci{
17058c2ecf20Sopenharmony_ci	struct iio_dev *indio_dev = dev_get_drvdata(parent);
17068c2ecf20Sopenharmony_ci
17078c2ecf20Sopenharmony_ci	iio_device_unregister(indio_dev);
17088c2ecf20Sopenharmony_ci	zpa2326_fini_runtime(indio_dev->dev.parent);
17098c2ecf20Sopenharmony_ci	zpa2326_sleep(indio_dev);
17108c2ecf20Sopenharmony_ci	zpa2326_power_off(indio_dev, iio_priv(indio_dev));
17118c2ecf20Sopenharmony_ci}
17128c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(zpa2326_remove);
17138c2ecf20Sopenharmony_ci
17148c2ecf20Sopenharmony_ciMODULE_AUTHOR("Gregor Boirie <gregor.boirie@parrot.com>");
17158c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Core driver for Murata ZPA2326 pressure sensor");
17168c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
1717