2019-05-27 09:55:21 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2016-09-13 15:23:14 +03:00
/*
* Murata ZPA2326 pressure and temperature sensor IIO driver
*
* Copyright ( c ) 2016 Parrot S . A .
*
* Author : Gregor Boirie < gregor . boirie @ parrot . com >
*/
/**
* DOC : ZPA2326 theory of operations
*
* This driver supports % INDIO_DIRECT_MODE and % INDIO_BUFFER_TRIGGERED IIO
* modes .
* A internal hardware trigger is also implemented to dispatch registered IIO
* trigger consumers upon " sample ready " interrupts .
*
* ZPA2326 hardware supports 2 sampling mode : one shot and continuous .
*
* A complete one shot sampling cycle gets device out of low power mode ,
* performs pressure and temperature measurements , then automatically switches
* back to low power mode . It is meant for on demand sampling with optimal power
* saving at the cost of lower sampling rate and higher software overhead .
* This is a natural candidate for IIO read_raw hook implementation
* ( % INDIO_DIRECT_MODE ) . It is also used for triggered buffering support to
* ensure explicit synchronization with external trigger events
* ( % INDIO_BUFFER_TRIGGERED ) .
*
* The continuous mode works according to a periodic hardware measurement
* process continuously pushing samples into an internal hardware FIFO ( for
* pressure samples only ) . Measurement cycle completion may be signaled by a
* " sample ready " interrupt .
* Typical software sequence of operations :
* - get device out of low power mode ,
* - setup hardware sampling period ,
* - at end of period , upon data ready interrupt : pop pressure samples out of
* hardware FIFO and fetch temperature sample
* - when no longer needed , stop sampling process by putting device into
* low power mode .
* This mode is used to implement % INDIO_BUFFER_TRIGGERED mode if device tree
* declares a valid interrupt line . In this case , the internal hardware trigger
* drives acquisition .
*
* Note that hardware sampling frequency is taken into account only when
* internal hardware trigger is attached as the highest sampling rate seems to
* be the most energy efficient .
*
* TODO :
* preset pressure threshold crossing / IIO events ;
* differential pressure sampling ;
* hardware samples averaging .
*/
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/delay.h>
# include <linux/interrupt.h>
# include <linux/regulator/consumer.h>
# include <linux/pm_runtime.h>
# include <linux/regmap.h>
# include <linux/iio/iio.h>
# include <linux/iio/sysfs.h>
# include <linux/iio/buffer.h>
# include <linux/iio/trigger.h>
# include <linux/iio/trigger_consumer.h>
# include <linux/iio/triggered_buffer.h>
2020-04-21 03:31:33 +03:00
# include <asm/unaligned.h>
2016-09-13 15:23:14 +03:00
# include "zpa2326.h"
/* 200 ms should be enough for the longest conversion time in one-shot mode. */
# define ZPA2326_CONVERSION_JIFFIES (HZ / 5)
/* There should be a 1 ms delay (Tpup) after getting out of reset. */
# define ZPA2326_TPUP_USEC_MIN (1000)
# define ZPA2326_TPUP_USEC_MAX (2000)
/**
* struct zpa2326_frequency - Hardware sampling frequency descriptor
* @ hz : Frequency in Hertz .
* @ odr : Output Data Rate word as expected by % ZPA2326_CTRL_REG3_REG .
*/
struct zpa2326_frequency {
int hz ;
u16 odr ;
} ;
/*
* Keep these in strict ascending order : last array entry is expected to
* correspond to the highest sampling frequency .
*/
static const struct zpa2326_frequency zpa2326_sampling_frequencies [ ] = {
{ . hz = 1 , . odr = 1 < < ZPA2326_CTRL_REG3_ODR_SHIFT } ,
{ . hz = 5 , . odr = 5 < < ZPA2326_CTRL_REG3_ODR_SHIFT } ,
{ . hz = 11 , . odr = 6 < < ZPA2326_CTRL_REG3_ODR_SHIFT } ,
{ . hz = 23 , . odr = 7 < < ZPA2326_CTRL_REG3_ODR_SHIFT } ,
} ;
/* Return the highest hardware sampling frequency available. */
static const struct zpa2326_frequency * zpa2326_highest_frequency ( void )
{
return & zpa2326_sampling_frequencies [
ARRAY_SIZE ( zpa2326_sampling_frequencies ) - 1 ] ;
}
/**
2021-03-14 19:46:48 +03:00
* struct zpa2326_private - Per - device internal private state
2016-09-13 15:23:14 +03:00
* @ timestamp : Buffered samples ready datum .
* @ regmap : Underlying I2C / SPI bus adapter used to abstract slave register
* accesses .
* @ result : Allows sampling logic to get completion status of operations
* that interrupt handlers perform asynchronously .
* @ data_ready : Interrupt handler uses this to wake user context up at sampling
* operation completion .
* @ trigger : Optional hardware / interrupt driven trigger used to notify
* external devices a new sample is ready .
* @ waken : Flag indicating whether or not device has just been powered on .
* @ irq : Optional interrupt line : negative or zero if not declared into
* DT , in which case sampling logic keeps polling status register
* to detect completion .
* @ frequency : Current hardware sampling frequency .
* @ vref : Power / voltage reference .
* @ vdd : Power supply .
*/
struct zpa2326_private {
s64 timestamp ;
struct regmap * regmap ;
int result ;
struct completion data_ready ;
struct iio_trigger * trigger ;
bool waken ;
int irq ;
const struct zpa2326_frequency * frequency ;
struct regulator * vref ;
struct regulator * vdd ;
} ;
2017-07-05 13:25:58 +03:00
# define zpa2326_err(idev, fmt, ...) \
dev_err ( idev - > dev . parent , fmt " \n " , # # __VA_ARGS__ )
2016-09-13 15:23:14 +03:00
2017-07-05 13:25:58 +03:00
# define zpa2326_warn(idev, fmt, ...) \
dev_warn ( idev - > dev . parent , fmt " \n " , # # __VA_ARGS__ )
2016-09-13 15:23:14 +03:00
2017-07-05 13:25:58 +03:00
# define zpa2326_dbg(idev, fmt, ...) \
dev_dbg ( idev - > dev . parent , fmt " \n " , # # __VA_ARGS__ )
2016-09-13 15:23:14 +03:00
bool zpa2326_isreg_writeable ( struct device * dev , unsigned int reg )
{
switch ( reg ) {
case ZPA2326_REF_P_XL_REG :
case ZPA2326_REF_P_L_REG :
case ZPA2326_REF_P_H_REG :
case ZPA2326_RES_CONF_REG :
case ZPA2326_CTRL_REG0_REG :
case ZPA2326_CTRL_REG1_REG :
case ZPA2326_CTRL_REG2_REG :
case ZPA2326_CTRL_REG3_REG :
case ZPA2326_THS_P_LOW_REG :
case ZPA2326_THS_P_HIGH_REG :
return true ;
default :
return false ;
}
}
2022-01-30 23:56:54 +03:00
EXPORT_SYMBOL_NS_GPL ( zpa2326_isreg_writeable , IIO_ZPA2326 ) ;
2016-09-13 15:23:14 +03:00
bool zpa2326_isreg_readable ( struct device * dev , unsigned int reg )
{
switch ( reg ) {
case ZPA2326_REF_P_XL_REG :
case ZPA2326_REF_P_L_REG :
case ZPA2326_REF_P_H_REG :
case ZPA2326_DEVICE_ID_REG :
case ZPA2326_RES_CONF_REG :
case ZPA2326_CTRL_REG0_REG :
case ZPA2326_CTRL_REG1_REG :
case ZPA2326_CTRL_REG2_REG :
case ZPA2326_CTRL_REG3_REG :
case ZPA2326_INT_SOURCE_REG :
case ZPA2326_THS_P_LOW_REG :
case ZPA2326_THS_P_HIGH_REG :
case ZPA2326_STATUS_REG :
case ZPA2326_PRESS_OUT_XL_REG :
case ZPA2326_PRESS_OUT_L_REG :
case ZPA2326_PRESS_OUT_H_REG :
case ZPA2326_TEMP_OUT_L_REG :
case ZPA2326_TEMP_OUT_H_REG :
return true ;
default :
return false ;
}
}
2022-01-30 23:56:54 +03:00
EXPORT_SYMBOL_NS_GPL ( zpa2326_isreg_readable , IIO_ZPA2326 ) ;
2016-09-13 15:23:14 +03:00
bool zpa2326_isreg_precious ( struct device * dev , unsigned int reg )
{
switch ( reg ) {
case ZPA2326_INT_SOURCE_REG :
case ZPA2326_PRESS_OUT_H_REG :
return true ;
default :
return false ;
}
}
2022-01-30 23:56:54 +03:00
EXPORT_SYMBOL_NS_GPL ( zpa2326_isreg_precious , IIO_ZPA2326 ) ;
2016-09-13 15:23:14 +03:00
/**
* zpa2326_enable_device ( ) - Enable device , i . e . get out of low power mode .
* @ indio_dev : The IIO device associated with the hardware to enable .
*
* Required to access complete register space and to perform any sampling
* or control operations .
*
* Return : Zero when successful , a negative error code otherwise .
*/
static int zpa2326_enable_device ( const struct iio_dev * indio_dev )
{
int err ;
err = regmap_write ( ( ( struct zpa2326_private * )
iio_priv ( indio_dev ) ) - > regmap ,
ZPA2326_CTRL_REG0_REG , ZPA2326_CTRL_REG0_ENABLE ) ;
if ( err ) {
zpa2326_err ( indio_dev , " failed to enable device (%d) " , err ) ;
return err ;
}
zpa2326_dbg ( indio_dev , " enabled " ) ;
return 0 ;
}
/**
* zpa2326_sleep ( ) - Disable device , i . e . switch to low power mode .
* @ indio_dev : The IIO device associated with the hardware to disable .
*
* Only % ZPA2326_DEVICE_ID_REG and % ZPA2326_CTRL_REG0_REG registers may be
* accessed once device is in the disabled state .
*
* Return : Zero when successful , a negative error code otherwise .
*/
static int zpa2326_sleep ( const struct iio_dev * indio_dev )
{
int err ;
err = regmap_write ( ( ( struct zpa2326_private * )
iio_priv ( indio_dev ) ) - > regmap ,
ZPA2326_CTRL_REG0_REG , 0 ) ;
if ( err ) {
zpa2326_err ( indio_dev , " failed to sleep (%d) " , err ) ;
return err ;
}
zpa2326_dbg ( indio_dev , " sleeping " ) ;
return 0 ;
}
/**
* zpa2326_reset_device ( ) - Reset device to default hardware state .
* @ indio_dev : The IIO device associated with the hardware to reset .
*
* Disable sampling and empty hardware FIFO .
* Device must be enabled before reset , i . e . not in low power mode .
*
* Return : Zero when successful , a negative error code otherwise .
*/
static int zpa2326_reset_device ( const struct iio_dev * indio_dev )
{
int err ;
err = regmap_write ( ( ( struct zpa2326_private * )
iio_priv ( indio_dev ) ) - > regmap ,
ZPA2326_CTRL_REG2_REG , ZPA2326_CTRL_REG2_SWRESET ) ;
if ( err ) {
zpa2326_err ( indio_dev , " failed to reset device (%d) " , err ) ;
return err ;
}
usleep_range ( ZPA2326_TPUP_USEC_MIN , ZPA2326_TPUP_USEC_MAX ) ;
zpa2326_dbg ( indio_dev , " reset " ) ;
return 0 ;
}
/**
* zpa2326_start_oneshot ( ) - Start a single sampling cycle , i . e . in one shot
* mode .
* @ indio_dev : The IIO device associated with the sampling hardware .
*
* Device must have been previously enabled and configured for one shot mode .
* Device will be switched back to low power mode at end of cycle .
*
* Return : Zero when successful , a negative error code otherwise .
*/
static int zpa2326_start_oneshot ( const struct iio_dev * indio_dev )
{
int err ;
err = regmap_write ( ( ( struct zpa2326_private * )
iio_priv ( indio_dev ) ) - > regmap ,
ZPA2326_CTRL_REG0_REG ,
ZPA2326_CTRL_REG0_ENABLE |
ZPA2326_CTRL_REG0_ONE_SHOT ) ;
if ( err ) {
zpa2326_err ( indio_dev , " failed to start one shot cycle (%d) " ,
err ) ;
return err ;
}
zpa2326_dbg ( indio_dev , " one shot cycle started " ) ;
return 0 ;
}
/**
* zpa2326_power_on ( ) - Power on device to allow subsequent configuration .
* @ indio_dev : The IIO device associated with the sampling hardware .
* @ private : Internal private state related to @ indio_dev .
*
* Sampling will be disabled , preventing strange things from happening in our
* back . Hardware FIFO content will be cleared .
* When successful , device will be left in the enabled state to allow further
* configuration .
*
* Return : Zero when successful , a negative error code otherwise .
*/
static int zpa2326_power_on ( const struct iio_dev * indio_dev ,
const struct zpa2326_private * private )
{
int err ;
err = regulator_enable ( private - > vref ) ;
if ( err )
return err ;
err = regulator_enable ( private - > vdd ) ;
if ( err )
goto vref ;
zpa2326_dbg ( indio_dev , " powered on " ) ;
err = zpa2326_enable_device ( indio_dev ) ;
if ( err )
goto vdd ;
err = zpa2326_reset_device ( indio_dev ) ;
if ( err )
goto sleep ;
return 0 ;
sleep :
zpa2326_sleep ( indio_dev ) ;
vdd :
regulator_disable ( private - > vdd ) ;
vref :
regulator_disable ( private - > vref ) ;
zpa2326_dbg ( indio_dev , " powered off " ) ;
return err ;
}
/**
* zpa2326_power_off ( ) - Power off device , i . e . disable attached power
* regulators .
* @ indio_dev : The IIO device associated with the sampling hardware .
* @ private : Internal private state related to @ indio_dev .
*
* Return : Zero when successful , a negative error code otherwise .
*/
static void zpa2326_power_off ( const struct iio_dev * indio_dev ,
const struct zpa2326_private * private )
{
regulator_disable ( private - > vdd ) ;
regulator_disable ( private - > vref ) ;
zpa2326_dbg ( indio_dev , " powered off " ) ;
}
/**
* zpa2326_config_oneshot ( ) - Setup device for one shot / on demand mode .
* @ indio_dev : The IIO device associated with the sampling hardware .
* @ irq : Optional interrupt line the hardware uses to notify new data
* samples are ready . Negative or zero values indicate no interrupts
* are available , meaning polling is required .
*
* Output Data Rate is configured for the highest possible rate so that
* conversion time and power consumption are reduced to a minimum .
* Note that hardware internal averaging machinery ( not implemented in this
* driver ) is not applicable in this mode .
*
* Device must have been previously enabled before calling
* zpa2326_config_oneshot ( ) .
*
* Return : Zero when successful , a negative error code otherwise .
*/
static int zpa2326_config_oneshot ( const struct iio_dev * indio_dev ,
int irq )
{
struct regmap * regs = ( ( struct zpa2326_private * )
iio_priv ( indio_dev ) ) - > regmap ;
const struct zpa2326_frequency * freq = zpa2326_highest_frequency ( ) ;
int err ;
/* Setup highest available Output Data Rate for one shot mode. */
err = regmap_write ( regs , ZPA2326_CTRL_REG3_REG , freq - > odr ) ;
if ( err )
return err ;
if ( irq > 0 ) {
/* Request interrupt when new sample is available. */
err = regmap_write ( regs , ZPA2326_CTRL_REG1_REG ,
( u8 ) ~ ZPA2326_CTRL_REG1_MASK_DATA_READY ) ;
if ( err ) {
dev_err ( indio_dev - > dev . parent ,
" failed to setup one shot mode (%d) " , err ) ;
return err ;
}
}
zpa2326_dbg ( indio_dev , " one shot mode setup @%dHz " , freq - > hz ) ;
return 0 ;
}
/**
* zpa2326_clear_fifo ( ) - Clear remaining entries in hardware FIFO .
* @ indio_dev : The IIO device associated with the sampling hardware .
* @ min_count : Number of samples present within hardware FIFO .
*
* @ min_count argument is a hint corresponding to the known minimum number of
* samples currently living in the FIFO . This allows to reduce the number of bus
* accesses by skipping status register read operation as long as we know for
* sure there are still entries left .
*
* Return : Zero when successful , a negative error code otherwise .
*/
static int zpa2326_clear_fifo ( const struct iio_dev * indio_dev ,
unsigned int min_count )
{
struct regmap * regs = ( ( struct zpa2326_private * )
iio_priv ( indio_dev ) ) - > regmap ;
int err ;
unsigned int val ;
if ( ! min_count ) {
/*
* No hint : read status register to determine whether FIFO is
* empty or not .
*/
err = regmap_read ( regs , ZPA2326_STATUS_REG , & val ) ;
if ( err < 0 )
goto err ;
if ( val & ZPA2326_STATUS_FIFO_E )
/* Fifo is empty: nothing to trash. */
return 0 ;
}
/* Clear FIFO. */
do {
/*
* A single fetch from pressure MSB register is enough to pop
* values out of FIFO .
*/
err = regmap_read ( regs , ZPA2326_PRESS_OUT_H_REG , & val ) ;
if ( err < 0 )
goto err ;
if ( min_count ) {
/*
* We know for sure there are at least min_count entries
* left in FIFO . Skip status register read .
*/
min_count - - ;
continue ;
}
err = regmap_read ( regs , ZPA2326_STATUS_REG , & val ) ;
if ( err < 0 )
goto err ;
} while ( ! ( val & ZPA2326_STATUS_FIFO_E ) ) ;
zpa2326_dbg ( indio_dev , " FIFO cleared " ) ;
return 0 ;
err :
zpa2326_err ( indio_dev , " failed to clear FIFO (%d) " , err ) ;
return err ;
}
/**
* zpa2326_dequeue_pressure ( ) - Retrieve the most recent pressure sample from
* hardware FIFO .
* @ indio_dev : The IIO device associated with the sampling hardware .
* @ pressure : Sampled pressure output .
*
* Note that ZPA2326 hardware FIFO stores pressure samples only .
*
* Return : Zero when successful , a negative error code otherwise .
*/
static int zpa2326_dequeue_pressure ( const struct iio_dev * indio_dev ,
u32 * pressure )
{
struct regmap * regs = ( ( struct zpa2326_private * )
iio_priv ( indio_dev ) ) - > regmap ;
unsigned int val ;
int err ;
int cleared = - 1 ;
err = regmap_read ( regs , ZPA2326_STATUS_REG , & val ) ;
if ( err < 0 )
return err ;
* pressure = 0 ;
if ( val & ZPA2326_STATUS_P_OR ) {
/*
* Fifo overrun : first sample dequeued from FIFO is the
* newest .
*/
zpa2326_warn ( indio_dev , " FIFO overflow " ) ;
err = regmap_bulk_read ( regs , ZPA2326_PRESS_OUT_XL_REG , pressure ,
3 ) ;
if ( err )
return err ;
# define ZPA2326_FIFO_DEPTH (16U)
/* Hardware FIFO may hold no more than 16 pressure samples. */
return zpa2326_clear_fifo ( indio_dev , ZPA2326_FIFO_DEPTH - 1 ) ;
}
/*
* Fifo has not overflown : retrieve newest sample . We need to pop
* values out until FIFO is empty : last fetched pressure is the newest .
* In nominal cases , we should find a single queued sample only .
*/
do {
err = regmap_bulk_read ( regs , ZPA2326_PRESS_OUT_XL_REG , pressure ,
3 ) ;
if ( err )
return err ;
err = regmap_read ( regs , ZPA2326_STATUS_REG , & val ) ;
if ( err < 0 )
return err ;
cleared + + ;
} while ( ! ( val & ZPA2326_STATUS_FIFO_E ) ) ;
if ( cleared )
/*
* Samples were pushed by hardware during previous rounds but we
* didn ' t consume them fast enough : inform user .
*/
zpa2326_dbg ( indio_dev , " cleared %d FIFO entries " , cleared ) ;
return 0 ;
}
/**
* zpa2326_fill_sample_buffer ( ) - Enqueue new channel samples to IIO buffer .
* @ indio_dev : The IIO device associated with the sampling hardware .
* @ private : Internal private state related to @ indio_dev .
*
* Return : Zero when successful , a negative error code otherwise .
*/
static int zpa2326_fill_sample_buffer ( struct iio_dev * indio_dev ,
const struct zpa2326_private * private )
{
struct {
u32 pressure ;
u16 temperature ;
u64 timestamp ;
} sample ;
int err ;
if ( test_bit ( 0 , indio_dev - > active_scan_mask ) ) {
/* Get current pressure from hardware FIFO. */
err = zpa2326_dequeue_pressure ( indio_dev , & sample . pressure ) ;
if ( err ) {
zpa2326_warn ( indio_dev , " failed to fetch pressure (%d) " ,
err ) ;
return err ;
}
}
if ( test_bit ( 1 , indio_dev - > active_scan_mask ) ) {
/* Get current temperature. */
err = regmap_bulk_read ( private - > regmap , ZPA2326_TEMP_OUT_L_REG ,
& sample . temperature , 2 ) ;
if ( err ) {
zpa2326_warn ( indio_dev ,
" failed to fetch temperature (%d) " , err ) ;
return err ;
}
}
/*
* Now push samples using timestamp stored either :
* - by hardware interrupt handler if interrupt is available : see
* zpa2326_handle_irq ( ) ,
* - or oneshot completion polling machinery : see
* zpa2326_trigger_handler ( ) .
*/
zpa2326_dbg ( indio_dev , " filling raw samples buffer " ) ;
iio_push_to_buffers_with_timestamp ( indio_dev , & sample ,
private - > timestamp ) ;
return 0 ;
}
# ifdef CONFIG_PM
static int zpa2326_runtime_suspend ( struct device * parent )
{
const struct iio_dev * indio_dev = dev_get_drvdata ( parent ) ;
if ( pm_runtime_autosuspend_expiration ( parent ) )
/* Userspace changed autosuspend delay. */
return - EAGAIN ;
zpa2326_power_off ( indio_dev , iio_priv ( indio_dev ) ) ;
return 0 ;
}
static int zpa2326_runtime_resume ( struct device * parent )
{
const struct iio_dev * indio_dev = dev_get_drvdata ( parent ) ;
return zpa2326_power_on ( indio_dev , iio_priv ( indio_dev ) ) ;
}
const struct dev_pm_ops zpa2326_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS ( pm_runtime_force_suspend ,
pm_runtime_force_resume )
SET_RUNTIME_PM_OPS ( zpa2326_runtime_suspend , zpa2326_runtime_resume ,
NULL )
} ;
2022-01-30 23:56:54 +03:00
EXPORT_SYMBOL_NS_GPL ( zpa2326_pm_ops , IIO_ZPA2326 ) ;
2016-09-13 15:23:14 +03:00
/**
* zpa2326_resume ( ) - Request the PM layer to power supply the device .
* @ indio_dev : The IIO device associated with the sampling hardware .
*
* Return :
* < 0 - a negative error code meaning failure ;
* 0 - success , device has just been powered up ;
* 1 - success , device was already powered .
*/
static int zpa2326_resume ( const struct iio_dev * indio_dev )
{
int err ;
err = pm_runtime_get_sync ( indio_dev - > dev . parent ) ;
2020-06-05 05:44:44 +03:00
if ( err < 0 ) {
pm_runtime_put ( indio_dev - > dev . parent ) ;
2016-09-13 15:23:14 +03:00
return err ;
2020-06-05 05:44:44 +03:00
}
2016-09-13 15:23:14 +03:00
if ( err > 0 ) {
/*
* Device was already power supplied : get it out of low power
* mode and inform caller .
*/
zpa2326_enable_device ( indio_dev ) ;
return 1 ;
}
/* Inform caller device has just been brought back to life. */
return 0 ;
}
/**
* zpa2326_suspend ( ) - Schedule a power down using autosuspend feature of PM
* layer .
* @ indio_dev : The IIO device associated with the sampling hardware .
*
* Device is switched to low power mode at first to save power even when
* attached regulator is a " dummy " one .
*/
static void zpa2326_suspend ( struct iio_dev * indio_dev )
{
struct device * parent = indio_dev - > dev . parent ;
zpa2326_sleep ( indio_dev ) ;
pm_runtime_mark_last_busy ( parent ) ;
pm_runtime_put_autosuspend ( parent ) ;
}
static void zpa2326_init_runtime ( struct device * parent )
{
pm_runtime_get_noresume ( parent ) ;
pm_runtime_set_active ( parent ) ;
pm_runtime_enable ( parent ) ;
pm_runtime_set_autosuspend_delay ( parent , 1000 ) ;
pm_runtime_use_autosuspend ( parent ) ;
pm_runtime_mark_last_busy ( parent ) ;
pm_runtime_put_autosuspend ( parent ) ;
}
static void zpa2326_fini_runtime ( struct device * parent )
{
pm_runtime_disable ( parent ) ;
pm_runtime_set_suspended ( parent ) ;
}
# else /* !CONFIG_PM */
static int zpa2326_resume ( const struct iio_dev * indio_dev )
{
zpa2326_enable_device ( indio_dev ) ;
return 0 ;
}
static void zpa2326_suspend ( struct iio_dev * indio_dev )
{
zpa2326_sleep ( indio_dev ) ;
}
# define zpa2326_init_runtime(_parent)
# define zpa2326_fini_runtime(_parent)
# endif /* !CONFIG_PM */
/**
* zpa2326_handle_irq ( ) - Process hardware interrupts .
* @ irq : Interrupt line the hardware uses to notify new data has arrived .
* @ data : The IIO device associated with the sampling hardware .
*
* Timestamp buffered samples as soon as possible then schedule threaded bottom
* half .
*
* Return : Always successful .
*/
static irqreturn_t zpa2326_handle_irq ( int irq , void * data )
{
2017-04-01 17:18:39 +03:00
struct iio_dev * indio_dev = data ;
2016-09-13 15:23:14 +03:00
if ( iio_buffer_enabled ( indio_dev ) ) {
/* Timestamping needed for buffered sampling only. */
( ( struct zpa2326_private * )
iio_priv ( indio_dev ) ) - > timestamp = iio_get_time_ns ( indio_dev ) ;
}
return IRQ_WAKE_THREAD ;
}
/**
* zpa2326_handle_threaded_irq ( ) - Interrupt bottom - half handler .
* @ irq : Interrupt line the hardware uses to notify new data has arrived .
* @ data : The IIO device associated with the sampling hardware .
*
* Mainly ensures interrupt is caused by a real " new sample available "
* condition . This relies upon the ability to perform blocking / sleeping bus
* accesses to slave ' s registers . This is why zpa2326_handle_threaded_irq ( ) is
* called from within a thread , i . e . not called from hard interrupt context .
*
* When device is using its own internal hardware trigger in continuous sampling
* mode , data are available into hardware FIFO once interrupt has occurred . All
* we have to do is to dispatch the trigger , which in turn will fetch data and
* fill IIO buffer .
*
* When not using its own internal hardware trigger , the device has been
* configured in one - shot mode either by an external trigger or the IIO read_raw
* hook . This means one of the latter is currently waiting for sampling
* completion , in which case we must simply wake it up .
*
* See zpa2326_trigger_handler ( ) .
*
* Return :
* % IRQ_NONE - no consistent interrupt happened ;
* % IRQ_HANDLED - there was new samples available .
*/
static irqreturn_t zpa2326_handle_threaded_irq ( int irq , void * data )
{
2017-04-01 17:18:39 +03:00
struct iio_dev * indio_dev = data ;
2016-09-13 15:23:14 +03:00
struct zpa2326_private * priv = iio_priv ( indio_dev ) ;
unsigned int val ;
bool cont ;
irqreturn_t ret = IRQ_NONE ;
/*
* Are we using our own internal trigger in triggered buffer mode , i . e . ,
* currently working in continuous sampling mode ?
*/
cont = ( iio_buffer_enabled ( indio_dev ) & &
iio_trigger_using_own ( indio_dev ) ) ;
/*
* Device works according to a level interrupt scheme : reading interrupt
* status de - asserts interrupt line .
*/
priv - > result = regmap_read ( priv - > regmap , ZPA2326_INT_SOURCE_REG , & val ) ;
if ( priv - > result < 0 ) {
if ( cont )
return IRQ_NONE ;
goto complete ;
}
/* Data ready is the only interrupt source we requested. */
if ( ! ( val & ZPA2326_INT_SOURCE_DATA_READY ) ) {
/*
* Interrupt happened but no new sample available : likely caused
* by spurious interrupts , in which case , returning IRQ_NONE
* allows to benefit from the generic spurious interrupts
* handling .
*/
zpa2326_warn ( indio_dev , " unexpected interrupt status %02x " ,
val ) ;
if ( cont )
return IRQ_NONE ;
priv - > result = - ENODATA ;
goto complete ;
}
/* New sample available: dispatch internal trigger consumers. */
iio_trigger_poll_chained ( priv - > trigger ) ;
if ( cont )
/*
* Internal hardware trigger has been scheduled above : it will
* fetch data on its own .
*/
return IRQ_HANDLED ;
ret = IRQ_HANDLED ;
complete :
/*
* Wake up direct or externaly triggered buffer mode waiters : see
* zpa2326_sample_oneshot ( ) and zpa2326_trigger_handler ( ) .
*/
complete ( & priv - > data_ready ) ;
return ret ;
}
/**
* zpa2326_wait_oneshot_completion ( ) - Wait for oneshot data ready interrupt .
* @ indio_dev : The IIO device associated with the sampling hardware .
* @ private : Internal private state related to @ indio_dev .
*
* Return : Zero when successful , a negative error code otherwise .
*/
static int zpa2326_wait_oneshot_completion ( const struct iio_dev * indio_dev ,
struct zpa2326_private * private )
{
unsigned int val ;
2017-05-14 11:43:55 +03:00
long timeout ;
2016-09-13 15:23:14 +03:00
zpa2326_dbg ( indio_dev , " waiting for one shot completion interrupt " ) ;
2017-05-14 11:43:55 +03:00
timeout = wait_for_completion_interruptible_timeout (
2016-09-13 15:23:14 +03:00
& private - > data_ready , ZPA2326_CONVERSION_JIFFIES ) ;
2017-05-14 11:43:55 +03:00
if ( timeout > 0 )
2016-09-13 15:23:14 +03:00
/*
* Interrupt handler completed before timeout : return operation
* status .
*/
return private - > result ;
/* Clear all interrupts just to be sure. */
regmap_read ( private - > regmap , ZPA2326_INT_SOURCE_REG , & val ) ;
2017-05-14 11:43:55 +03:00
if ( ! timeout ) {
2016-09-13 15:23:14 +03:00
/* Timed out. */
2017-05-14 11:43:55 +03:00
zpa2326_warn ( indio_dev , " no one shot interrupt occurred (%ld) " ,
timeout ) ;
2017-07-05 11:14:59 +03:00
return - ETIME ;
2017-05-14 11:43:55 +03:00
}
2016-09-13 15:23:14 +03:00
2017-07-05 11:14:59 +03:00
zpa2326_warn ( indio_dev , " wait for one shot interrupt cancelled " ) ;
return - ERESTARTSYS ;
2016-09-13 15:23:14 +03:00
}
static int zpa2326_init_managed_irq ( struct device * parent ,
struct iio_dev * indio_dev ,
struct zpa2326_private * private ,
int irq )
{
int err ;
private - > irq = irq ;
if ( irq < = 0 ) {
/*
* Platform declared no interrupt line : device will be polled
* for data availability .
*/
dev_info ( parent , " no interrupt found, running in polling mode " ) ;
return 0 ;
}
init_completion ( & private - > data_ready ) ;
/* Request handler to be scheduled into threaded interrupt context. */
err = devm_request_threaded_irq ( parent , irq , zpa2326_handle_irq ,
zpa2326_handle_threaded_irq ,
IRQF_TRIGGER_RISING | IRQF_ONESHOT ,
dev_name ( parent ) , indio_dev ) ;
if ( err ) {
dev_err ( parent , " failed to request interrupt %d (%d) " , irq ,
err ) ;
return err ;
}
dev_info ( parent , " using interrupt %d " , irq ) ;
return 0 ;
}
/**
* zpa2326_poll_oneshot_completion ( ) - Actively poll for one shot data ready .
* @ indio_dev : The IIO device associated with the sampling hardware .
*
* Loop over registers content to detect end of sampling cycle . Used when DT
* declared no valid interrupt lines .
*
* Return : Zero when successful , a negative error code otherwise .
*/
static int zpa2326_poll_oneshot_completion ( const struct iio_dev * indio_dev )
{
unsigned long tmout = jiffies + ZPA2326_CONVERSION_JIFFIES ;
struct regmap * regs = ( ( struct zpa2326_private * )
iio_priv ( indio_dev ) ) - > regmap ;
unsigned int val ;
int err ;
zpa2326_dbg ( indio_dev , " polling for one shot completion " ) ;
/*
* At least , 100 ms is needed for the device to complete its one - shot
* cycle .
*/
if ( msleep_interruptible ( 100 ) )
return - ERESTARTSYS ;
/* Poll for conversion completion in hardware. */
while ( true ) {
err = regmap_read ( regs , ZPA2326_CTRL_REG0_REG , & val ) ;
if ( err < 0 )
goto err ;
if ( ! ( val & ZPA2326_CTRL_REG0_ONE_SHOT ) )
/* One-shot bit self clears at conversion end. */
break ;
if ( time_after ( jiffies , tmout ) ) {
/* Prevent from waiting forever : let's time out. */
err = - ETIME ;
goto err ;
}
usleep_range ( 10000 , 20000 ) ;
}
/*
* In oneshot mode , pressure sample availability guarantees that
* temperature conversion has also completed : just check pressure
* status bit to keep things simple .
*/
err = regmap_read ( regs , ZPA2326_STATUS_REG , & val ) ;
if ( err < 0 )
goto err ;
if ( ! ( val & ZPA2326_STATUS_P_DA ) ) {
/* No sample available. */
err = - ENODATA ;
goto err ;
}
return 0 ;
err :
zpa2326_warn ( indio_dev , " failed to poll one shot completion (%d) " , err ) ;
return err ;
}
/**
* zpa2326_fetch_raw_sample ( ) - Retrieve a raw sample and convert it to CPU
* endianness .
* @ indio_dev : The IIO device associated with the sampling hardware .
* @ type : Type of measurement / channel to fetch from .
* @ value : Sample output .
*
* Return : Zero when successful , a negative error code otherwise .
*/
static int zpa2326_fetch_raw_sample ( const struct iio_dev * indio_dev ,
enum iio_chan_type type ,
int * value )
{
struct regmap * regs = ( ( struct zpa2326_private * )
iio_priv ( indio_dev ) ) - > regmap ;
int err ;
2020-04-21 03:31:33 +03:00
u8 v [ 3 ] ;
2016-09-13 15:23:14 +03:00
switch ( type ) {
case IIO_PRESSURE :
zpa2326_dbg ( indio_dev , " fetching raw pressure sample " ) ;
2020-04-21 03:31:33 +03:00
err = regmap_bulk_read ( regs , ZPA2326_PRESS_OUT_XL_REG , v , sizeof ( v ) ) ;
2016-09-13 15:23:14 +03:00
if ( err ) {
zpa2326_warn ( indio_dev , " failed to fetch pressure (%d) " ,
err ) ;
return err ;
}
2020-04-21 03:31:33 +03:00
* value = get_unaligned_le24 ( & v [ 0 ] ) ;
2016-09-13 15:23:14 +03:00
return IIO_VAL_INT ;
case IIO_TEMP :
zpa2326_dbg ( indio_dev , " fetching raw temperature sample " ) ;
err = regmap_bulk_read ( regs , ZPA2326_TEMP_OUT_L_REG , value , 2 ) ;
if ( err ) {
zpa2326_warn ( indio_dev ,
" failed to fetch temperature (%d) " , err ) ;
return err ;
}
/* Temperature is a 16 bits wide little-endian signed int. */
* value = ( int ) le16_to_cpup ( ( __le16 * ) value ) ;
return IIO_VAL_INT ;
default :
return - EINVAL ;
}
}
/**
* zpa2326_sample_oneshot ( ) - Perform a complete one shot sampling cycle .
* @ indio_dev : The IIO device associated with the sampling hardware .
* @ type : Type of measurement / channel to fetch from .
* @ value : Sample output .
*
* Return : Zero when successful , a negative error code otherwise .
*/
static int zpa2326_sample_oneshot ( struct iio_dev * indio_dev ,
enum iio_chan_type type ,
int * value )
{
int ret ;
struct zpa2326_private * priv ;
ret = iio_device_claim_direct_mode ( indio_dev ) ;
if ( ret )
return ret ;
ret = zpa2326_resume ( indio_dev ) ;
if ( ret < 0 )
goto release ;
priv = iio_priv ( indio_dev ) ;
if ( ret > 0 ) {
/*
* We were already power supplied . Just clear hardware FIFO to
* get rid of samples acquired during previous rounds ( if any ) .
* Sampling operation always generates both temperature and
* pressure samples . The latter are always enqueued into
* hardware FIFO . This may lead to situations were pressure
* samples still sit into FIFO when previous cycle ( s ) fetched
* temperature data only .
* Hence , we need to clear hardware FIFO content to prevent from
* getting outdated values at the end of current cycle .
*/
if ( type = = IIO_PRESSURE ) {
ret = zpa2326_clear_fifo ( indio_dev , 0 ) ;
if ( ret )
goto suspend ;
}
} else {
/*
* We have just been power supplied , i . e . device is in default
* " out of reset " state , meaning we need to reconfigure it
* entirely .
*/
ret = zpa2326_config_oneshot ( indio_dev , priv - > irq ) ;
if ( ret )
goto suspend ;
}
/* Start a sampling cycle in oneshot mode. */
ret = zpa2326_start_oneshot ( indio_dev ) ;
if ( ret )
goto suspend ;
/* Wait for sampling cycle to complete. */
if ( priv - > irq > 0 )
ret = zpa2326_wait_oneshot_completion ( indio_dev , priv ) ;
else
ret = zpa2326_poll_oneshot_completion ( indio_dev ) ;
if ( ret )
goto suspend ;
/* Retrieve raw sample value and convert it to CPU endianness. */
ret = zpa2326_fetch_raw_sample ( indio_dev , type , value ) ;
suspend :
zpa2326_suspend ( indio_dev ) ;
release :
iio_device_release_direct_mode ( indio_dev ) ;
return ret ;
}
/**
* zpa2326_trigger_handler ( ) - Perform an IIO buffered sampling round in one
* shot mode .
* @ irq : The software interrupt assigned to @ data
* @ data : The IIO poll function dispatched by external trigger our device is
* attached to .
*
* Bottom - half handler called by the IIO trigger to which our device is
* currently attached . Allows us to synchronize this device buffered sampling
* either with external events ( such as timer expiration , external device sample
* ready , etc . . . ) or with its own interrupt ( internal hardware trigger ) .
*
* When using an external trigger , basically run the same sequence of operations
* as for zpa2326_sample_oneshot ( ) with the following hereafter . Hardware FIFO
* is not cleared since already done at buffering enable time and samples
* dequeueing always retrieves the most recent value .
*
* Otherwise , when internal hardware trigger has dispatched us , just fetch data
* from hardware FIFO .
*
* Fetched data will pushed unprocessed to IIO buffer since samples conversion
* is delegated to userspace in buffered mode ( endianness , etc . . . ) .
*
* Return :
* % IRQ_NONE - no consistent interrupt happened ;
* % IRQ_HANDLED - there was new samples available .
*/
static irqreturn_t zpa2326_trigger_handler ( int irq , void * data )
{
struct iio_dev * indio_dev = ( ( struct iio_poll_func * )
data ) - > indio_dev ;
struct zpa2326_private * priv = iio_priv ( indio_dev ) ;
bool cont ;
/*
* We have been dispatched , meaning we are in triggered buffer mode .
* Using our own internal trigger implies we are currently in continuous
* hardware sampling mode .
*/
cont = iio_trigger_using_own ( indio_dev ) ;
if ( ! cont ) {
/* On demand sampling : start a one shot cycle. */
if ( zpa2326_start_oneshot ( indio_dev ) )
goto out ;
/* Wait for sampling cycle to complete. */
if ( priv - > irq < = 0 ) {
/* No interrupt available: poll for completion. */
if ( zpa2326_poll_oneshot_completion ( indio_dev ) )
goto out ;
/* Only timestamp sample once it is ready. */
priv - > timestamp = iio_get_time_ns ( indio_dev ) ;
} else {
/* Interrupt handlers will timestamp for us. */
if ( zpa2326_wait_oneshot_completion ( indio_dev , priv ) )
goto out ;
}
}
/* Enqueue to IIO buffer / userspace. */
zpa2326_fill_sample_buffer ( indio_dev , priv ) ;
out :
if ( ! cont )
/* Don't switch to low power if sampling continuously. */
zpa2326_sleep ( indio_dev ) ;
/* Inform attached trigger we are done. */
iio_trigger_notify_done ( indio_dev - > trig ) ;
return IRQ_HANDLED ;
}
/**
* zpa2326_preenable_buffer ( ) - Prepare device for configuring triggered
* sampling
* modes .
* @ indio_dev : The IIO device associated with the sampling hardware .
*
* Basically power up device .
* Called with IIO device ' s lock held .
*
* Return : Zero when successful , a negative error code otherwise .
*/
static int zpa2326_preenable_buffer ( struct iio_dev * indio_dev )
{
int ret = zpa2326_resume ( indio_dev ) ;
if ( ret < 0 )
return ret ;
/* Tell zpa2326_postenable_buffer() if we have just been powered on. */
( ( struct zpa2326_private * )
iio_priv ( indio_dev ) ) - > waken = iio_priv ( indio_dev ) ;
return 0 ;
}
/**
* zpa2326_postenable_buffer ( ) - Configure device for triggered sampling .
* @ indio_dev : The IIO device associated with the sampling hardware .
*
* Basically setup one - shot mode if plugging external trigger .
* Otherwise , let internal trigger configure continuous sampling :
* see zpa2326_set_trigger_state ( ) .
*
* If an error is returned , IIO layer will call our postdisable hook for us ,
* i . e . no need to explicitly power device off here .
* Called with IIO device ' s lock held .
*
* Called with IIO device ' s lock held .
*
* Return : Zero when successful , a negative error code otherwise .
*/
static int zpa2326_postenable_buffer ( struct iio_dev * indio_dev )
{
const struct zpa2326_private * priv = iio_priv ( indio_dev ) ;
int err ;
if ( ! priv - > waken ) {
/*
* We were already power supplied . Just clear hardware FIFO to
* get rid of samples acquired during previous rounds ( if any ) .
*/
err = zpa2326_clear_fifo ( indio_dev , 0 ) ;
2020-05-25 14:38:53 +03:00
if ( err ) {
zpa2326_err ( indio_dev ,
" failed to enable buffering (%d) " , err ) ;
return err ;
}
2016-09-13 15:23:14 +03:00
}
if ( ! iio_trigger_using_own ( indio_dev ) & & priv - > waken ) {
/*
* We are using an external trigger and we have just been
* powered up : reconfigure one - shot mode .
*/
err = zpa2326_config_oneshot ( indio_dev , priv - > irq ) ;
2020-05-25 14:38:53 +03:00
if ( err ) {
zpa2326_err ( indio_dev ,
" failed to enable buffering (%d) " , err ) ;
return err ;
}
2016-09-13 15:23:14 +03:00
}
return 0 ;
}
static int zpa2326_postdisable_buffer ( struct iio_dev * indio_dev )
{
zpa2326_suspend ( indio_dev ) ;
return 0 ;
}
static const struct iio_buffer_setup_ops zpa2326_buffer_setup_ops = {
. preenable = zpa2326_preenable_buffer ,
. postenable = zpa2326_postenable_buffer ,
. postdisable = zpa2326_postdisable_buffer
} ;
/**
* zpa2326_set_trigger_state ( ) - Start / stop continuous sampling .
* @ trig : The trigger being attached to IIO device associated with the sampling
* hardware .
* @ state : Tell whether to start ( true ) or stop ( false )
*
* Basically enable / disable hardware continuous sampling mode .
*
* Called with IIO device ' s lock held at postenable ( ) or predisable ( ) time .
*
* Return : Zero when successful , a negative error code otherwise .
*/
static int zpa2326_set_trigger_state ( struct iio_trigger * trig , bool state )
{
const struct iio_dev * indio_dev = dev_get_drvdata (
trig - > dev . parent ) ;
const struct zpa2326_private * priv = iio_priv ( indio_dev ) ;
int err ;
if ( ! state ) {
/*
* Switch trigger off : in case of failure , interrupt is left
* disabled in order to prevent handler from accessing released
* resources .
*/
unsigned int val ;
/*
* As device is working in continuous mode , handlers may be
* accessing resources we are currently freeing . . .
* Prevent this by disabling interrupt handlers and ensure
* the device will generate no more interrupts unless explicitly
* required to , i . e . by restoring back to default one shot mode .
*/
disable_irq ( priv - > irq ) ;
/*
* Disable continuous sampling mode to restore settings for
* one shot / direct sampling operations .
*/
err = regmap_write ( priv - > regmap , ZPA2326_CTRL_REG3_REG ,
zpa2326_highest_frequency ( ) - > odr ) ;
if ( err )
return err ;
/*
* Now that device won ' t generate interrupts on its own ,
* acknowledge any currently active interrupts ( may happen on
* rare occasions while stopping continuous mode ) .
*/
err = regmap_read ( priv - > regmap , ZPA2326_INT_SOURCE_REG , & val ) ;
if ( err < 0 )
return err ;
/*
* Re - enable interrupts only if we can guarantee the device will
* generate no more interrupts to prevent handlers from
* accessing released resources .
*/
enable_irq ( priv - > irq ) ;
zpa2326_dbg ( indio_dev , " continuous mode stopped " ) ;
} else {
/*
* Switch trigger on : start continuous sampling at required
* frequency .
*/
if ( priv - > waken ) {
/* Enable interrupt if getting out of reset. */
err = regmap_write ( priv - > regmap , ZPA2326_CTRL_REG1_REG ,
( u8 )
~ ZPA2326_CTRL_REG1_MASK_DATA_READY ) ;
if ( err )
return err ;
}
/* Enable continuous sampling at specified frequency. */
err = regmap_write ( priv - > regmap , ZPA2326_CTRL_REG3_REG ,
ZPA2326_CTRL_REG3_ENABLE_MEAS |
priv - > frequency - > odr ) ;
if ( err )
return err ;
zpa2326_dbg ( indio_dev , " continuous mode setup @%dHz " ,
priv - > frequency - > hz ) ;
}
return 0 ;
}
static const struct iio_trigger_ops zpa2326_trigger_ops = {
. set_trigger_state = zpa2326_set_trigger_state ,
} ;
/**
2021-03-14 19:46:48 +03:00
* zpa2326_init_managed_trigger ( ) - Create interrupt driven / hardware trigger
2016-09-13 15:23:14 +03:00
* allowing to notify external devices a new sample is
* ready .
* @ parent : Hardware sampling device @ indio_dev is a child of .
* @ indio_dev : The IIO device associated with the sampling hardware .
* @ private : Internal private state related to @ indio_dev .
* @ irq : Optional interrupt line the hardware uses to notify new data
* samples are ready . Negative or zero values indicate no interrupts
* are available , meaning polling is required .
*
* Only relevant when DT declares a valid interrupt line .
*
* Return : Zero when successful , a negative error code otherwise .
*/
static int zpa2326_init_managed_trigger ( struct device * parent ,
struct iio_dev * indio_dev ,
struct zpa2326_private * private ,
int irq )
{
struct iio_trigger * trigger ;
int ret ;
if ( irq < = 0 )
return 0 ;
trigger = devm_iio_trigger_alloc ( parent , " %s-dev%d " ,
2021-04-26 20:49:03 +03:00
indio_dev - > name ,
iio_device_id ( indio_dev ) ) ;
2016-09-13 15:23:14 +03:00
if ( ! trigger )
return - ENOMEM ;
/* Basic setup. */
trigger - > ops = & zpa2326_trigger_ops ;
private - > trigger = trigger ;
/* Register to triggers space. */
ret = devm_iio_trigger_register ( parent , trigger ) ;
if ( ret )
dev_err ( parent , " failed to register hardware trigger (%d) " ,
ret ) ;
return ret ;
}
static int zpa2326_get_frequency ( const struct iio_dev * indio_dev )
{
return ( ( struct zpa2326_private * ) iio_priv ( indio_dev ) ) - > frequency - > hz ;
}
static int zpa2326_set_frequency ( struct iio_dev * indio_dev , int hz )
{
struct zpa2326_private * priv = iio_priv ( indio_dev ) ;
int freq ;
int err ;
/* Check if requested frequency is supported. */
for ( freq = 0 ; freq < ARRAY_SIZE ( zpa2326_sampling_frequencies ) ; freq + + )
if ( zpa2326_sampling_frequencies [ freq ] . hz = = hz )
break ;
if ( freq = = ARRAY_SIZE ( zpa2326_sampling_frequencies ) )
return - EINVAL ;
/* Don't allow changing frequency if buffered sampling is ongoing. */
err = iio_device_claim_direct_mode ( indio_dev ) ;
if ( err )
return err ;
priv - > frequency = & zpa2326_sampling_frequencies [ freq ] ;
iio_device_release_direct_mode ( indio_dev ) ;
return 0 ;
}
/* Expose supported hardware sampling frequencies (Hz) through sysfs. */
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL ( " 1 5 11 23 " ) ;
static struct attribute * zpa2326_attributes [ ] = {
& iio_const_attr_sampling_frequency_available . dev_attr . attr ,
NULL
} ;
static const struct attribute_group zpa2326_attribute_group = {
. attrs = zpa2326_attributes ,
} ;
static int zpa2326_read_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan ,
int * val ,
int * val2 ,
long mask )
{
switch ( mask ) {
case IIO_CHAN_INFO_RAW :
return zpa2326_sample_oneshot ( indio_dev , chan - > type , val ) ;
case IIO_CHAN_INFO_SCALE :
switch ( chan - > type ) {
case IIO_PRESSURE :
/*
* Pressure resolution is 1 / 64 Pascal . Scale to kPascal
* as required by IIO ABI .
*/
* val = 1 ;
* val2 = 64000 ;
return IIO_VAL_FRACTIONAL ;
case IIO_TEMP :
/*
* Temperature follows the equation :
* Temp [ degC ] = Tempcode * 0.00649 - 176.83
* where :
* Tempcode is composed the raw sampled 16 bits .
*
* Hence , to produce a temperature in milli - degrees
* Celsius according to IIO ABI , we need to apply the
* following equation to raw samples :
* Temp [ milli degC ] = ( Tempcode + Offset ) * Scale
* where :
* Offset = - 176.83 / 0.00649
* Scale = 0.00649 * 1000
*/
* val = 6 ;
* val2 = 490000 ;
return IIO_VAL_INT_PLUS_MICRO ;
default :
return - EINVAL ;
}
case IIO_CHAN_INFO_OFFSET :
switch ( chan - > type ) {
case IIO_TEMP :
* val = - 17683000 ;
* val2 = 649 ;
return IIO_VAL_FRACTIONAL ;
default :
return - EINVAL ;
}
case IIO_CHAN_INFO_SAMP_FREQ :
* val = zpa2326_get_frequency ( indio_dev ) ;
return IIO_VAL_INT ;
default :
return - EINVAL ;
}
}
static int zpa2326_write_raw ( struct iio_dev * indio_dev ,
const struct iio_chan_spec * chan ,
int val ,
int val2 ,
long mask )
{
if ( ( mask ! = IIO_CHAN_INFO_SAMP_FREQ ) | | val2 )
return - EINVAL ;
return zpa2326_set_frequency ( indio_dev , val ) ;
}
static const struct iio_chan_spec zpa2326_channels [ ] = {
[ 0 ] = {
. type = IIO_PRESSURE ,
. scan_index = 0 ,
. scan_type = {
. sign = ' u ' ,
. realbits = 24 ,
. storagebits = 32 ,
. endianness = IIO_LE ,
} ,
. info_mask_separate = BIT ( IIO_CHAN_INFO_RAW ) |
BIT ( IIO_CHAN_INFO_SCALE ) ,
. info_mask_shared_by_all = BIT ( IIO_CHAN_INFO_SAMP_FREQ ) ,
} ,
[ 1 ] = {
. type = IIO_TEMP ,
. scan_index = 1 ,
. scan_type = {
. sign = ' s ' ,
. realbits = 16 ,
. storagebits = 16 ,
. endianness = IIO_LE ,
} ,
. info_mask_separate = BIT ( IIO_CHAN_INFO_RAW ) |
BIT ( IIO_CHAN_INFO_SCALE ) |
BIT ( IIO_CHAN_INFO_OFFSET ) ,
. info_mask_shared_by_all = BIT ( IIO_CHAN_INFO_SAMP_FREQ ) ,
} ,
[ 2 ] = IIO_CHAN_SOFT_TIMESTAMP ( 2 ) ,
} ;
static const struct iio_info zpa2326_info = {
. attrs = & zpa2326_attribute_group ,
. read_raw = zpa2326_read_raw ,
. write_raw = zpa2326_write_raw ,
} ;
static struct iio_dev * zpa2326_create_managed_iiodev ( struct device * device ,
const char * name ,
struct regmap * regmap )
{
struct iio_dev * indio_dev ;
/* Allocate space to hold IIO device internal state. */
indio_dev = devm_iio_device_alloc ( device ,
sizeof ( struct zpa2326_private ) ) ;
if ( ! indio_dev )
return NULL ;
/* Setup for userspace synchronous on demand sampling. */
indio_dev - > modes = INDIO_DIRECT_MODE ;
indio_dev - > channels = zpa2326_channels ;
indio_dev - > num_channels = ARRAY_SIZE ( zpa2326_channels ) ;
indio_dev - > name = name ;
indio_dev - > info = & zpa2326_info ;
return indio_dev ;
}
int zpa2326_probe ( struct device * parent ,
const char * name ,
int irq ,
unsigned int hwid ,
struct regmap * regmap )
{
struct iio_dev * indio_dev ;
struct zpa2326_private * priv ;
int err ;
unsigned int id ;
indio_dev = zpa2326_create_managed_iiodev ( parent , name , regmap ) ;
if ( ! indio_dev )
return - ENOMEM ;
priv = iio_priv ( indio_dev ) ;
priv - > vref = devm_regulator_get ( parent , " vref " ) ;
if ( IS_ERR ( priv - > vref ) )
return PTR_ERR ( priv - > vref ) ;
priv - > vdd = devm_regulator_get ( parent , " vdd " ) ;
if ( IS_ERR ( priv - > vdd ) )
return PTR_ERR ( priv - > vdd ) ;
/* Set default hardware sampling frequency to highest rate supported. */
priv - > frequency = zpa2326_highest_frequency ( ) ;
/*
* Plug device ' s underlying bus abstraction : this MUST be set before
* registering interrupt handlers since an interrupt might happen if
* power up sequence is not properly applied .
*/
priv - > regmap = regmap ;
err = devm_iio_triggered_buffer_setup ( parent , indio_dev , NULL ,
zpa2326_trigger_handler ,
& zpa2326_buffer_setup_ops ) ;
if ( err )
return err ;
err = zpa2326_init_managed_trigger ( parent , indio_dev , priv , irq ) ;
if ( err )
return err ;
err = zpa2326_init_managed_irq ( parent , indio_dev , priv , irq ) ;
if ( err )
return err ;
/* Power up to check device ID and perform initial hardware setup. */
err = zpa2326_power_on ( indio_dev , priv ) ;
if ( err )
return err ;
/* Read id register to check we are talking to the right slave. */
err = regmap_read ( regmap , ZPA2326_DEVICE_ID_REG , & id ) ;
if ( err )
goto sleep ;
if ( id ! = hwid ) {
dev_err ( parent , " found device with unexpected id %02x " , id ) ;
err = - ENODEV ;
goto sleep ;
}
err = zpa2326_config_oneshot ( indio_dev , irq ) ;
if ( err )
goto sleep ;
/* Setup done : go sleeping. Device will be awaken upon user request. */
err = zpa2326_sleep ( indio_dev ) ;
if ( err )
goto poweroff ;
dev_set_drvdata ( parent , indio_dev ) ;
zpa2326_init_runtime ( parent ) ;
err = iio_device_register ( indio_dev ) ;
if ( err ) {
zpa2326_fini_runtime ( parent ) ;
goto poweroff ;
}
return 0 ;
sleep :
/* Put to sleep just in case power regulators are "dummy" ones. */
zpa2326_sleep ( indio_dev ) ;
poweroff :
zpa2326_power_off ( indio_dev , priv ) ;
return err ;
}
2022-01-30 23:56:54 +03:00
EXPORT_SYMBOL_NS_GPL ( zpa2326_probe , IIO_ZPA2326 ) ;
2016-09-13 15:23:14 +03:00
void zpa2326_remove ( const struct device * parent )
{
struct iio_dev * indio_dev = dev_get_drvdata ( parent ) ;
iio_device_unregister ( indio_dev ) ;
zpa2326_fini_runtime ( indio_dev - > dev . parent ) ;
zpa2326_sleep ( indio_dev ) ;
zpa2326_power_off ( indio_dev , iio_priv ( indio_dev ) ) ;
}
2022-01-30 23:56:54 +03:00
EXPORT_SYMBOL_NS_GPL ( zpa2326_remove , IIO_ZPA2326 ) ;
2016-09-13 15:23:14 +03:00
MODULE_AUTHOR ( " Gregor Boirie <gregor.boirie@parrot.com> " ) ;
MODULE_DESCRIPTION ( " Core driver for Murata ZPA2326 pressure sensor " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;