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