162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Murata ZPA2326 pressure and temperature sensor IIO driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2016 Parrot S.A. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Author: Gregor Boirie <gregor.boirie@parrot.com> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci/** 1162306a36Sopenharmony_ci * DOC: ZPA2326 theory of operations 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * This driver supports %INDIO_DIRECT_MODE and %INDIO_BUFFER_TRIGGERED IIO 1462306a36Sopenharmony_ci * modes. 1562306a36Sopenharmony_ci * A internal hardware trigger is also implemented to dispatch registered IIO 1662306a36Sopenharmony_ci * trigger consumers upon "sample ready" interrupts. 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * ZPA2326 hardware supports 2 sampling mode: one shot and continuous. 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * A complete one shot sampling cycle gets device out of low power mode, 2162306a36Sopenharmony_ci * performs pressure and temperature measurements, then automatically switches 2262306a36Sopenharmony_ci * back to low power mode. It is meant for on demand sampling with optimal power 2362306a36Sopenharmony_ci * saving at the cost of lower sampling rate and higher software overhead. 2462306a36Sopenharmony_ci * This is a natural candidate for IIO read_raw hook implementation 2562306a36Sopenharmony_ci * (%INDIO_DIRECT_MODE). It is also used for triggered buffering support to 2662306a36Sopenharmony_ci * ensure explicit synchronization with external trigger events 2762306a36Sopenharmony_ci * (%INDIO_BUFFER_TRIGGERED). 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * The continuous mode works according to a periodic hardware measurement 3062306a36Sopenharmony_ci * process continuously pushing samples into an internal hardware FIFO (for 3162306a36Sopenharmony_ci * pressure samples only). Measurement cycle completion may be signaled by a 3262306a36Sopenharmony_ci * "sample ready" interrupt. 3362306a36Sopenharmony_ci * Typical software sequence of operations : 3462306a36Sopenharmony_ci * - get device out of low power mode, 3562306a36Sopenharmony_ci * - setup hardware sampling period, 3662306a36Sopenharmony_ci * - at end of period, upon data ready interrupt: pop pressure samples out of 3762306a36Sopenharmony_ci * hardware FIFO and fetch temperature sample 3862306a36Sopenharmony_ci * - when no longer needed, stop sampling process by putting device into 3962306a36Sopenharmony_ci * low power mode. 4062306a36Sopenharmony_ci * This mode is used to implement %INDIO_BUFFER_TRIGGERED mode if device tree 4162306a36Sopenharmony_ci * declares a valid interrupt line. In this case, the internal hardware trigger 4262306a36Sopenharmony_ci * drives acquisition. 4362306a36Sopenharmony_ci * 4462306a36Sopenharmony_ci * Note that hardware sampling frequency is taken into account only when 4562306a36Sopenharmony_ci * internal hardware trigger is attached as the highest sampling rate seems to 4662306a36Sopenharmony_ci * be the most energy efficient. 4762306a36Sopenharmony_ci * 4862306a36Sopenharmony_ci * TODO: 4962306a36Sopenharmony_ci * preset pressure threshold crossing / IIO events ; 5062306a36Sopenharmony_ci * differential pressure sampling ; 5162306a36Sopenharmony_ci * hardware samples averaging. 5262306a36Sopenharmony_ci */ 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#include <linux/module.h> 5562306a36Sopenharmony_ci#include <linux/kernel.h> 5662306a36Sopenharmony_ci#include <linux/delay.h> 5762306a36Sopenharmony_ci#include <linux/interrupt.h> 5862306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 5962306a36Sopenharmony_ci#include <linux/pm_runtime.h> 6062306a36Sopenharmony_ci#include <linux/regmap.h> 6162306a36Sopenharmony_ci#include <linux/iio/iio.h> 6262306a36Sopenharmony_ci#include <linux/iio/sysfs.h> 6362306a36Sopenharmony_ci#include <linux/iio/buffer.h> 6462306a36Sopenharmony_ci#include <linux/iio/trigger.h> 6562306a36Sopenharmony_ci#include <linux/iio/trigger_consumer.h> 6662306a36Sopenharmony_ci#include <linux/iio/triggered_buffer.h> 6762306a36Sopenharmony_ci#include <asm/unaligned.h> 6862306a36Sopenharmony_ci#include "zpa2326.h" 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci/* 200 ms should be enough for the longest conversion time in one-shot mode. */ 7162306a36Sopenharmony_ci#define ZPA2326_CONVERSION_JIFFIES (HZ / 5) 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci/* There should be a 1 ms delay (Tpup) after getting out of reset. */ 7462306a36Sopenharmony_ci#define ZPA2326_TPUP_USEC_MIN (1000) 7562306a36Sopenharmony_ci#define ZPA2326_TPUP_USEC_MAX (2000) 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci/** 7862306a36Sopenharmony_ci * struct zpa2326_frequency - Hardware sampling frequency descriptor 7962306a36Sopenharmony_ci * @hz : Frequency in Hertz. 8062306a36Sopenharmony_ci * @odr: Output Data Rate word as expected by %ZPA2326_CTRL_REG3_REG. 8162306a36Sopenharmony_ci */ 8262306a36Sopenharmony_cistruct zpa2326_frequency { 8362306a36Sopenharmony_ci int hz; 8462306a36Sopenharmony_ci u16 odr; 8562306a36Sopenharmony_ci}; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci/* 8862306a36Sopenharmony_ci * Keep these in strict ascending order: last array entry is expected to 8962306a36Sopenharmony_ci * correspond to the highest sampling frequency. 9062306a36Sopenharmony_ci */ 9162306a36Sopenharmony_cistatic const struct zpa2326_frequency zpa2326_sampling_frequencies[] = { 9262306a36Sopenharmony_ci { .hz = 1, .odr = 1 << ZPA2326_CTRL_REG3_ODR_SHIFT }, 9362306a36Sopenharmony_ci { .hz = 5, .odr = 5 << ZPA2326_CTRL_REG3_ODR_SHIFT }, 9462306a36Sopenharmony_ci { .hz = 11, .odr = 6 << ZPA2326_CTRL_REG3_ODR_SHIFT }, 9562306a36Sopenharmony_ci { .hz = 23, .odr = 7 << ZPA2326_CTRL_REG3_ODR_SHIFT }, 9662306a36Sopenharmony_ci}; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci/* Return the highest hardware sampling frequency available. */ 9962306a36Sopenharmony_cistatic const struct zpa2326_frequency *zpa2326_highest_frequency(void) 10062306a36Sopenharmony_ci{ 10162306a36Sopenharmony_ci return &zpa2326_sampling_frequencies[ 10262306a36Sopenharmony_ci ARRAY_SIZE(zpa2326_sampling_frequencies) - 1]; 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci/** 10662306a36Sopenharmony_ci * struct zpa2326_private - Per-device internal private state 10762306a36Sopenharmony_ci * @timestamp: Buffered samples ready datum. 10862306a36Sopenharmony_ci * @regmap: Underlying I2C / SPI bus adapter used to abstract slave register 10962306a36Sopenharmony_ci * accesses. 11062306a36Sopenharmony_ci * @result: Allows sampling logic to get completion status of operations 11162306a36Sopenharmony_ci * that interrupt handlers perform asynchronously. 11262306a36Sopenharmony_ci * @data_ready: Interrupt handler uses this to wake user context up at sampling 11362306a36Sopenharmony_ci * operation completion. 11462306a36Sopenharmony_ci * @trigger: Optional hardware / interrupt driven trigger used to notify 11562306a36Sopenharmony_ci * external devices a new sample is ready. 11662306a36Sopenharmony_ci * @waken: Flag indicating whether or not device has just been powered on. 11762306a36Sopenharmony_ci * @irq: Optional interrupt line: negative or zero if not declared into 11862306a36Sopenharmony_ci * DT, in which case sampling logic keeps polling status register 11962306a36Sopenharmony_ci * to detect completion. 12062306a36Sopenharmony_ci * @frequency: Current hardware sampling frequency. 12162306a36Sopenharmony_ci * @vref: Power / voltage reference. 12262306a36Sopenharmony_ci * @vdd: Power supply. 12362306a36Sopenharmony_ci */ 12462306a36Sopenharmony_cistruct zpa2326_private { 12562306a36Sopenharmony_ci s64 timestamp; 12662306a36Sopenharmony_ci struct regmap *regmap; 12762306a36Sopenharmony_ci int result; 12862306a36Sopenharmony_ci struct completion data_ready; 12962306a36Sopenharmony_ci struct iio_trigger *trigger; 13062306a36Sopenharmony_ci bool waken; 13162306a36Sopenharmony_ci int irq; 13262306a36Sopenharmony_ci const struct zpa2326_frequency *frequency; 13362306a36Sopenharmony_ci struct regulator *vref; 13462306a36Sopenharmony_ci struct regulator *vdd; 13562306a36Sopenharmony_ci}; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci#define zpa2326_err(idev, fmt, ...) \ 13862306a36Sopenharmony_ci dev_err(idev->dev.parent, fmt "\n", ##__VA_ARGS__) 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci#define zpa2326_warn(idev, fmt, ...) \ 14162306a36Sopenharmony_ci dev_warn(idev->dev.parent, fmt "\n", ##__VA_ARGS__) 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci#define zpa2326_dbg(idev, fmt, ...) \ 14462306a36Sopenharmony_ci dev_dbg(idev->dev.parent, fmt "\n", ##__VA_ARGS__) 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cibool zpa2326_isreg_writeable(struct device *dev, unsigned int reg) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci switch (reg) { 14962306a36Sopenharmony_ci case ZPA2326_REF_P_XL_REG: 15062306a36Sopenharmony_ci case ZPA2326_REF_P_L_REG: 15162306a36Sopenharmony_ci case ZPA2326_REF_P_H_REG: 15262306a36Sopenharmony_ci case ZPA2326_RES_CONF_REG: 15362306a36Sopenharmony_ci case ZPA2326_CTRL_REG0_REG: 15462306a36Sopenharmony_ci case ZPA2326_CTRL_REG1_REG: 15562306a36Sopenharmony_ci case ZPA2326_CTRL_REG2_REG: 15662306a36Sopenharmony_ci case ZPA2326_CTRL_REG3_REG: 15762306a36Sopenharmony_ci case ZPA2326_THS_P_LOW_REG: 15862306a36Sopenharmony_ci case ZPA2326_THS_P_HIGH_REG: 15962306a36Sopenharmony_ci return true; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci default: 16262306a36Sopenharmony_ci return false; 16362306a36Sopenharmony_ci } 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(zpa2326_isreg_writeable, IIO_ZPA2326); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_cibool zpa2326_isreg_readable(struct device *dev, unsigned int reg) 16862306a36Sopenharmony_ci{ 16962306a36Sopenharmony_ci switch (reg) { 17062306a36Sopenharmony_ci case ZPA2326_REF_P_XL_REG: 17162306a36Sopenharmony_ci case ZPA2326_REF_P_L_REG: 17262306a36Sopenharmony_ci case ZPA2326_REF_P_H_REG: 17362306a36Sopenharmony_ci case ZPA2326_DEVICE_ID_REG: 17462306a36Sopenharmony_ci case ZPA2326_RES_CONF_REG: 17562306a36Sopenharmony_ci case ZPA2326_CTRL_REG0_REG: 17662306a36Sopenharmony_ci case ZPA2326_CTRL_REG1_REG: 17762306a36Sopenharmony_ci case ZPA2326_CTRL_REG2_REG: 17862306a36Sopenharmony_ci case ZPA2326_CTRL_REG3_REG: 17962306a36Sopenharmony_ci case ZPA2326_INT_SOURCE_REG: 18062306a36Sopenharmony_ci case ZPA2326_THS_P_LOW_REG: 18162306a36Sopenharmony_ci case ZPA2326_THS_P_HIGH_REG: 18262306a36Sopenharmony_ci case ZPA2326_STATUS_REG: 18362306a36Sopenharmony_ci case ZPA2326_PRESS_OUT_XL_REG: 18462306a36Sopenharmony_ci case ZPA2326_PRESS_OUT_L_REG: 18562306a36Sopenharmony_ci case ZPA2326_PRESS_OUT_H_REG: 18662306a36Sopenharmony_ci case ZPA2326_TEMP_OUT_L_REG: 18762306a36Sopenharmony_ci case ZPA2326_TEMP_OUT_H_REG: 18862306a36Sopenharmony_ci return true; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci default: 19162306a36Sopenharmony_ci return false; 19262306a36Sopenharmony_ci } 19362306a36Sopenharmony_ci} 19462306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(zpa2326_isreg_readable, IIO_ZPA2326); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cibool zpa2326_isreg_precious(struct device *dev, unsigned int reg) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci switch (reg) { 19962306a36Sopenharmony_ci case ZPA2326_INT_SOURCE_REG: 20062306a36Sopenharmony_ci case ZPA2326_PRESS_OUT_H_REG: 20162306a36Sopenharmony_ci return true; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci default: 20462306a36Sopenharmony_ci return false; 20562306a36Sopenharmony_ci } 20662306a36Sopenharmony_ci} 20762306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(zpa2326_isreg_precious, IIO_ZPA2326); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci/** 21062306a36Sopenharmony_ci * zpa2326_enable_device() - Enable device, i.e. get out of low power mode. 21162306a36Sopenharmony_ci * @indio_dev: The IIO device associated with the hardware to enable. 21262306a36Sopenharmony_ci * 21362306a36Sopenharmony_ci * Required to access complete register space and to perform any sampling 21462306a36Sopenharmony_ci * or control operations. 21562306a36Sopenharmony_ci * 21662306a36Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise. 21762306a36Sopenharmony_ci */ 21862306a36Sopenharmony_cistatic int zpa2326_enable_device(const struct iio_dev *indio_dev) 21962306a36Sopenharmony_ci{ 22062306a36Sopenharmony_ci int err; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci err = regmap_write(((struct zpa2326_private *) 22362306a36Sopenharmony_ci iio_priv(indio_dev))->regmap, 22462306a36Sopenharmony_ci ZPA2326_CTRL_REG0_REG, ZPA2326_CTRL_REG0_ENABLE); 22562306a36Sopenharmony_ci if (err) { 22662306a36Sopenharmony_ci zpa2326_err(indio_dev, "failed to enable device (%d)", err); 22762306a36Sopenharmony_ci return err; 22862306a36Sopenharmony_ci } 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci zpa2326_dbg(indio_dev, "enabled"); 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci return 0; 23362306a36Sopenharmony_ci} 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci/** 23662306a36Sopenharmony_ci * zpa2326_sleep() - Disable device, i.e. switch to low power mode. 23762306a36Sopenharmony_ci * @indio_dev: The IIO device associated with the hardware to disable. 23862306a36Sopenharmony_ci * 23962306a36Sopenharmony_ci * Only %ZPA2326_DEVICE_ID_REG and %ZPA2326_CTRL_REG0_REG registers may be 24062306a36Sopenharmony_ci * accessed once device is in the disabled state. 24162306a36Sopenharmony_ci * 24262306a36Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise. 24362306a36Sopenharmony_ci */ 24462306a36Sopenharmony_cistatic int zpa2326_sleep(const struct iio_dev *indio_dev) 24562306a36Sopenharmony_ci{ 24662306a36Sopenharmony_ci int err; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci err = regmap_write(((struct zpa2326_private *) 24962306a36Sopenharmony_ci iio_priv(indio_dev))->regmap, 25062306a36Sopenharmony_ci ZPA2326_CTRL_REG0_REG, 0); 25162306a36Sopenharmony_ci if (err) { 25262306a36Sopenharmony_ci zpa2326_err(indio_dev, "failed to sleep (%d)", err); 25362306a36Sopenharmony_ci return err; 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci zpa2326_dbg(indio_dev, "sleeping"); 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci return 0; 25962306a36Sopenharmony_ci} 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci/** 26262306a36Sopenharmony_ci * zpa2326_reset_device() - Reset device to default hardware state. 26362306a36Sopenharmony_ci * @indio_dev: The IIO device associated with the hardware to reset. 26462306a36Sopenharmony_ci * 26562306a36Sopenharmony_ci * Disable sampling and empty hardware FIFO. 26662306a36Sopenharmony_ci * Device must be enabled before reset, i.e. not in low power mode. 26762306a36Sopenharmony_ci * 26862306a36Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise. 26962306a36Sopenharmony_ci */ 27062306a36Sopenharmony_cistatic int zpa2326_reset_device(const struct iio_dev *indio_dev) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci int err; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci err = regmap_write(((struct zpa2326_private *) 27562306a36Sopenharmony_ci iio_priv(indio_dev))->regmap, 27662306a36Sopenharmony_ci ZPA2326_CTRL_REG2_REG, ZPA2326_CTRL_REG2_SWRESET); 27762306a36Sopenharmony_ci if (err) { 27862306a36Sopenharmony_ci zpa2326_err(indio_dev, "failed to reset device (%d)", err); 27962306a36Sopenharmony_ci return err; 28062306a36Sopenharmony_ci } 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci usleep_range(ZPA2326_TPUP_USEC_MIN, ZPA2326_TPUP_USEC_MAX); 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci zpa2326_dbg(indio_dev, "reset"); 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci return 0; 28762306a36Sopenharmony_ci} 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci/** 29062306a36Sopenharmony_ci * zpa2326_start_oneshot() - Start a single sampling cycle, i.e. in one shot 29162306a36Sopenharmony_ci * mode. 29262306a36Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware. 29362306a36Sopenharmony_ci * 29462306a36Sopenharmony_ci * Device must have been previously enabled and configured for one shot mode. 29562306a36Sopenharmony_ci * Device will be switched back to low power mode at end of cycle. 29662306a36Sopenharmony_ci * 29762306a36Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise. 29862306a36Sopenharmony_ci */ 29962306a36Sopenharmony_cistatic int zpa2326_start_oneshot(const struct iio_dev *indio_dev) 30062306a36Sopenharmony_ci{ 30162306a36Sopenharmony_ci int err; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci err = regmap_write(((struct zpa2326_private *) 30462306a36Sopenharmony_ci iio_priv(indio_dev))->regmap, 30562306a36Sopenharmony_ci ZPA2326_CTRL_REG0_REG, 30662306a36Sopenharmony_ci ZPA2326_CTRL_REG0_ENABLE | 30762306a36Sopenharmony_ci ZPA2326_CTRL_REG0_ONE_SHOT); 30862306a36Sopenharmony_ci if (err) { 30962306a36Sopenharmony_ci zpa2326_err(indio_dev, "failed to start one shot cycle (%d)", 31062306a36Sopenharmony_ci err); 31162306a36Sopenharmony_ci return err; 31262306a36Sopenharmony_ci } 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci zpa2326_dbg(indio_dev, "one shot cycle started"); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci return 0; 31762306a36Sopenharmony_ci} 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci/** 32062306a36Sopenharmony_ci * zpa2326_power_on() - Power on device to allow subsequent configuration. 32162306a36Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware. 32262306a36Sopenharmony_ci * @private: Internal private state related to @indio_dev. 32362306a36Sopenharmony_ci * 32462306a36Sopenharmony_ci * Sampling will be disabled, preventing strange things from happening in our 32562306a36Sopenharmony_ci * back. Hardware FIFO content will be cleared. 32662306a36Sopenharmony_ci * When successful, device will be left in the enabled state to allow further 32762306a36Sopenharmony_ci * configuration. 32862306a36Sopenharmony_ci * 32962306a36Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise. 33062306a36Sopenharmony_ci */ 33162306a36Sopenharmony_cistatic int zpa2326_power_on(const struct iio_dev *indio_dev, 33262306a36Sopenharmony_ci const struct zpa2326_private *private) 33362306a36Sopenharmony_ci{ 33462306a36Sopenharmony_ci int err; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci err = regulator_enable(private->vref); 33762306a36Sopenharmony_ci if (err) 33862306a36Sopenharmony_ci return err; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci err = regulator_enable(private->vdd); 34162306a36Sopenharmony_ci if (err) 34262306a36Sopenharmony_ci goto vref; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci zpa2326_dbg(indio_dev, "powered on"); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci err = zpa2326_enable_device(indio_dev); 34762306a36Sopenharmony_ci if (err) 34862306a36Sopenharmony_ci goto vdd; 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci err = zpa2326_reset_device(indio_dev); 35162306a36Sopenharmony_ci if (err) 35262306a36Sopenharmony_ci goto sleep; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci return 0; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_cisleep: 35762306a36Sopenharmony_ci zpa2326_sleep(indio_dev); 35862306a36Sopenharmony_civdd: 35962306a36Sopenharmony_ci regulator_disable(private->vdd); 36062306a36Sopenharmony_civref: 36162306a36Sopenharmony_ci regulator_disable(private->vref); 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci zpa2326_dbg(indio_dev, "powered off"); 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci return err; 36662306a36Sopenharmony_ci} 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci/** 36962306a36Sopenharmony_ci * zpa2326_power_off() - Power off device, i.e. disable attached power 37062306a36Sopenharmony_ci * regulators. 37162306a36Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware. 37262306a36Sopenharmony_ci * @private: Internal private state related to @indio_dev. 37362306a36Sopenharmony_ci * 37462306a36Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise. 37562306a36Sopenharmony_ci */ 37662306a36Sopenharmony_cistatic void zpa2326_power_off(const struct iio_dev *indio_dev, 37762306a36Sopenharmony_ci const struct zpa2326_private *private) 37862306a36Sopenharmony_ci{ 37962306a36Sopenharmony_ci regulator_disable(private->vdd); 38062306a36Sopenharmony_ci regulator_disable(private->vref); 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci zpa2326_dbg(indio_dev, "powered off"); 38362306a36Sopenharmony_ci} 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci/** 38662306a36Sopenharmony_ci * zpa2326_config_oneshot() - Setup device for one shot / on demand mode. 38762306a36Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware. 38862306a36Sopenharmony_ci * @irq: Optional interrupt line the hardware uses to notify new data 38962306a36Sopenharmony_ci * samples are ready. Negative or zero values indicate no interrupts 39062306a36Sopenharmony_ci * are available, meaning polling is required. 39162306a36Sopenharmony_ci * 39262306a36Sopenharmony_ci * Output Data Rate is configured for the highest possible rate so that 39362306a36Sopenharmony_ci * conversion time and power consumption are reduced to a minimum. 39462306a36Sopenharmony_ci * Note that hardware internal averaging machinery (not implemented in this 39562306a36Sopenharmony_ci * driver) is not applicable in this mode. 39662306a36Sopenharmony_ci * 39762306a36Sopenharmony_ci * Device must have been previously enabled before calling 39862306a36Sopenharmony_ci * zpa2326_config_oneshot(). 39962306a36Sopenharmony_ci * 40062306a36Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise. 40162306a36Sopenharmony_ci */ 40262306a36Sopenharmony_cistatic int zpa2326_config_oneshot(const struct iio_dev *indio_dev, 40362306a36Sopenharmony_ci int irq) 40462306a36Sopenharmony_ci{ 40562306a36Sopenharmony_ci struct regmap *regs = ((struct zpa2326_private *) 40662306a36Sopenharmony_ci iio_priv(indio_dev))->regmap; 40762306a36Sopenharmony_ci const struct zpa2326_frequency *freq = zpa2326_highest_frequency(); 40862306a36Sopenharmony_ci int err; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci /* Setup highest available Output Data Rate for one shot mode. */ 41162306a36Sopenharmony_ci err = regmap_write(regs, ZPA2326_CTRL_REG3_REG, freq->odr); 41262306a36Sopenharmony_ci if (err) 41362306a36Sopenharmony_ci return err; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci if (irq > 0) { 41662306a36Sopenharmony_ci /* Request interrupt when new sample is available. */ 41762306a36Sopenharmony_ci err = regmap_write(regs, ZPA2326_CTRL_REG1_REG, 41862306a36Sopenharmony_ci (u8)~ZPA2326_CTRL_REG1_MASK_DATA_READY); 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci if (err) { 42162306a36Sopenharmony_ci dev_err(indio_dev->dev.parent, 42262306a36Sopenharmony_ci "failed to setup one shot mode (%d)", err); 42362306a36Sopenharmony_ci return err; 42462306a36Sopenharmony_ci } 42562306a36Sopenharmony_ci } 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci zpa2326_dbg(indio_dev, "one shot mode setup @%dHz", freq->hz); 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci return 0; 43062306a36Sopenharmony_ci} 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci/** 43362306a36Sopenharmony_ci * zpa2326_clear_fifo() - Clear remaining entries in hardware FIFO. 43462306a36Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware. 43562306a36Sopenharmony_ci * @min_count: Number of samples present within hardware FIFO. 43662306a36Sopenharmony_ci * 43762306a36Sopenharmony_ci * @min_count argument is a hint corresponding to the known minimum number of 43862306a36Sopenharmony_ci * samples currently living in the FIFO. This allows to reduce the number of bus 43962306a36Sopenharmony_ci * accesses by skipping status register read operation as long as we know for 44062306a36Sopenharmony_ci * sure there are still entries left. 44162306a36Sopenharmony_ci * 44262306a36Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise. 44362306a36Sopenharmony_ci */ 44462306a36Sopenharmony_cistatic int zpa2326_clear_fifo(const struct iio_dev *indio_dev, 44562306a36Sopenharmony_ci unsigned int min_count) 44662306a36Sopenharmony_ci{ 44762306a36Sopenharmony_ci struct regmap *regs = ((struct zpa2326_private *) 44862306a36Sopenharmony_ci iio_priv(indio_dev))->regmap; 44962306a36Sopenharmony_ci int err; 45062306a36Sopenharmony_ci unsigned int val; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci if (!min_count) { 45362306a36Sopenharmony_ci /* 45462306a36Sopenharmony_ci * No hint: read status register to determine whether FIFO is 45562306a36Sopenharmony_ci * empty or not. 45662306a36Sopenharmony_ci */ 45762306a36Sopenharmony_ci err = regmap_read(regs, ZPA2326_STATUS_REG, &val); 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci if (err < 0) 46062306a36Sopenharmony_ci goto err; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci if (val & ZPA2326_STATUS_FIFO_E) 46362306a36Sopenharmony_ci /* Fifo is empty: nothing to trash. */ 46462306a36Sopenharmony_ci return 0; 46562306a36Sopenharmony_ci } 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci /* Clear FIFO. */ 46862306a36Sopenharmony_ci do { 46962306a36Sopenharmony_ci /* 47062306a36Sopenharmony_ci * A single fetch from pressure MSB register is enough to pop 47162306a36Sopenharmony_ci * values out of FIFO. 47262306a36Sopenharmony_ci */ 47362306a36Sopenharmony_ci err = regmap_read(regs, ZPA2326_PRESS_OUT_H_REG, &val); 47462306a36Sopenharmony_ci if (err < 0) 47562306a36Sopenharmony_ci goto err; 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci if (min_count) { 47862306a36Sopenharmony_ci /* 47962306a36Sopenharmony_ci * We know for sure there are at least min_count entries 48062306a36Sopenharmony_ci * left in FIFO. Skip status register read. 48162306a36Sopenharmony_ci */ 48262306a36Sopenharmony_ci min_count--; 48362306a36Sopenharmony_ci continue; 48462306a36Sopenharmony_ci } 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci err = regmap_read(regs, ZPA2326_STATUS_REG, &val); 48762306a36Sopenharmony_ci if (err < 0) 48862306a36Sopenharmony_ci goto err; 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci } while (!(val & ZPA2326_STATUS_FIFO_E)); 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci zpa2326_dbg(indio_dev, "FIFO cleared"); 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci return 0; 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_cierr: 49762306a36Sopenharmony_ci zpa2326_err(indio_dev, "failed to clear FIFO (%d)", err); 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci return err; 50062306a36Sopenharmony_ci} 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci/** 50362306a36Sopenharmony_ci * zpa2326_dequeue_pressure() - Retrieve the most recent pressure sample from 50462306a36Sopenharmony_ci * hardware FIFO. 50562306a36Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware. 50662306a36Sopenharmony_ci * @pressure: Sampled pressure output. 50762306a36Sopenharmony_ci * 50862306a36Sopenharmony_ci * Note that ZPA2326 hardware FIFO stores pressure samples only. 50962306a36Sopenharmony_ci * 51062306a36Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise. 51162306a36Sopenharmony_ci */ 51262306a36Sopenharmony_cistatic int zpa2326_dequeue_pressure(const struct iio_dev *indio_dev, 51362306a36Sopenharmony_ci u32 *pressure) 51462306a36Sopenharmony_ci{ 51562306a36Sopenharmony_ci struct regmap *regs = ((struct zpa2326_private *) 51662306a36Sopenharmony_ci iio_priv(indio_dev))->regmap; 51762306a36Sopenharmony_ci unsigned int val; 51862306a36Sopenharmony_ci int err; 51962306a36Sopenharmony_ci int cleared = -1; 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci err = regmap_read(regs, ZPA2326_STATUS_REG, &val); 52262306a36Sopenharmony_ci if (err < 0) 52362306a36Sopenharmony_ci return err; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci *pressure = 0; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci if (val & ZPA2326_STATUS_P_OR) { 52862306a36Sopenharmony_ci /* 52962306a36Sopenharmony_ci * Fifo overrun : first sample dequeued from FIFO is the 53062306a36Sopenharmony_ci * newest. 53162306a36Sopenharmony_ci */ 53262306a36Sopenharmony_ci zpa2326_warn(indio_dev, "FIFO overflow"); 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci err = regmap_bulk_read(regs, ZPA2326_PRESS_OUT_XL_REG, pressure, 53562306a36Sopenharmony_ci 3); 53662306a36Sopenharmony_ci if (err) 53762306a36Sopenharmony_ci return err; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci#define ZPA2326_FIFO_DEPTH (16U) 54062306a36Sopenharmony_ci /* Hardware FIFO may hold no more than 16 pressure samples. */ 54162306a36Sopenharmony_ci return zpa2326_clear_fifo(indio_dev, ZPA2326_FIFO_DEPTH - 1); 54262306a36Sopenharmony_ci } 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci /* 54562306a36Sopenharmony_ci * Fifo has not overflown : retrieve newest sample. We need to pop 54662306a36Sopenharmony_ci * values out until FIFO is empty : last fetched pressure is the newest. 54762306a36Sopenharmony_ci * In nominal cases, we should find a single queued sample only. 54862306a36Sopenharmony_ci */ 54962306a36Sopenharmony_ci do { 55062306a36Sopenharmony_ci err = regmap_bulk_read(regs, ZPA2326_PRESS_OUT_XL_REG, pressure, 55162306a36Sopenharmony_ci 3); 55262306a36Sopenharmony_ci if (err) 55362306a36Sopenharmony_ci return err; 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci err = regmap_read(regs, ZPA2326_STATUS_REG, &val); 55662306a36Sopenharmony_ci if (err < 0) 55762306a36Sopenharmony_ci return err; 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci cleared++; 56062306a36Sopenharmony_ci } while (!(val & ZPA2326_STATUS_FIFO_E)); 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci if (cleared) 56362306a36Sopenharmony_ci /* 56462306a36Sopenharmony_ci * Samples were pushed by hardware during previous rounds but we 56562306a36Sopenharmony_ci * didn't consume them fast enough: inform user. 56662306a36Sopenharmony_ci */ 56762306a36Sopenharmony_ci zpa2326_dbg(indio_dev, "cleared %d FIFO entries", cleared); 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci return 0; 57062306a36Sopenharmony_ci} 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci/** 57362306a36Sopenharmony_ci * zpa2326_fill_sample_buffer() - Enqueue new channel samples to IIO buffer. 57462306a36Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware. 57562306a36Sopenharmony_ci * @private: Internal private state related to @indio_dev. 57662306a36Sopenharmony_ci * 57762306a36Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise. 57862306a36Sopenharmony_ci */ 57962306a36Sopenharmony_cistatic int zpa2326_fill_sample_buffer(struct iio_dev *indio_dev, 58062306a36Sopenharmony_ci const struct zpa2326_private *private) 58162306a36Sopenharmony_ci{ 58262306a36Sopenharmony_ci struct { 58362306a36Sopenharmony_ci u32 pressure; 58462306a36Sopenharmony_ci u16 temperature; 58562306a36Sopenharmony_ci u64 timestamp; 58662306a36Sopenharmony_ci } sample; 58762306a36Sopenharmony_ci int err; 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci if (test_bit(0, indio_dev->active_scan_mask)) { 59062306a36Sopenharmony_ci /* Get current pressure from hardware FIFO. */ 59162306a36Sopenharmony_ci err = zpa2326_dequeue_pressure(indio_dev, &sample.pressure); 59262306a36Sopenharmony_ci if (err) { 59362306a36Sopenharmony_ci zpa2326_warn(indio_dev, "failed to fetch pressure (%d)", 59462306a36Sopenharmony_ci err); 59562306a36Sopenharmony_ci return err; 59662306a36Sopenharmony_ci } 59762306a36Sopenharmony_ci } 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci if (test_bit(1, indio_dev->active_scan_mask)) { 60062306a36Sopenharmony_ci /* Get current temperature. */ 60162306a36Sopenharmony_ci err = regmap_bulk_read(private->regmap, ZPA2326_TEMP_OUT_L_REG, 60262306a36Sopenharmony_ci &sample.temperature, 2); 60362306a36Sopenharmony_ci if (err) { 60462306a36Sopenharmony_ci zpa2326_warn(indio_dev, 60562306a36Sopenharmony_ci "failed to fetch temperature (%d)", err); 60662306a36Sopenharmony_ci return err; 60762306a36Sopenharmony_ci } 60862306a36Sopenharmony_ci } 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci /* 61162306a36Sopenharmony_ci * Now push samples using timestamp stored either : 61262306a36Sopenharmony_ci * - by hardware interrupt handler if interrupt is available: see 61362306a36Sopenharmony_ci * zpa2326_handle_irq(), 61462306a36Sopenharmony_ci * - or oneshot completion polling machinery : see 61562306a36Sopenharmony_ci * zpa2326_trigger_handler(). 61662306a36Sopenharmony_ci */ 61762306a36Sopenharmony_ci zpa2326_dbg(indio_dev, "filling raw samples buffer"); 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci iio_push_to_buffers_with_timestamp(indio_dev, &sample, 62062306a36Sopenharmony_ci private->timestamp); 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci return 0; 62362306a36Sopenharmony_ci} 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci#ifdef CONFIG_PM 62662306a36Sopenharmony_cistatic int zpa2326_runtime_suspend(struct device *parent) 62762306a36Sopenharmony_ci{ 62862306a36Sopenharmony_ci const struct iio_dev *indio_dev = dev_get_drvdata(parent); 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci if (pm_runtime_autosuspend_expiration(parent)) 63162306a36Sopenharmony_ci /* Userspace changed autosuspend delay. */ 63262306a36Sopenharmony_ci return -EAGAIN; 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci zpa2326_power_off(indio_dev, iio_priv(indio_dev)); 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci return 0; 63762306a36Sopenharmony_ci} 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_cistatic int zpa2326_runtime_resume(struct device *parent) 64062306a36Sopenharmony_ci{ 64162306a36Sopenharmony_ci const struct iio_dev *indio_dev = dev_get_drvdata(parent); 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci return zpa2326_power_on(indio_dev, iio_priv(indio_dev)); 64462306a36Sopenharmony_ci} 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ciconst struct dev_pm_ops zpa2326_pm_ops = { 64762306a36Sopenharmony_ci SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 64862306a36Sopenharmony_ci pm_runtime_force_resume) 64962306a36Sopenharmony_ci SET_RUNTIME_PM_OPS(zpa2326_runtime_suspend, zpa2326_runtime_resume, 65062306a36Sopenharmony_ci NULL) 65162306a36Sopenharmony_ci}; 65262306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(zpa2326_pm_ops, IIO_ZPA2326); 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci/** 65562306a36Sopenharmony_ci * zpa2326_resume() - Request the PM layer to power supply the device. 65662306a36Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware. 65762306a36Sopenharmony_ci * 65862306a36Sopenharmony_ci * Return: 65962306a36Sopenharmony_ci * < 0 - a negative error code meaning failure ; 66062306a36Sopenharmony_ci * 0 - success, device has just been powered up ; 66162306a36Sopenharmony_ci * 1 - success, device was already powered. 66262306a36Sopenharmony_ci */ 66362306a36Sopenharmony_cistatic int zpa2326_resume(const struct iio_dev *indio_dev) 66462306a36Sopenharmony_ci{ 66562306a36Sopenharmony_ci int err; 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci err = pm_runtime_get_sync(indio_dev->dev.parent); 66862306a36Sopenharmony_ci if (err < 0) { 66962306a36Sopenharmony_ci pm_runtime_put(indio_dev->dev.parent); 67062306a36Sopenharmony_ci return err; 67162306a36Sopenharmony_ci } 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci if (err > 0) { 67462306a36Sopenharmony_ci /* 67562306a36Sopenharmony_ci * Device was already power supplied: get it out of low power 67662306a36Sopenharmony_ci * mode and inform caller. 67762306a36Sopenharmony_ci */ 67862306a36Sopenharmony_ci zpa2326_enable_device(indio_dev); 67962306a36Sopenharmony_ci return 1; 68062306a36Sopenharmony_ci } 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci /* Inform caller device has just been brought back to life. */ 68362306a36Sopenharmony_ci return 0; 68462306a36Sopenharmony_ci} 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci/** 68762306a36Sopenharmony_ci * zpa2326_suspend() - Schedule a power down using autosuspend feature of PM 68862306a36Sopenharmony_ci * layer. 68962306a36Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware. 69062306a36Sopenharmony_ci * 69162306a36Sopenharmony_ci * Device is switched to low power mode at first to save power even when 69262306a36Sopenharmony_ci * attached regulator is a "dummy" one. 69362306a36Sopenharmony_ci */ 69462306a36Sopenharmony_cistatic void zpa2326_suspend(struct iio_dev *indio_dev) 69562306a36Sopenharmony_ci{ 69662306a36Sopenharmony_ci struct device *parent = indio_dev->dev.parent; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci zpa2326_sleep(indio_dev); 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci pm_runtime_mark_last_busy(parent); 70162306a36Sopenharmony_ci pm_runtime_put_autosuspend(parent); 70262306a36Sopenharmony_ci} 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_cistatic void zpa2326_init_runtime(struct device *parent) 70562306a36Sopenharmony_ci{ 70662306a36Sopenharmony_ci pm_runtime_get_noresume(parent); 70762306a36Sopenharmony_ci pm_runtime_set_active(parent); 70862306a36Sopenharmony_ci pm_runtime_enable(parent); 70962306a36Sopenharmony_ci pm_runtime_set_autosuspend_delay(parent, 1000); 71062306a36Sopenharmony_ci pm_runtime_use_autosuspend(parent); 71162306a36Sopenharmony_ci pm_runtime_mark_last_busy(parent); 71262306a36Sopenharmony_ci pm_runtime_put_autosuspend(parent); 71362306a36Sopenharmony_ci} 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_cistatic void zpa2326_fini_runtime(struct device *parent) 71662306a36Sopenharmony_ci{ 71762306a36Sopenharmony_ci pm_runtime_disable(parent); 71862306a36Sopenharmony_ci pm_runtime_set_suspended(parent); 71962306a36Sopenharmony_ci} 72062306a36Sopenharmony_ci#else /* !CONFIG_PM */ 72162306a36Sopenharmony_cistatic int zpa2326_resume(const struct iio_dev *indio_dev) 72262306a36Sopenharmony_ci{ 72362306a36Sopenharmony_ci zpa2326_enable_device(indio_dev); 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci return 0; 72662306a36Sopenharmony_ci} 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_cistatic void zpa2326_suspend(struct iio_dev *indio_dev) 72962306a36Sopenharmony_ci{ 73062306a36Sopenharmony_ci zpa2326_sleep(indio_dev); 73162306a36Sopenharmony_ci} 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci#define zpa2326_init_runtime(_parent) 73462306a36Sopenharmony_ci#define zpa2326_fini_runtime(_parent) 73562306a36Sopenharmony_ci#endif /* !CONFIG_PM */ 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci/** 73862306a36Sopenharmony_ci * zpa2326_handle_irq() - Process hardware interrupts. 73962306a36Sopenharmony_ci * @irq: Interrupt line the hardware uses to notify new data has arrived. 74062306a36Sopenharmony_ci * @data: The IIO device associated with the sampling hardware. 74162306a36Sopenharmony_ci * 74262306a36Sopenharmony_ci * Timestamp buffered samples as soon as possible then schedule threaded bottom 74362306a36Sopenharmony_ci * half. 74462306a36Sopenharmony_ci * 74562306a36Sopenharmony_ci * Return: Always successful. 74662306a36Sopenharmony_ci */ 74762306a36Sopenharmony_cistatic irqreturn_t zpa2326_handle_irq(int irq, void *data) 74862306a36Sopenharmony_ci{ 74962306a36Sopenharmony_ci struct iio_dev *indio_dev = data; 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci if (iio_buffer_enabled(indio_dev)) { 75262306a36Sopenharmony_ci /* Timestamping needed for buffered sampling only. */ 75362306a36Sopenharmony_ci ((struct zpa2326_private *) 75462306a36Sopenharmony_ci iio_priv(indio_dev))->timestamp = iio_get_time_ns(indio_dev); 75562306a36Sopenharmony_ci } 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci return IRQ_WAKE_THREAD; 75862306a36Sopenharmony_ci} 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci/** 76162306a36Sopenharmony_ci * zpa2326_handle_threaded_irq() - Interrupt bottom-half handler. 76262306a36Sopenharmony_ci * @irq: Interrupt line the hardware uses to notify new data has arrived. 76362306a36Sopenharmony_ci * @data: The IIO device associated with the sampling hardware. 76462306a36Sopenharmony_ci * 76562306a36Sopenharmony_ci * Mainly ensures interrupt is caused by a real "new sample available" 76662306a36Sopenharmony_ci * condition. This relies upon the ability to perform blocking / sleeping bus 76762306a36Sopenharmony_ci * accesses to slave's registers. This is why zpa2326_handle_threaded_irq() is 76862306a36Sopenharmony_ci * called from within a thread, i.e. not called from hard interrupt context. 76962306a36Sopenharmony_ci * 77062306a36Sopenharmony_ci * When device is using its own internal hardware trigger in continuous sampling 77162306a36Sopenharmony_ci * mode, data are available into hardware FIFO once interrupt has occurred. All 77262306a36Sopenharmony_ci * we have to do is to dispatch the trigger, which in turn will fetch data and 77362306a36Sopenharmony_ci * fill IIO buffer. 77462306a36Sopenharmony_ci * 77562306a36Sopenharmony_ci * When not using its own internal hardware trigger, the device has been 77662306a36Sopenharmony_ci * configured in one-shot mode either by an external trigger or the IIO read_raw 77762306a36Sopenharmony_ci * hook. This means one of the latter is currently waiting for sampling 77862306a36Sopenharmony_ci * completion, in which case we must simply wake it up. 77962306a36Sopenharmony_ci * 78062306a36Sopenharmony_ci * See zpa2326_trigger_handler(). 78162306a36Sopenharmony_ci * 78262306a36Sopenharmony_ci * Return: 78362306a36Sopenharmony_ci * %IRQ_NONE - no consistent interrupt happened ; 78462306a36Sopenharmony_ci * %IRQ_HANDLED - there was new samples available. 78562306a36Sopenharmony_ci */ 78662306a36Sopenharmony_cistatic irqreturn_t zpa2326_handle_threaded_irq(int irq, void *data) 78762306a36Sopenharmony_ci{ 78862306a36Sopenharmony_ci struct iio_dev *indio_dev = data; 78962306a36Sopenharmony_ci struct zpa2326_private *priv = iio_priv(indio_dev); 79062306a36Sopenharmony_ci unsigned int val; 79162306a36Sopenharmony_ci bool cont; 79262306a36Sopenharmony_ci irqreturn_t ret = IRQ_NONE; 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci /* 79562306a36Sopenharmony_ci * Are we using our own internal trigger in triggered buffer mode, i.e., 79662306a36Sopenharmony_ci * currently working in continuous sampling mode ? 79762306a36Sopenharmony_ci */ 79862306a36Sopenharmony_ci cont = (iio_buffer_enabled(indio_dev) && 79962306a36Sopenharmony_ci iio_trigger_using_own(indio_dev)); 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci /* 80262306a36Sopenharmony_ci * Device works according to a level interrupt scheme: reading interrupt 80362306a36Sopenharmony_ci * status de-asserts interrupt line. 80462306a36Sopenharmony_ci */ 80562306a36Sopenharmony_ci priv->result = regmap_read(priv->regmap, ZPA2326_INT_SOURCE_REG, &val); 80662306a36Sopenharmony_ci if (priv->result < 0) { 80762306a36Sopenharmony_ci if (cont) 80862306a36Sopenharmony_ci return IRQ_NONE; 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci goto complete; 81162306a36Sopenharmony_ci } 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci /* Data ready is the only interrupt source we requested. */ 81462306a36Sopenharmony_ci if (!(val & ZPA2326_INT_SOURCE_DATA_READY)) { 81562306a36Sopenharmony_ci /* 81662306a36Sopenharmony_ci * Interrupt happened but no new sample available: likely caused 81762306a36Sopenharmony_ci * by spurious interrupts, in which case, returning IRQ_NONE 81862306a36Sopenharmony_ci * allows to benefit from the generic spurious interrupts 81962306a36Sopenharmony_ci * handling. 82062306a36Sopenharmony_ci */ 82162306a36Sopenharmony_ci zpa2326_warn(indio_dev, "unexpected interrupt status %02x", 82262306a36Sopenharmony_ci val); 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci if (cont) 82562306a36Sopenharmony_ci return IRQ_NONE; 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci priv->result = -ENODATA; 82862306a36Sopenharmony_ci goto complete; 82962306a36Sopenharmony_ci } 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci /* New sample available: dispatch internal trigger consumers. */ 83262306a36Sopenharmony_ci iio_trigger_poll_nested(priv->trigger); 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_ci if (cont) 83562306a36Sopenharmony_ci /* 83662306a36Sopenharmony_ci * Internal hardware trigger has been scheduled above : it will 83762306a36Sopenharmony_ci * fetch data on its own. 83862306a36Sopenharmony_ci */ 83962306a36Sopenharmony_ci return IRQ_HANDLED; 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci ret = IRQ_HANDLED; 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_cicomplete: 84462306a36Sopenharmony_ci /* 84562306a36Sopenharmony_ci * Wake up direct or externaly triggered buffer mode waiters: see 84662306a36Sopenharmony_ci * zpa2326_sample_oneshot() and zpa2326_trigger_handler(). 84762306a36Sopenharmony_ci */ 84862306a36Sopenharmony_ci complete(&priv->data_ready); 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci return ret; 85162306a36Sopenharmony_ci} 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci/** 85462306a36Sopenharmony_ci * zpa2326_wait_oneshot_completion() - Wait for oneshot data ready interrupt. 85562306a36Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware. 85662306a36Sopenharmony_ci * @private: Internal private state related to @indio_dev. 85762306a36Sopenharmony_ci * 85862306a36Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise. 85962306a36Sopenharmony_ci */ 86062306a36Sopenharmony_cistatic int zpa2326_wait_oneshot_completion(const struct iio_dev *indio_dev, 86162306a36Sopenharmony_ci struct zpa2326_private *private) 86262306a36Sopenharmony_ci{ 86362306a36Sopenharmony_ci unsigned int val; 86462306a36Sopenharmony_ci long timeout; 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci zpa2326_dbg(indio_dev, "waiting for one shot completion interrupt"); 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci timeout = wait_for_completion_interruptible_timeout( 86962306a36Sopenharmony_ci &private->data_ready, ZPA2326_CONVERSION_JIFFIES); 87062306a36Sopenharmony_ci if (timeout > 0) 87162306a36Sopenharmony_ci /* 87262306a36Sopenharmony_ci * Interrupt handler completed before timeout: return operation 87362306a36Sopenharmony_ci * status. 87462306a36Sopenharmony_ci */ 87562306a36Sopenharmony_ci return private->result; 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci /* Clear all interrupts just to be sure. */ 87862306a36Sopenharmony_ci regmap_read(private->regmap, ZPA2326_INT_SOURCE_REG, &val); 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci if (!timeout) { 88162306a36Sopenharmony_ci /* Timed out. */ 88262306a36Sopenharmony_ci zpa2326_warn(indio_dev, "no one shot interrupt occurred (%ld)", 88362306a36Sopenharmony_ci timeout); 88462306a36Sopenharmony_ci return -ETIME; 88562306a36Sopenharmony_ci } 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci zpa2326_warn(indio_dev, "wait for one shot interrupt cancelled"); 88862306a36Sopenharmony_ci return -ERESTARTSYS; 88962306a36Sopenharmony_ci} 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_cistatic int zpa2326_init_managed_irq(struct device *parent, 89262306a36Sopenharmony_ci struct iio_dev *indio_dev, 89362306a36Sopenharmony_ci struct zpa2326_private *private, 89462306a36Sopenharmony_ci int irq) 89562306a36Sopenharmony_ci{ 89662306a36Sopenharmony_ci int err; 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci private->irq = irq; 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci if (irq <= 0) { 90162306a36Sopenharmony_ci /* 90262306a36Sopenharmony_ci * Platform declared no interrupt line: device will be polled 90362306a36Sopenharmony_ci * for data availability. 90462306a36Sopenharmony_ci */ 90562306a36Sopenharmony_ci dev_info(parent, "no interrupt found, running in polling mode"); 90662306a36Sopenharmony_ci return 0; 90762306a36Sopenharmony_ci } 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci init_completion(&private->data_ready); 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci /* Request handler to be scheduled into threaded interrupt context. */ 91262306a36Sopenharmony_ci err = devm_request_threaded_irq(parent, irq, zpa2326_handle_irq, 91362306a36Sopenharmony_ci zpa2326_handle_threaded_irq, 91462306a36Sopenharmony_ci IRQF_TRIGGER_RISING | IRQF_ONESHOT, 91562306a36Sopenharmony_ci dev_name(parent), indio_dev); 91662306a36Sopenharmony_ci if (err) { 91762306a36Sopenharmony_ci dev_err(parent, "failed to request interrupt %d (%d)", irq, 91862306a36Sopenharmony_ci err); 91962306a36Sopenharmony_ci return err; 92062306a36Sopenharmony_ci } 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_ci dev_info(parent, "using interrupt %d", irq); 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_ci return 0; 92562306a36Sopenharmony_ci} 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci/** 92862306a36Sopenharmony_ci * zpa2326_poll_oneshot_completion() - Actively poll for one shot data ready. 92962306a36Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware. 93062306a36Sopenharmony_ci * 93162306a36Sopenharmony_ci * Loop over registers content to detect end of sampling cycle. Used when DT 93262306a36Sopenharmony_ci * declared no valid interrupt lines. 93362306a36Sopenharmony_ci * 93462306a36Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise. 93562306a36Sopenharmony_ci */ 93662306a36Sopenharmony_cistatic int zpa2326_poll_oneshot_completion(const struct iio_dev *indio_dev) 93762306a36Sopenharmony_ci{ 93862306a36Sopenharmony_ci unsigned long tmout = jiffies + ZPA2326_CONVERSION_JIFFIES; 93962306a36Sopenharmony_ci struct regmap *regs = ((struct zpa2326_private *) 94062306a36Sopenharmony_ci iio_priv(indio_dev))->regmap; 94162306a36Sopenharmony_ci unsigned int val; 94262306a36Sopenharmony_ci int err; 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci zpa2326_dbg(indio_dev, "polling for one shot completion"); 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci /* 94762306a36Sopenharmony_ci * At least, 100 ms is needed for the device to complete its one-shot 94862306a36Sopenharmony_ci * cycle. 94962306a36Sopenharmony_ci */ 95062306a36Sopenharmony_ci if (msleep_interruptible(100)) 95162306a36Sopenharmony_ci return -ERESTARTSYS; 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_ci /* Poll for conversion completion in hardware. */ 95462306a36Sopenharmony_ci while (true) { 95562306a36Sopenharmony_ci err = regmap_read(regs, ZPA2326_CTRL_REG0_REG, &val); 95662306a36Sopenharmony_ci if (err < 0) 95762306a36Sopenharmony_ci goto err; 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci if (!(val & ZPA2326_CTRL_REG0_ONE_SHOT)) 96062306a36Sopenharmony_ci /* One-shot bit self clears at conversion end. */ 96162306a36Sopenharmony_ci break; 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ci if (time_after(jiffies, tmout)) { 96462306a36Sopenharmony_ci /* Prevent from waiting forever : let's time out. */ 96562306a36Sopenharmony_ci err = -ETIME; 96662306a36Sopenharmony_ci goto err; 96762306a36Sopenharmony_ci } 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci usleep_range(10000, 20000); 97062306a36Sopenharmony_ci } 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_ci /* 97362306a36Sopenharmony_ci * In oneshot mode, pressure sample availability guarantees that 97462306a36Sopenharmony_ci * temperature conversion has also completed : just check pressure 97562306a36Sopenharmony_ci * status bit to keep things simple. 97662306a36Sopenharmony_ci */ 97762306a36Sopenharmony_ci err = regmap_read(regs, ZPA2326_STATUS_REG, &val); 97862306a36Sopenharmony_ci if (err < 0) 97962306a36Sopenharmony_ci goto err; 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci if (!(val & ZPA2326_STATUS_P_DA)) { 98262306a36Sopenharmony_ci /* No sample available. */ 98362306a36Sopenharmony_ci err = -ENODATA; 98462306a36Sopenharmony_ci goto err; 98562306a36Sopenharmony_ci } 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci return 0; 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_cierr: 99062306a36Sopenharmony_ci zpa2326_warn(indio_dev, "failed to poll one shot completion (%d)", err); 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci return err; 99362306a36Sopenharmony_ci} 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci/** 99662306a36Sopenharmony_ci * zpa2326_fetch_raw_sample() - Retrieve a raw sample and convert it to CPU 99762306a36Sopenharmony_ci * endianness. 99862306a36Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware. 99962306a36Sopenharmony_ci * @type: Type of measurement / channel to fetch from. 100062306a36Sopenharmony_ci * @value: Sample output. 100162306a36Sopenharmony_ci * 100262306a36Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise. 100362306a36Sopenharmony_ci */ 100462306a36Sopenharmony_cistatic int zpa2326_fetch_raw_sample(const struct iio_dev *indio_dev, 100562306a36Sopenharmony_ci enum iio_chan_type type, 100662306a36Sopenharmony_ci int *value) 100762306a36Sopenharmony_ci{ 100862306a36Sopenharmony_ci struct regmap *regs = ((struct zpa2326_private *) 100962306a36Sopenharmony_ci iio_priv(indio_dev))->regmap; 101062306a36Sopenharmony_ci int err; 101162306a36Sopenharmony_ci u8 v[3]; 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci switch (type) { 101462306a36Sopenharmony_ci case IIO_PRESSURE: 101562306a36Sopenharmony_ci zpa2326_dbg(indio_dev, "fetching raw pressure sample"); 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci err = regmap_bulk_read(regs, ZPA2326_PRESS_OUT_XL_REG, v, sizeof(v)); 101862306a36Sopenharmony_ci if (err) { 101962306a36Sopenharmony_ci zpa2326_warn(indio_dev, "failed to fetch pressure (%d)", 102062306a36Sopenharmony_ci err); 102162306a36Sopenharmony_ci return err; 102262306a36Sopenharmony_ci } 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci *value = get_unaligned_le24(&v[0]); 102562306a36Sopenharmony_ci 102662306a36Sopenharmony_ci return IIO_VAL_INT; 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci case IIO_TEMP: 102962306a36Sopenharmony_ci zpa2326_dbg(indio_dev, "fetching raw temperature sample"); 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_ci err = regmap_bulk_read(regs, ZPA2326_TEMP_OUT_L_REG, value, 2); 103262306a36Sopenharmony_ci if (err) { 103362306a36Sopenharmony_ci zpa2326_warn(indio_dev, 103462306a36Sopenharmony_ci "failed to fetch temperature (%d)", err); 103562306a36Sopenharmony_ci return err; 103662306a36Sopenharmony_ci } 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci /* Temperature is a 16 bits wide little-endian signed int. */ 103962306a36Sopenharmony_ci *value = (int)le16_to_cpup((__le16 *)value); 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_ci return IIO_VAL_INT; 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci default: 104462306a36Sopenharmony_ci return -EINVAL; 104562306a36Sopenharmony_ci } 104662306a36Sopenharmony_ci} 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ci/** 104962306a36Sopenharmony_ci * zpa2326_sample_oneshot() - Perform a complete one shot sampling cycle. 105062306a36Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware. 105162306a36Sopenharmony_ci * @type: Type of measurement / channel to fetch from. 105262306a36Sopenharmony_ci * @value: Sample output. 105362306a36Sopenharmony_ci * 105462306a36Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise. 105562306a36Sopenharmony_ci */ 105662306a36Sopenharmony_cistatic int zpa2326_sample_oneshot(struct iio_dev *indio_dev, 105762306a36Sopenharmony_ci enum iio_chan_type type, 105862306a36Sopenharmony_ci int *value) 105962306a36Sopenharmony_ci{ 106062306a36Sopenharmony_ci int ret; 106162306a36Sopenharmony_ci struct zpa2326_private *priv; 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci ret = iio_device_claim_direct_mode(indio_dev); 106462306a36Sopenharmony_ci if (ret) 106562306a36Sopenharmony_ci return ret; 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci ret = zpa2326_resume(indio_dev); 106862306a36Sopenharmony_ci if (ret < 0) 106962306a36Sopenharmony_ci goto release; 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci priv = iio_priv(indio_dev); 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_ci if (ret > 0) { 107462306a36Sopenharmony_ci /* 107562306a36Sopenharmony_ci * We were already power supplied. Just clear hardware FIFO to 107662306a36Sopenharmony_ci * get rid of samples acquired during previous rounds (if any). 107762306a36Sopenharmony_ci * Sampling operation always generates both temperature and 107862306a36Sopenharmony_ci * pressure samples. The latter are always enqueued into 107962306a36Sopenharmony_ci * hardware FIFO. This may lead to situations were pressure 108062306a36Sopenharmony_ci * samples still sit into FIFO when previous cycle(s) fetched 108162306a36Sopenharmony_ci * temperature data only. 108262306a36Sopenharmony_ci * Hence, we need to clear hardware FIFO content to prevent from 108362306a36Sopenharmony_ci * getting outdated values at the end of current cycle. 108462306a36Sopenharmony_ci */ 108562306a36Sopenharmony_ci if (type == IIO_PRESSURE) { 108662306a36Sopenharmony_ci ret = zpa2326_clear_fifo(indio_dev, 0); 108762306a36Sopenharmony_ci if (ret) 108862306a36Sopenharmony_ci goto suspend; 108962306a36Sopenharmony_ci } 109062306a36Sopenharmony_ci } else { 109162306a36Sopenharmony_ci /* 109262306a36Sopenharmony_ci * We have just been power supplied, i.e. device is in default 109362306a36Sopenharmony_ci * "out of reset" state, meaning we need to reconfigure it 109462306a36Sopenharmony_ci * entirely. 109562306a36Sopenharmony_ci */ 109662306a36Sopenharmony_ci ret = zpa2326_config_oneshot(indio_dev, priv->irq); 109762306a36Sopenharmony_ci if (ret) 109862306a36Sopenharmony_ci goto suspend; 109962306a36Sopenharmony_ci } 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ci /* Start a sampling cycle in oneshot mode. */ 110262306a36Sopenharmony_ci ret = zpa2326_start_oneshot(indio_dev); 110362306a36Sopenharmony_ci if (ret) 110462306a36Sopenharmony_ci goto suspend; 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_ci /* Wait for sampling cycle to complete. */ 110762306a36Sopenharmony_ci if (priv->irq > 0) 110862306a36Sopenharmony_ci ret = zpa2326_wait_oneshot_completion(indio_dev, priv); 110962306a36Sopenharmony_ci else 111062306a36Sopenharmony_ci ret = zpa2326_poll_oneshot_completion(indio_dev); 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_ci if (ret) 111362306a36Sopenharmony_ci goto suspend; 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_ci /* Retrieve raw sample value and convert it to CPU endianness. */ 111662306a36Sopenharmony_ci ret = zpa2326_fetch_raw_sample(indio_dev, type, value); 111762306a36Sopenharmony_ci 111862306a36Sopenharmony_cisuspend: 111962306a36Sopenharmony_ci zpa2326_suspend(indio_dev); 112062306a36Sopenharmony_cirelease: 112162306a36Sopenharmony_ci iio_device_release_direct_mode(indio_dev); 112262306a36Sopenharmony_ci 112362306a36Sopenharmony_ci return ret; 112462306a36Sopenharmony_ci} 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci/** 112762306a36Sopenharmony_ci * zpa2326_trigger_handler() - Perform an IIO buffered sampling round in one 112862306a36Sopenharmony_ci * shot mode. 112962306a36Sopenharmony_ci * @irq: The software interrupt assigned to @data 113062306a36Sopenharmony_ci * @data: The IIO poll function dispatched by external trigger our device is 113162306a36Sopenharmony_ci * attached to. 113262306a36Sopenharmony_ci * 113362306a36Sopenharmony_ci * Bottom-half handler called by the IIO trigger to which our device is 113462306a36Sopenharmony_ci * currently attached. Allows us to synchronize this device buffered sampling 113562306a36Sopenharmony_ci * either with external events (such as timer expiration, external device sample 113662306a36Sopenharmony_ci * ready, etc...) or with its own interrupt (internal hardware trigger). 113762306a36Sopenharmony_ci * 113862306a36Sopenharmony_ci * When using an external trigger, basically run the same sequence of operations 113962306a36Sopenharmony_ci * as for zpa2326_sample_oneshot() with the following hereafter. Hardware FIFO 114062306a36Sopenharmony_ci * is not cleared since already done at buffering enable time and samples 114162306a36Sopenharmony_ci * dequeueing always retrieves the most recent value. 114262306a36Sopenharmony_ci * 114362306a36Sopenharmony_ci * Otherwise, when internal hardware trigger has dispatched us, just fetch data 114462306a36Sopenharmony_ci * from hardware FIFO. 114562306a36Sopenharmony_ci * 114662306a36Sopenharmony_ci * Fetched data will pushed unprocessed to IIO buffer since samples conversion 114762306a36Sopenharmony_ci * is delegated to userspace in buffered mode (endianness, etc...). 114862306a36Sopenharmony_ci * 114962306a36Sopenharmony_ci * Return: 115062306a36Sopenharmony_ci * %IRQ_NONE - no consistent interrupt happened ; 115162306a36Sopenharmony_ci * %IRQ_HANDLED - there was new samples available. 115262306a36Sopenharmony_ci */ 115362306a36Sopenharmony_cistatic irqreturn_t zpa2326_trigger_handler(int irq, void *data) 115462306a36Sopenharmony_ci{ 115562306a36Sopenharmony_ci struct iio_dev *indio_dev = ((struct iio_poll_func *) 115662306a36Sopenharmony_ci data)->indio_dev; 115762306a36Sopenharmony_ci struct zpa2326_private *priv = iio_priv(indio_dev); 115862306a36Sopenharmony_ci bool cont; 115962306a36Sopenharmony_ci 116062306a36Sopenharmony_ci /* 116162306a36Sopenharmony_ci * We have been dispatched, meaning we are in triggered buffer mode. 116262306a36Sopenharmony_ci * Using our own internal trigger implies we are currently in continuous 116362306a36Sopenharmony_ci * hardware sampling mode. 116462306a36Sopenharmony_ci */ 116562306a36Sopenharmony_ci cont = iio_trigger_using_own(indio_dev); 116662306a36Sopenharmony_ci 116762306a36Sopenharmony_ci if (!cont) { 116862306a36Sopenharmony_ci /* On demand sampling : start a one shot cycle. */ 116962306a36Sopenharmony_ci if (zpa2326_start_oneshot(indio_dev)) 117062306a36Sopenharmony_ci goto out; 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_ci /* Wait for sampling cycle to complete. */ 117362306a36Sopenharmony_ci if (priv->irq <= 0) { 117462306a36Sopenharmony_ci /* No interrupt available: poll for completion. */ 117562306a36Sopenharmony_ci if (zpa2326_poll_oneshot_completion(indio_dev)) 117662306a36Sopenharmony_ci goto out; 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_ci /* Only timestamp sample once it is ready. */ 117962306a36Sopenharmony_ci priv->timestamp = iio_get_time_ns(indio_dev); 118062306a36Sopenharmony_ci } else { 118162306a36Sopenharmony_ci /* Interrupt handlers will timestamp for us. */ 118262306a36Sopenharmony_ci if (zpa2326_wait_oneshot_completion(indio_dev, priv)) 118362306a36Sopenharmony_ci goto out; 118462306a36Sopenharmony_ci } 118562306a36Sopenharmony_ci } 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci /* Enqueue to IIO buffer / userspace. */ 118862306a36Sopenharmony_ci zpa2326_fill_sample_buffer(indio_dev, priv); 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_ciout: 119162306a36Sopenharmony_ci if (!cont) 119262306a36Sopenharmony_ci /* Don't switch to low power if sampling continuously. */ 119362306a36Sopenharmony_ci zpa2326_sleep(indio_dev); 119462306a36Sopenharmony_ci 119562306a36Sopenharmony_ci /* Inform attached trigger we are done. */ 119662306a36Sopenharmony_ci iio_trigger_notify_done(indio_dev->trig); 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci return IRQ_HANDLED; 119962306a36Sopenharmony_ci} 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ci/** 120262306a36Sopenharmony_ci * zpa2326_preenable_buffer() - Prepare device for configuring triggered 120362306a36Sopenharmony_ci * sampling 120462306a36Sopenharmony_ci * modes. 120562306a36Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware. 120662306a36Sopenharmony_ci * 120762306a36Sopenharmony_ci * Basically power up device. 120862306a36Sopenharmony_ci * Called with IIO device's lock held. 120962306a36Sopenharmony_ci * 121062306a36Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise. 121162306a36Sopenharmony_ci */ 121262306a36Sopenharmony_cistatic int zpa2326_preenable_buffer(struct iio_dev *indio_dev) 121362306a36Sopenharmony_ci{ 121462306a36Sopenharmony_ci int ret = zpa2326_resume(indio_dev); 121562306a36Sopenharmony_ci 121662306a36Sopenharmony_ci if (ret < 0) 121762306a36Sopenharmony_ci return ret; 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ci /* Tell zpa2326_postenable_buffer() if we have just been powered on. */ 122062306a36Sopenharmony_ci ((struct zpa2326_private *) 122162306a36Sopenharmony_ci iio_priv(indio_dev))->waken = iio_priv(indio_dev); 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_ci return 0; 122462306a36Sopenharmony_ci} 122562306a36Sopenharmony_ci 122662306a36Sopenharmony_ci/** 122762306a36Sopenharmony_ci * zpa2326_postenable_buffer() - Configure device for triggered sampling. 122862306a36Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware. 122962306a36Sopenharmony_ci * 123062306a36Sopenharmony_ci * Basically setup one-shot mode if plugging external trigger. 123162306a36Sopenharmony_ci * Otherwise, let internal trigger configure continuous sampling : 123262306a36Sopenharmony_ci * see zpa2326_set_trigger_state(). 123362306a36Sopenharmony_ci * 123462306a36Sopenharmony_ci * If an error is returned, IIO layer will call our postdisable hook for us, 123562306a36Sopenharmony_ci * i.e. no need to explicitly power device off here. 123662306a36Sopenharmony_ci * Called with IIO device's lock held. 123762306a36Sopenharmony_ci * 123862306a36Sopenharmony_ci * Called with IIO device's lock held. 123962306a36Sopenharmony_ci * 124062306a36Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise. 124162306a36Sopenharmony_ci */ 124262306a36Sopenharmony_cistatic int zpa2326_postenable_buffer(struct iio_dev *indio_dev) 124362306a36Sopenharmony_ci{ 124462306a36Sopenharmony_ci const struct zpa2326_private *priv = iio_priv(indio_dev); 124562306a36Sopenharmony_ci int err; 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_ci if (!priv->waken) { 124862306a36Sopenharmony_ci /* 124962306a36Sopenharmony_ci * We were already power supplied. Just clear hardware FIFO to 125062306a36Sopenharmony_ci * get rid of samples acquired during previous rounds (if any). 125162306a36Sopenharmony_ci */ 125262306a36Sopenharmony_ci err = zpa2326_clear_fifo(indio_dev, 0); 125362306a36Sopenharmony_ci if (err) { 125462306a36Sopenharmony_ci zpa2326_err(indio_dev, 125562306a36Sopenharmony_ci "failed to enable buffering (%d)", err); 125662306a36Sopenharmony_ci return err; 125762306a36Sopenharmony_ci } 125862306a36Sopenharmony_ci } 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_ci if (!iio_trigger_using_own(indio_dev) && priv->waken) { 126162306a36Sopenharmony_ci /* 126262306a36Sopenharmony_ci * We are using an external trigger and we have just been 126362306a36Sopenharmony_ci * powered up: reconfigure one-shot mode. 126462306a36Sopenharmony_ci */ 126562306a36Sopenharmony_ci err = zpa2326_config_oneshot(indio_dev, priv->irq); 126662306a36Sopenharmony_ci if (err) { 126762306a36Sopenharmony_ci zpa2326_err(indio_dev, 126862306a36Sopenharmony_ci "failed to enable buffering (%d)", err); 126962306a36Sopenharmony_ci return err; 127062306a36Sopenharmony_ci } 127162306a36Sopenharmony_ci } 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_ci return 0; 127462306a36Sopenharmony_ci} 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_cistatic int zpa2326_postdisable_buffer(struct iio_dev *indio_dev) 127762306a36Sopenharmony_ci{ 127862306a36Sopenharmony_ci zpa2326_suspend(indio_dev); 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_ci return 0; 128162306a36Sopenharmony_ci} 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_cistatic const struct iio_buffer_setup_ops zpa2326_buffer_setup_ops = { 128462306a36Sopenharmony_ci .preenable = zpa2326_preenable_buffer, 128562306a36Sopenharmony_ci .postenable = zpa2326_postenable_buffer, 128662306a36Sopenharmony_ci .postdisable = zpa2326_postdisable_buffer 128762306a36Sopenharmony_ci}; 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_ci/** 129062306a36Sopenharmony_ci * zpa2326_set_trigger_state() - Start / stop continuous sampling. 129162306a36Sopenharmony_ci * @trig: The trigger being attached to IIO device associated with the sampling 129262306a36Sopenharmony_ci * hardware. 129362306a36Sopenharmony_ci * @state: Tell whether to start (true) or stop (false) 129462306a36Sopenharmony_ci * 129562306a36Sopenharmony_ci * Basically enable / disable hardware continuous sampling mode. 129662306a36Sopenharmony_ci * 129762306a36Sopenharmony_ci * Called with IIO device's lock held at postenable() or predisable() time. 129862306a36Sopenharmony_ci * 129962306a36Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise. 130062306a36Sopenharmony_ci */ 130162306a36Sopenharmony_cistatic int zpa2326_set_trigger_state(struct iio_trigger *trig, bool state) 130262306a36Sopenharmony_ci{ 130362306a36Sopenharmony_ci const struct iio_dev *indio_dev = dev_get_drvdata( 130462306a36Sopenharmony_ci trig->dev.parent); 130562306a36Sopenharmony_ci const struct zpa2326_private *priv = iio_priv(indio_dev); 130662306a36Sopenharmony_ci int err; 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci if (!state) { 130962306a36Sopenharmony_ci /* 131062306a36Sopenharmony_ci * Switch trigger off : in case of failure, interrupt is left 131162306a36Sopenharmony_ci * disabled in order to prevent handler from accessing released 131262306a36Sopenharmony_ci * resources. 131362306a36Sopenharmony_ci */ 131462306a36Sopenharmony_ci unsigned int val; 131562306a36Sopenharmony_ci 131662306a36Sopenharmony_ci /* 131762306a36Sopenharmony_ci * As device is working in continuous mode, handlers may be 131862306a36Sopenharmony_ci * accessing resources we are currently freeing... 131962306a36Sopenharmony_ci * Prevent this by disabling interrupt handlers and ensure 132062306a36Sopenharmony_ci * the device will generate no more interrupts unless explicitly 132162306a36Sopenharmony_ci * required to, i.e. by restoring back to default one shot mode. 132262306a36Sopenharmony_ci */ 132362306a36Sopenharmony_ci disable_irq(priv->irq); 132462306a36Sopenharmony_ci 132562306a36Sopenharmony_ci /* 132662306a36Sopenharmony_ci * Disable continuous sampling mode to restore settings for 132762306a36Sopenharmony_ci * one shot / direct sampling operations. 132862306a36Sopenharmony_ci */ 132962306a36Sopenharmony_ci err = regmap_write(priv->regmap, ZPA2326_CTRL_REG3_REG, 133062306a36Sopenharmony_ci zpa2326_highest_frequency()->odr); 133162306a36Sopenharmony_ci if (err) 133262306a36Sopenharmony_ci return err; 133362306a36Sopenharmony_ci 133462306a36Sopenharmony_ci /* 133562306a36Sopenharmony_ci * Now that device won't generate interrupts on its own, 133662306a36Sopenharmony_ci * acknowledge any currently active interrupts (may happen on 133762306a36Sopenharmony_ci * rare occasions while stopping continuous mode). 133862306a36Sopenharmony_ci */ 133962306a36Sopenharmony_ci err = regmap_read(priv->regmap, ZPA2326_INT_SOURCE_REG, &val); 134062306a36Sopenharmony_ci if (err < 0) 134162306a36Sopenharmony_ci return err; 134262306a36Sopenharmony_ci 134362306a36Sopenharmony_ci /* 134462306a36Sopenharmony_ci * Re-enable interrupts only if we can guarantee the device will 134562306a36Sopenharmony_ci * generate no more interrupts to prevent handlers from 134662306a36Sopenharmony_ci * accessing released resources. 134762306a36Sopenharmony_ci */ 134862306a36Sopenharmony_ci enable_irq(priv->irq); 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci zpa2326_dbg(indio_dev, "continuous mode stopped"); 135162306a36Sopenharmony_ci } else { 135262306a36Sopenharmony_ci /* 135362306a36Sopenharmony_ci * Switch trigger on : start continuous sampling at required 135462306a36Sopenharmony_ci * frequency. 135562306a36Sopenharmony_ci */ 135662306a36Sopenharmony_ci 135762306a36Sopenharmony_ci if (priv->waken) { 135862306a36Sopenharmony_ci /* Enable interrupt if getting out of reset. */ 135962306a36Sopenharmony_ci err = regmap_write(priv->regmap, ZPA2326_CTRL_REG1_REG, 136062306a36Sopenharmony_ci (u8) 136162306a36Sopenharmony_ci ~ZPA2326_CTRL_REG1_MASK_DATA_READY); 136262306a36Sopenharmony_ci if (err) 136362306a36Sopenharmony_ci return err; 136462306a36Sopenharmony_ci } 136562306a36Sopenharmony_ci 136662306a36Sopenharmony_ci /* Enable continuous sampling at specified frequency. */ 136762306a36Sopenharmony_ci err = regmap_write(priv->regmap, ZPA2326_CTRL_REG3_REG, 136862306a36Sopenharmony_ci ZPA2326_CTRL_REG3_ENABLE_MEAS | 136962306a36Sopenharmony_ci priv->frequency->odr); 137062306a36Sopenharmony_ci if (err) 137162306a36Sopenharmony_ci return err; 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_ci zpa2326_dbg(indio_dev, "continuous mode setup @%dHz", 137462306a36Sopenharmony_ci priv->frequency->hz); 137562306a36Sopenharmony_ci } 137662306a36Sopenharmony_ci 137762306a36Sopenharmony_ci return 0; 137862306a36Sopenharmony_ci} 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_cistatic const struct iio_trigger_ops zpa2326_trigger_ops = { 138162306a36Sopenharmony_ci .set_trigger_state = zpa2326_set_trigger_state, 138262306a36Sopenharmony_ci}; 138362306a36Sopenharmony_ci 138462306a36Sopenharmony_ci/** 138562306a36Sopenharmony_ci * zpa2326_init_managed_trigger() - Create interrupt driven / hardware trigger 138662306a36Sopenharmony_ci * allowing to notify external devices a new sample is 138762306a36Sopenharmony_ci * ready. 138862306a36Sopenharmony_ci * @parent: Hardware sampling device @indio_dev is a child of. 138962306a36Sopenharmony_ci * @indio_dev: The IIO device associated with the sampling hardware. 139062306a36Sopenharmony_ci * @private: Internal private state related to @indio_dev. 139162306a36Sopenharmony_ci * @irq: Optional interrupt line the hardware uses to notify new data 139262306a36Sopenharmony_ci * samples are ready. Negative or zero values indicate no interrupts 139362306a36Sopenharmony_ci * are available, meaning polling is required. 139462306a36Sopenharmony_ci * 139562306a36Sopenharmony_ci * Only relevant when DT declares a valid interrupt line. 139662306a36Sopenharmony_ci * 139762306a36Sopenharmony_ci * Return: Zero when successful, a negative error code otherwise. 139862306a36Sopenharmony_ci */ 139962306a36Sopenharmony_cistatic int zpa2326_init_managed_trigger(struct device *parent, 140062306a36Sopenharmony_ci struct iio_dev *indio_dev, 140162306a36Sopenharmony_ci struct zpa2326_private *private, 140262306a36Sopenharmony_ci int irq) 140362306a36Sopenharmony_ci{ 140462306a36Sopenharmony_ci struct iio_trigger *trigger; 140562306a36Sopenharmony_ci int ret; 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_ci if (irq <= 0) 140862306a36Sopenharmony_ci return 0; 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_ci trigger = devm_iio_trigger_alloc(parent, "%s-dev%d", 141162306a36Sopenharmony_ci indio_dev->name, 141262306a36Sopenharmony_ci iio_device_id(indio_dev)); 141362306a36Sopenharmony_ci if (!trigger) 141462306a36Sopenharmony_ci return -ENOMEM; 141562306a36Sopenharmony_ci 141662306a36Sopenharmony_ci /* Basic setup. */ 141762306a36Sopenharmony_ci trigger->ops = &zpa2326_trigger_ops; 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci private->trigger = trigger; 142062306a36Sopenharmony_ci 142162306a36Sopenharmony_ci /* Register to triggers space. */ 142262306a36Sopenharmony_ci ret = devm_iio_trigger_register(parent, trigger); 142362306a36Sopenharmony_ci if (ret) 142462306a36Sopenharmony_ci dev_err(parent, "failed to register hardware trigger (%d)", 142562306a36Sopenharmony_ci ret); 142662306a36Sopenharmony_ci 142762306a36Sopenharmony_ci return ret; 142862306a36Sopenharmony_ci} 142962306a36Sopenharmony_ci 143062306a36Sopenharmony_cistatic int zpa2326_get_frequency(const struct iio_dev *indio_dev) 143162306a36Sopenharmony_ci{ 143262306a36Sopenharmony_ci return ((struct zpa2326_private *)iio_priv(indio_dev))->frequency->hz; 143362306a36Sopenharmony_ci} 143462306a36Sopenharmony_ci 143562306a36Sopenharmony_cistatic int zpa2326_set_frequency(struct iio_dev *indio_dev, int hz) 143662306a36Sopenharmony_ci{ 143762306a36Sopenharmony_ci struct zpa2326_private *priv = iio_priv(indio_dev); 143862306a36Sopenharmony_ci int freq; 143962306a36Sopenharmony_ci int err; 144062306a36Sopenharmony_ci 144162306a36Sopenharmony_ci /* Check if requested frequency is supported. */ 144262306a36Sopenharmony_ci for (freq = 0; freq < ARRAY_SIZE(zpa2326_sampling_frequencies); freq++) 144362306a36Sopenharmony_ci if (zpa2326_sampling_frequencies[freq].hz == hz) 144462306a36Sopenharmony_ci break; 144562306a36Sopenharmony_ci if (freq == ARRAY_SIZE(zpa2326_sampling_frequencies)) 144662306a36Sopenharmony_ci return -EINVAL; 144762306a36Sopenharmony_ci 144862306a36Sopenharmony_ci /* Don't allow changing frequency if buffered sampling is ongoing. */ 144962306a36Sopenharmony_ci err = iio_device_claim_direct_mode(indio_dev); 145062306a36Sopenharmony_ci if (err) 145162306a36Sopenharmony_ci return err; 145262306a36Sopenharmony_ci 145362306a36Sopenharmony_ci priv->frequency = &zpa2326_sampling_frequencies[freq]; 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_ci iio_device_release_direct_mode(indio_dev); 145662306a36Sopenharmony_ci 145762306a36Sopenharmony_ci return 0; 145862306a36Sopenharmony_ci} 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_ci/* Expose supported hardware sampling frequencies (Hz) through sysfs. */ 146162306a36Sopenharmony_cistatic IIO_CONST_ATTR_SAMP_FREQ_AVAIL("1 5 11 23"); 146262306a36Sopenharmony_ci 146362306a36Sopenharmony_cistatic struct attribute *zpa2326_attributes[] = { 146462306a36Sopenharmony_ci &iio_const_attr_sampling_frequency_available.dev_attr.attr, 146562306a36Sopenharmony_ci NULL 146662306a36Sopenharmony_ci}; 146762306a36Sopenharmony_ci 146862306a36Sopenharmony_cistatic const struct attribute_group zpa2326_attribute_group = { 146962306a36Sopenharmony_ci .attrs = zpa2326_attributes, 147062306a36Sopenharmony_ci}; 147162306a36Sopenharmony_ci 147262306a36Sopenharmony_cistatic int zpa2326_read_raw(struct iio_dev *indio_dev, 147362306a36Sopenharmony_ci struct iio_chan_spec const *chan, 147462306a36Sopenharmony_ci int *val, 147562306a36Sopenharmony_ci int *val2, 147662306a36Sopenharmony_ci long mask) 147762306a36Sopenharmony_ci{ 147862306a36Sopenharmony_ci switch (mask) { 147962306a36Sopenharmony_ci case IIO_CHAN_INFO_RAW: 148062306a36Sopenharmony_ci return zpa2326_sample_oneshot(indio_dev, chan->type, val); 148162306a36Sopenharmony_ci 148262306a36Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 148362306a36Sopenharmony_ci switch (chan->type) { 148462306a36Sopenharmony_ci case IIO_PRESSURE: 148562306a36Sopenharmony_ci /* 148662306a36Sopenharmony_ci * Pressure resolution is 1/64 Pascal. Scale to kPascal 148762306a36Sopenharmony_ci * as required by IIO ABI. 148862306a36Sopenharmony_ci */ 148962306a36Sopenharmony_ci *val = 1; 149062306a36Sopenharmony_ci *val2 = 64000; 149162306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL; 149262306a36Sopenharmony_ci 149362306a36Sopenharmony_ci case IIO_TEMP: 149462306a36Sopenharmony_ci /* 149562306a36Sopenharmony_ci * Temperature follows the equation: 149662306a36Sopenharmony_ci * Temp[degC] = Tempcode * 0.00649 - 176.83 149762306a36Sopenharmony_ci * where: 149862306a36Sopenharmony_ci * Tempcode is composed the raw sampled 16 bits. 149962306a36Sopenharmony_ci * 150062306a36Sopenharmony_ci * Hence, to produce a temperature in milli-degrees 150162306a36Sopenharmony_ci * Celsius according to IIO ABI, we need to apply the 150262306a36Sopenharmony_ci * following equation to raw samples: 150362306a36Sopenharmony_ci * Temp[milli degC] = (Tempcode + Offset) * Scale 150462306a36Sopenharmony_ci * where: 150562306a36Sopenharmony_ci * Offset = -176.83 / 0.00649 150662306a36Sopenharmony_ci * Scale = 0.00649 * 1000 150762306a36Sopenharmony_ci */ 150862306a36Sopenharmony_ci *val = 6; 150962306a36Sopenharmony_ci *val2 = 490000; 151062306a36Sopenharmony_ci return IIO_VAL_INT_PLUS_MICRO; 151162306a36Sopenharmony_ci 151262306a36Sopenharmony_ci default: 151362306a36Sopenharmony_ci return -EINVAL; 151462306a36Sopenharmony_ci } 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ci case IIO_CHAN_INFO_OFFSET: 151762306a36Sopenharmony_ci switch (chan->type) { 151862306a36Sopenharmony_ci case IIO_TEMP: 151962306a36Sopenharmony_ci *val = -17683000; 152062306a36Sopenharmony_ci *val2 = 649; 152162306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL; 152262306a36Sopenharmony_ci 152362306a36Sopenharmony_ci default: 152462306a36Sopenharmony_ci return -EINVAL; 152562306a36Sopenharmony_ci } 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_ci case IIO_CHAN_INFO_SAMP_FREQ: 152862306a36Sopenharmony_ci *val = zpa2326_get_frequency(indio_dev); 152962306a36Sopenharmony_ci return IIO_VAL_INT; 153062306a36Sopenharmony_ci 153162306a36Sopenharmony_ci default: 153262306a36Sopenharmony_ci return -EINVAL; 153362306a36Sopenharmony_ci } 153462306a36Sopenharmony_ci} 153562306a36Sopenharmony_ci 153662306a36Sopenharmony_cistatic int zpa2326_write_raw(struct iio_dev *indio_dev, 153762306a36Sopenharmony_ci const struct iio_chan_spec *chan, 153862306a36Sopenharmony_ci int val, 153962306a36Sopenharmony_ci int val2, 154062306a36Sopenharmony_ci long mask) 154162306a36Sopenharmony_ci{ 154262306a36Sopenharmony_ci if ((mask != IIO_CHAN_INFO_SAMP_FREQ) || val2) 154362306a36Sopenharmony_ci return -EINVAL; 154462306a36Sopenharmony_ci 154562306a36Sopenharmony_ci return zpa2326_set_frequency(indio_dev, val); 154662306a36Sopenharmony_ci} 154762306a36Sopenharmony_ci 154862306a36Sopenharmony_cistatic const struct iio_chan_spec zpa2326_channels[] = { 154962306a36Sopenharmony_ci [0] = { 155062306a36Sopenharmony_ci .type = IIO_PRESSURE, 155162306a36Sopenharmony_ci .scan_index = 0, 155262306a36Sopenharmony_ci .scan_type = { 155362306a36Sopenharmony_ci .sign = 'u', 155462306a36Sopenharmony_ci .realbits = 24, 155562306a36Sopenharmony_ci .storagebits = 32, 155662306a36Sopenharmony_ci .endianness = IIO_LE, 155762306a36Sopenharmony_ci }, 155862306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 155962306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE), 156062306a36Sopenharmony_ci .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), 156162306a36Sopenharmony_ci }, 156262306a36Sopenharmony_ci [1] = { 156362306a36Sopenharmony_ci .type = IIO_TEMP, 156462306a36Sopenharmony_ci .scan_index = 1, 156562306a36Sopenharmony_ci .scan_type = { 156662306a36Sopenharmony_ci .sign = 's', 156762306a36Sopenharmony_ci .realbits = 16, 156862306a36Sopenharmony_ci .storagebits = 16, 156962306a36Sopenharmony_ci .endianness = IIO_LE, 157062306a36Sopenharmony_ci }, 157162306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 157262306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE) | 157362306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_OFFSET), 157462306a36Sopenharmony_ci .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), 157562306a36Sopenharmony_ci }, 157662306a36Sopenharmony_ci [2] = IIO_CHAN_SOFT_TIMESTAMP(2), 157762306a36Sopenharmony_ci}; 157862306a36Sopenharmony_ci 157962306a36Sopenharmony_cistatic const struct iio_info zpa2326_info = { 158062306a36Sopenharmony_ci .attrs = &zpa2326_attribute_group, 158162306a36Sopenharmony_ci .read_raw = zpa2326_read_raw, 158262306a36Sopenharmony_ci .write_raw = zpa2326_write_raw, 158362306a36Sopenharmony_ci}; 158462306a36Sopenharmony_ci 158562306a36Sopenharmony_cistatic struct iio_dev *zpa2326_create_managed_iiodev(struct device *device, 158662306a36Sopenharmony_ci const char *name, 158762306a36Sopenharmony_ci struct regmap *regmap) 158862306a36Sopenharmony_ci{ 158962306a36Sopenharmony_ci struct iio_dev *indio_dev; 159062306a36Sopenharmony_ci 159162306a36Sopenharmony_ci /* Allocate space to hold IIO device internal state. */ 159262306a36Sopenharmony_ci indio_dev = devm_iio_device_alloc(device, 159362306a36Sopenharmony_ci sizeof(struct zpa2326_private)); 159462306a36Sopenharmony_ci if (!indio_dev) 159562306a36Sopenharmony_ci return NULL; 159662306a36Sopenharmony_ci 159762306a36Sopenharmony_ci /* Setup for userspace synchronous on demand sampling. */ 159862306a36Sopenharmony_ci indio_dev->modes = INDIO_DIRECT_MODE; 159962306a36Sopenharmony_ci indio_dev->channels = zpa2326_channels; 160062306a36Sopenharmony_ci indio_dev->num_channels = ARRAY_SIZE(zpa2326_channels); 160162306a36Sopenharmony_ci indio_dev->name = name; 160262306a36Sopenharmony_ci indio_dev->info = &zpa2326_info; 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_ci return indio_dev; 160562306a36Sopenharmony_ci} 160662306a36Sopenharmony_ci 160762306a36Sopenharmony_ciint zpa2326_probe(struct device *parent, 160862306a36Sopenharmony_ci const char *name, 160962306a36Sopenharmony_ci int irq, 161062306a36Sopenharmony_ci unsigned int hwid, 161162306a36Sopenharmony_ci struct regmap *regmap) 161262306a36Sopenharmony_ci{ 161362306a36Sopenharmony_ci struct iio_dev *indio_dev; 161462306a36Sopenharmony_ci struct zpa2326_private *priv; 161562306a36Sopenharmony_ci int err; 161662306a36Sopenharmony_ci unsigned int id; 161762306a36Sopenharmony_ci 161862306a36Sopenharmony_ci indio_dev = zpa2326_create_managed_iiodev(parent, name, regmap); 161962306a36Sopenharmony_ci if (!indio_dev) 162062306a36Sopenharmony_ci return -ENOMEM; 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_ci priv = iio_priv(indio_dev); 162362306a36Sopenharmony_ci 162462306a36Sopenharmony_ci priv->vref = devm_regulator_get(parent, "vref"); 162562306a36Sopenharmony_ci if (IS_ERR(priv->vref)) 162662306a36Sopenharmony_ci return PTR_ERR(priv->vref); 162762306a36Sopenharmony_ci 162862306a36Sopenharmony_ci priv->vdd = devm_regulator_get(parent, "vdd"); 162962306a36Sopenharmony_ci if (IS_ERR(priv->vdd)) 163062306a36Sopenharmony_ci return PTR_ERR(priv->vdd); 163162306a36Sopenharmony_ci 163262306a36Sopenharmony_ci /* Set default hardware sampling frequency to highest rate supported. */ 163362306a36Sopenharmony_ci priv->frequency = zpa2326_highest_frequency(); 163462306a36Sopenharmony_ci 163562306a36Sopenharmony_ci /* 163662306a36Sopenharmony_ci * Plug device's underlying bus abstraction : this MUST be set before 163762306a36Sopenharmony_ci * registering interrupt handlers since an interrupt might happen if 163862306a36Sopenharmony_ci * power up sequence is not properly applied. 163962306a36Sopenharmony_ci */ 164062306a36Sopenharmony_ci priv->regmap = regmap; 164162306a36Sopenharmony_ci 164262306a36Sopenharmony_ci err = devm_iio_triggered_buffer_setup(parent, indio_dev, NULL, 164362306a36Sopenharmony_ci zpa2326_trigger_handler, 164462306a36Sopenharmony_ci &zpa2326_buffer_setup_ops); 164562306a36Sopenharmony_ci if (err) 164662306a36Sopenharmony_ci return err; 164762306a36Sopenharmony_ci 164862306a36Sopenharmony_ci err = zpa2326_init_managed_trigger(parent, indio_dev, priv, irq); 164962306a36Sopenharmony_ci if (err) 165062306a36Sopenharmony_ci return err; 165162306a36Sopenharmony_ci 165262306a36Sopenharmony_ci err = zpa2326_init_managed_irq(parent, indio_dev, priv, irq); 165362306a36Sopenharmony_ci if (err) 165462306a36Sopenharmony_ci return err; 165562306a36Sopenharmony_ci 165662306a36Sopenharmony_ci /* Power up to check device ID and perform initial hardware setup. */ 165762306a36Sopenharmony_ci err = zpa2326_power_on(indio_dev, priv); 165862306a36Sopenharmony_ci if (err) 165962306a36Sopenharmony_ci return err; 166062306a36Sopenharmony_ci 166162306a36Sopenharmony_ci /* Read id register to check we are talking to the right slave. */ 166262306a36Sopenharmony_ci err = regmap_read(regmap, ZPA2326_DEVICE_ID_REG, &id); 166362306a36Sopenharmony_ci if (err) 166462306a36Sopenharmony_ci goto sleep; 166562306a36Sopenharmony_ci 166662306a36Sopenharmony_ci if (id != hwid) { 166762306a36Sopenharmony_ci dev_err(parent, "found device with unexpected id %02x", id); 166862306a36Sopenharmony_ci err = -ENODEV; 166962306a36Sopenharmony_ci goto sleep; 167062306a36Sopenharmony_ci } 167162306a36Sopenharmony_ci 167262306a36Sopenharmony_ci err = zpa2326_config_oneshot(indio_dev, irq); 167362306a36Sopenharmony_ci if (err) 167462306a36Sopenharmony_ci goto sleep; 167562306a36Sopenharmony_ci 167662306a36Sopenharmony_ci /* Setup done : go sleeping. Device will be awaken upon user request. */ 167762306a36Sopenharmony_ci err = zpa2326_sleep(indio_dev); 167862306a36Sopenharmony_ci if (err) 167962306a36Sopenharmony_ci goto poweroff; 168062306a36Sopenharmony_ci 168162306a36Sopenharmony_ci dev_set_drvdata(parent, indio_dev); 168262306a36Sopenharmony_ci 168362306a36Sopenharmony_ci zpa2326_init_runtime(parent); 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_ci err = iio_device_register(indio_dev); 168662306a36Sopenharmony_ci if (err) { 168762306a36Sopenharmony_ci zpa2326_fini_runtime(parent); 168862306a36Sopenharmony_ci goto poweroff; 168962306a36Sopenharmony_ci } 169062306a36Sopenharmony_ci 169162306a36Sopenharmony_ci return 0; 169262306a36Sopenharmony_ci 169362306a36Sopenharmony_cisleep: 169462306a36Sopenharmony_ci /* Put to sleep just in case power regulators are "dummy" ones. */ 169562306a36Sopenharmony_ci zpa2326_sleep(indio_dev); 169662306a36Sopenharmony_cipoweroff: 169762306a36Sopenharmony_ci zpa2326_power_off(indio_dev, priv); 169862306a36Sopenharmony_ci 169962306a36Sopenharmony_ci return err; 170062306a36Sopenharmony_ci} 170162306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(zpa2326_probe, IIO_ZPA2326); 170262306a36Sopenharmony_ci 170362306a36Sopenharmony_civoid zpa2326_remove(const struct device *parent) 170462306a36Sopenharmony_ci{ 170562306a36Sopenharmony_ci struct iio_dev *indio_dev = dev_get_drvdata(parent); 170662306a36Sopenharmony_ci 170762306a36Sopenharmony_ci iio_device_unregister(indio_dev); 170862306a36Sopenharmony_ci zpa2326_fini_runtime(indio_dev->dev.parent); 170962306a36Sopenharmony_ci zpa2326_sleep(indio_dev); 171062306a36Sopenharmony_ci zpa2326_power_off(indio_dev, iio_priv(indio_dev)); 171162306a36Sopenharmony_ci} 171262306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(zpa2326_remove, IIO_ZPA2326); 171362306a36Sopenharmony_ci 171462306a36Sopenharmony_ciMODULE_AUTHOR("Gregor Boirie <gregor.boirie@parrot.com>"); 171562306a36Sopenharmony_ciMODULE_DESCRIPTION("Core driver for Murata ZPA2326 pressure sensor"); 171662306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 1717