forked from Minki/linux
Third set of new stuff for IIO in the 4.5 cycle.
New driver features - us5182 * Add interrupt support and rising / falling threshold events. Cleanups / fixes to new stuff / minor additions * Expose the IIO value formatting function for drivers to make use of internally. - ina2xx * Fix wrong channel order * Fix incorrect reporting of endianness * Adding documentation of ABI unique to this device - mma8452 * Drop an unused register description * Use an enum for the channel index to aid readability - sca3000 * Use standard NULL comparison style - us5182 * fix an inconsistency in status of enable (a bug with no real effect until above patches are applied) * refactor the read_raw function to improve maintainability / readability. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCAAGBQJWeZ3IAAoJEFSFNJnE9BaIT2UP/3+VlQzBFrg1pBqLCR4xqMHB 9gUBInzgBwmzpmAqD9pkvyG5f9fTz7hSqX2IGkAA1V6I91H2cunEROSGyhFd4VBW vhUhpz9WpRyx+8yLE3fQKUU/UmZJWTI7Xyladwrk3k87OOdcfn3wjtUdTuAhD5SW OWzW9txC5dAgSEC5yhqD8VdXN6tRL/eEOEFawHlf9f7bBr9DuyhECp6aIP79gKAS pynUPe3R5Uk/GuXdKX6zEWim4XZxhQR0oRmtrdCPIbauK6/ENDOWcaAvgS3mcN8i KJ/L27hQGc5zjR8VzysZzZw+7Edc4EqY2UvhA19+0RN93064s0qvR8hoEMp0bHP/ MKGtwHv8MiqKfdCqIdimf6aT2GILTVWWx8WjyrM0O0+h444ba3ETRPGQ4mYNohuN Gt7FFv345aiFh2lQw8Rb54H2d19KV2hwUar3CTpRcl9OhOEnD3ulfDvQghzNlbXl nUh5dSOK+yDmXPPMEeZU4pYKG8rNaNZ1FxvVFy/yvUgytD1uqQDnWZ3b1gR0DiV9 56ucUcrSg74LSqC8R/D6BXb+73LPBTmpu60iGvOQsUYcnmJSdnmEobWCnSXGjFXR I2e/H/ZOL4+dyHVpoyfQIiDpe6rGgYQHxyQ/kojWn2NxCJpgUufuR6jPTJ9GMF7k eckCq5cDb0nmmg45EQq0 =aiE2 -----END PGP SIGNATURE----- Merge tag 'iio-for-4.5c' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next Jonathan writes: Third set of new stuff for IIO in the 4.5 cycle. New driver features - us5182 * Add interrupt support and rising / falling threshold events. Cleanups / fixes to new stuff / minor additions * Expose the IIO value formatting function for drivers to make use of internally. - ina2xx * Fix wrong channel order * Fix incorrect reporting of endianness * Adding documentation of ABI unique to this device - mma8452 * Drop an unused register description * Use an enum for the channel index to aid readability - sca3000 * Use standard NULL comparison style - us5182 * fix an inconsistency in status of enable (a bug with no real effect until above patches are applied) * refactor the read_raw function to improve maintainability / readability.
This commit is contained in:
commit
02c34ccc1d
24
Documentation/ABI/testing/sysfs-bus-iio-ina2xx-adc
Normal file
24
Documentation/ABI/testing/sysfs-bus-iio-ina2xx-adc
Normal file
@ -0,0 +1,24 @@
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_allow_async_readout
|
||||
Date: December 2015
|
||||
KernelVersion: 4.4
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
By default (value '0'), the capture thread checks for the Conversion
|
||||
Ready Flag to being set prior to committing a new value to the sample
|
||||
buffer. This synchronizes the in-chip conversion rate with the
|
||||
in-driver readout rate at the cost of an additional register read.
|
||||
|
||||
Writing '1' will remove the polling for the Conversion Ready Flags to
|
||||
save the additional i2c transaction, which will improve the bandwidth
|
||||
available for reading data. However, samples can be occasionally skipped
|
||||
or repeated, depending on the beat between the capture and conversion
|
||||
rates.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_shunt_resistor
|
||||
Date: December 2015
|
||||
KernelVersion: 4.4
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
The value of the shunt resistor may be known only at runtime fom an
|
||||
eeprom content read by a client application. This attribute allows to
|
||||
set its value in ohms.
|
@ -58,7 +58,6 @@
|
||||
#define MMA8452_FF_MT_COUNT 0x18
|
||||
#define MMA8452_TRANSIENT_CFG 0x1d
|
||||
#define MMA8452_TRANSIENT_CFG_HPF_BYP BIT(0)
|
||||
#define MMA8452_TRANSIENT_CFG_CHAN(chan) BIT(chan + 1)
|
||||
#define MMA8452_TRANSIENT_CFG_ELE BIT(4)
|
||||
#define MMA8452_TRANSIENT_SRC 0x1e
|
||||
#define MMA8452_TRANSIENT_SRC_XTRANSE BIT(1)
|
||||
@ -144,6 +143,13 @@ struct mma_chip_info {
|
||||
u8 ev_count;
|
||||
};
|
||||
|
||||
enum {
|
||||
idx_x,
|
||||
idx_y,
|
||||
idx_z,
|
||||
idx_ts,
|
||||
};
|
||||
|
||||
static int mma8452_drdy(struct mma8452_data *data)
|
||||
{
|
||||
int tries = 150;
|
||||
@ -817,31 +823,31 @@ static struct attribute_group mma8452_event_attribute_group = {
|
||||
}
|
||||
|
||||
static const struct iio_chan_spec mma8452_channels[] = {
|
||||
MMA8452_CHANNEL(X, 0, 12),
|
||||
MMA8452_CHANNEL(Y, 1, 12),
|
||||
MMA8452_CHANNEL(Z, 2, 12),
|
||||
IIO_CHAN_SOFT_TIMESTAMP(3),
|
||||
MMA8452_CHANNEL(X, idx_x, 12),
|
||||
MMA8452_CHANNEL(Y, idx_y, 12),
|
||||
MMA8452_CHANNEL(Z, idx_z, 12),
|
||||
IIO_CHAN_SOFT_TIMESTAMP(idx_ts),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec mma8453_channels[] = {
|
||||
MMA8452_CHANNEL(X, 0, 10),
|
||||
MMA8452_CHANNEL(Y, 1, 10),
|
||||
MMA8452_CHANNEL(Z, 2, 10),
|
||||
IIO_CHAN_SOFT_TIMESTAMP(3),
|
||||
MMA8452_CHANNEL(X, idx_x, 10),
|
||||
MMA8452_CHANNEL(Y, idx_y, 10),
|
||||
MMA8452_CHANNEL(Z, idx_z, 10),
|
||||
IIO_CHAN_SOFT_TIMESTAMP(idx_ts),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec mma8652_channels[] = {
|
||||
MMA8652_CHANNEL(X, 0, 12),
|
||||
MMA8652_CHANNEL(Y, 1, 12),
|
||||
MMA8652_CHANNEL(Z, 2, 12),
|
||||
IIO_CHAN_SOFT_TIMESTAMP(3),
|
||||
MMA8652_CHANNEL(X, idx_x, 12),
|
||||
MMA8652_CHANNEL(Y, idx_y, 12),
|
||||
MMA8652_CHANNEL(Z, idx_z, 12),
|
||||
IIO_CHAN_SOFT_TIMESTAMP(idx_ts),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec mma8653_channels[] = {
|
||||
MMA8652_CHANNEL(X, 0, 10),
|
||||
MMA8652_CHANNEL(Y, 1, 10),
|
||||
MMA8652_CHANNEL(Z, 2, 10),
|
||||
IIO_CHAN_SOFT_TIMESTAMP(3),
|
||||
MMA8652_CHANNEL(X, idx_x, 10),
|
||||
MMA8652_CHANNEL(Y, idx_y, 10),
|
||||
MMA8652_CHANNEL(Z, idx_z, 10),
|
||||
IIO_CHAN_SOFT_TIMESTAMP(idx_ts),
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -400,7 +400,7 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev,
|
||||
.sign = 'u', \
|
||||
.realbits = 16, \
|
||||
.storagebits = 16, \
|
||||
.endianness = IIO_LE, \
|
||||
.endianness = IIO_CPU, \
|
||||
} \
|
||||
}
|
||||
|
||||
@ -428,8 +428,8 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev,
|
||||
static const struct iio_chan_spec ina2xx_channels[] = {
|
||||
INA2XX_CHAN_VOLTAGE(0, INA2XX_SHUNT_VOLTAGE),
|
||||
INA2XX_CHAN_VOLTAGE(1, INA2XX_BUS_VOLTAGE),
|
||||
INA2XX_CHAN(IIO_CURRENT, 2, INA2XX_CURRENT),
|
||||
INA2XX_CHAN(IIO_POWER, 3, INA2XX_POWER),
|
||||
INA2XX_CHAN(IIO_POWER, 2, INA2XX_POWER),
|
||||
INA2XX_CHAN(IIO_CURRENT, 3, INA2XX_CURRENT),
|
||||
IIO_CHAN_SOFT_TIMESTAMP(4),
|
||||
};
|
||||
|
||||
|
@ -470,6 +470,7 @@ ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iio_format_value);
|
||||
|
||||
static ssize_t iio_read_channel_info(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
|
@ -20,7 +20,10 @@
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/iio/events.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/pm.h>
|
||||
@ -30,6 +33,8 @@
|
||||
#define US5182D_CFG0_ONESHOT_EN BIT(6)
|
||||
#define US5182D_CFG0_SHUTDOWN_EN BIT(7)
|
||||
#define US5182D_CFG0_WORD_ENABLE BIT(0)
|
||||
#define US5182D_CFG0_PROX BIT(3)
|
||||
#define US5182D_CFG0_PX_IRQ BIT(2)
|
||||
|
||||
#define US5182D_REG_CFG1 0x01
|
||||
#define US5182D_CFG1_ALS_RES16 BIT(4)
|
||||
@ -41,6 +46,7 @@
|
||||
|
||||
#define US5182D_REG_CFG3 0x03
|
||||
#define US5182D_CFG3_LED_CURRENT100 (BIT(4) | BIT(5))
|
||||
#define US5182D_CFG3_INT_SOURCE_PX BIT(3)
|
||||
|
||||
#define US5182D_REG_CFG4 0x10
|
||||
|
||||
@ -55,6 +61,13 @@
|
||||
#define US5182D_REG_AUTO_LDARK_GAIN 0x29
|
||||
#define US5182D_REG_AUTO_HDARK_GAIN 0x2a
|
||||
|
||||
/* Thresholds for events: px low (0x08-l, 0x09-h), px high (0x0a-l 0x0b-h) */
|
||||
#define US5182D_REG_PXL_TH 0x08
|
||||
#define US5182D_REG_PXH_TH 0x0a
|
||||
|
||||
#define US5182D_REG_PXL_TH_DEFAULT 1000
|
||||
#define US5182D_REG_PXH_TH_DEFAULT 30000
|
||||
|
||||
#define US5182D_OPMODE_ALS 0x01
|
||||
#define US5182D_OPMODE_PX 0x02
|
||||
#define US5182D_OPMODE_SHIFT 4
|
||||
@ -84,6 +97,8 @@
|
||||
#define US5182D_READ_WORD 2
|
||||
#define US5182D_OPSTORE_SLEEP_TIME 20 /* ms */
|
||||
#define US5182D_SLEEP_MS 3000 /* ms */
|
||||
#define US5182D_PXH_TH_DISABLE 0xffff
|
||||
#define US5182D_PXL_TH_DISABLE 0x0000
|
||||
|
||||
/* Available ranges: [12354, 7065, 3998, 2202, 1285, 498, 256, 138] lux */
|
||||
static const int us5182d_scales[] = {188500, 107800, 61000, 33600, 19600, 7600,
|
||||
@ -119,6 +134,12 @@ struct us5182d_data {
|
||||
u8 upper_dark_gain;
|
||||
u16 *us5182d_dark_ths;
|
||||
|
||||
u16 px_low_th;
|
||||
u16 px_high_th;
|
||||
|
||||
int rising_en;
|
||||
int falling_en;
|
||||
|
||||
u8 opmode;
|
||||
u8 power_mode;
|
||||
|
||||
@ -148,10 +169,26 @@ static const struct {
|
||||
{US5182D_REG_CFG1, US5182D_CFG1_ALS_RES16},
|
||||
{US5182D_REG_CFG2, (US5182D_CFG2_PX_RES16 |
|
||||
US5182D_CFG2_PXGAIN_DEFAULT)},
|
||||
{US5182D_REG_CFG3, US5182D_CFG3_LED_CURRENT100},
|
||||
{US5182D_REG_CFG3, US5182D_CFG3_LED_CURRENT100 |
|
||||
US5182D_CFG3_INT_SOURCE_PX},
|
||||
{US5182D_REG_CFG4, 0x00},
|
||||
};
|
||||
|
||||
static const struct iio_event_spec us5182d_events[] = {
|
||||
{
|
||||
.type = IIO_EV_TYPE_THRESH,
|
||||
.dir = IIO_EV_DIR_RISING,
|
||||
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
|
||||
BIT(IIO_EV_INFO_ENABLE),
|
||||
},
|
||||
{
|
||||
.type = IIO_EV_TYPE_THRESH,
|
||||
.dir = IIO_EV_DIR_FALLING,
|
||||
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
|
||||
BIT(IIO_EV_INFO_ENABLE),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec us5182d_channels[] = {
|
||||
{
|
||||
.type = IIO_LIGHT,
|
||||
@ -161,26 +198,11 @@ static const struct iio_chan_spec us5182d_channels[] = {
|
||||
{
|
||||
.type = IIO_PROXIMITY,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
||||
.event_spec = us5182d_events,
|
||||
.num_event_specs = ARRAY_SIZE(us5182d_events),
|
||||
}
|
||||
};
|
||||
|
||||
static int us5182d_get_als(struct us5182d_data *data)
|
||||
{
|
||||
int ret;
|
||||
unsigned long result;
|
||||
|
||||
ret = i2c_smbus_read_word_data(data->client,
|
||||
US5182D_REG_ADL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
result = ret * data->ga / US5182D_GA_RESOLUTION;
|
||||
if (result > 0xffff)
|
||||
result = 0xffff;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int us5182d_oneshot_en(struct us5182d_data *data)
|
||||
{
|
||||
int ret;
|
||||
@ -238,8 +260,12 @@ static int us5182d_als_enable(struct us5182d_data *data)
|
||||
int ret;
|
||||
u8 mode;
|
||||
|
||||
if (data->power_mode == US5182D_ONESHOT)
|
||||
return us5182d_set_opmode(data, US5182D_ALS_ONLY);
|
||||
if (data->power_mode == US5182D_ONESHOT) {
|
||||
ret = us5182d_set_opmode(data, US5182D_ALS_ONLY);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
data->px_enabled = false;
|
||||
}
|
||||
|
||||
if (data->als_enabled)
|
||||
return 0;
|
||||
@ -260,8 +286,12 @@ static int us5182d_px_enable(struct us5182d_data *data)
|
||||
int ret;
|
||||
u8 mode;
|
||||
|
||||
if (data->power_mode == US5182D_ONESHOT)
|
||||
return us5182d_set_opmode(data, US5182D_PX_ONLY);
|
||||
if (data->power_mode == US5182D_ONESHOT) {
|
||||
ret = us5182d_set_opmode(data, US5182D_PX_ONLY);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
data->als_enabled = false;
|
||||
}
|
||||
|
||||
if (data->px_enabled)
|
||||
return 0;
|
||||
@ -277,6 +307,39 @@ static int us5182d_px_enable(struct us5182d_data *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int us5182d_get_als(struct us5182d_data *data)
|
||||
{
|
||||
int ret;
|
||||
unsigned long result;
|
||||
|
||||
ret = us5182d_als_enable(data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = i2c_smbus_read_word_data(data->client,
|
||||
US5182D_REG_ADL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
result = ret * data->ga / US5182D_GA_RESOLUTION;
|
||||
if (result > 0xffff)
|
||||
result = 0xffff;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int us5182d_get_px(struct us5182d_data *data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = us5182d_px_enable(data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return i2c_smbus_read_word_data(data->client,
|
||||
US5182D_REG_PDL);
|
||||
}
|
||||
|
||||
static int us5182d_shutdown_en(struct us5182d_data *data, u8 state)
|
||||
{
|
||||
int ret;
|
||||
@ -323,6 +386,46 @@ static int us5182d_set_power_state(struct us5182d_data *data, bool on)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int us5182d_read_value(struct us5182d_data *data,
|
||||
struct iio_chan_spec const *chan)
|
||||
{
|
||||
int ret, value;
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
|
||||
if (data->power_mode == US5182D_ONESHOT) {
|
||||
ret = us5182d_oneshot_en(data);
|
||||
if (ret < 0)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
ret = us5182d_set_power_state(data, true);
|
||||
if (ret < 0)
|
||||
goto out_err;
|
||||
|
||||
if (chan->type == IIO_LIGHT)
|
||||
ret = us5182d_get_als(data);
|
||||
else
|
||||
ret = us5182d_get_px(data);
|
||||
if (ret < 0)
|
||||
goto out_poweroff;
|
||||
|
||||
value = ret;
|
||||
|
||||
ret = us5182d_set_power_state(data, false);
|
||||
if (ret < 0)
|
||||
goto out_err;
|
||||
|
||||
mutex_unlock(&data->lock);
|
||||
return value;
|
||||
|
||||
out_poweroff:
|
||||
us5182d_set_power_state(data, false);
|
||||
out_err:
|
||||
mutex_unlock(&data->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int us5182d_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan, int *val,
|
||||
int *val2, long mask)
|
||||
@ -332,76 +435,21 @@ static int us5182d_read_raw(struct iio_dev *indio_dev,
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
switch (chan->type) {
|
||||
case IIO_LIGHT:
|
||||
mutex_lock(&data->lock);
|
||||
if (data->power_mode == US5182D_ONESHOT) {
|
||||
ret = us5182d_oneshot_en(data);
|
||||
if (ret < 0)
|
||||
goto out_err;
|
||||
}
|
||||
ret = us5182d_set_power_state(data, true);
|
||||
if (ret < 0)
|
||||
goto out_err;
|
||||
ret = us5182d_als_enable(data);
|
||||
if (ret < 0)
|
||||
goto out_poweroff;
|
||||
ret = us5182d_get_als(data);
|
||||
if (ret < 0)
|
||||
goto out_poweroff;
|
||||
*val = ret;
|
||||
ret = us5182d_set_power_state(data, false);
|
||||
if (ret < 0)
|
||||
goto out_err;
|
||||
mutex_unlock(&data->lock);
|
||||
return IIO_VAL_INT;
|
||||
case IIO_PROXIMITY:
|
||||
mutex_lock(&data->lock);
|
||||
if (data->power_mode == US5182D_ONESHOT) {
|
||||
ret = us5182d_oneshot_en(data);
|
||||
if (ret < 0)
|
||||
goto out_err;
|
||||
}
|
||||
ret = us5182d_set_power_state(data, true);
|
||||
if (ret < 0)
|
||||
goto out_err;
|
||||
ret = us5182d_px_enable(data);
|
||||
if (ret < 0)
|
||||
goto out_poweroff;
|
||||
ret = i2c_smbus_read_word_data(data->client,
|
||||
US5182D_REG_PDL);
|
||||
if (ret < 0)
|
||||
goto out_poweroff;
|
||||
*val = ret;
|
||||
ret = us5182d_set_power_state(data, false);
|
||||
if (ret < 0)
|
||||
goto out_err;
|
||||
mutex_unlock(&data->lock);
|
||||
return IIO_VAL_INT;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = us5182d_read_value(data, chan);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*val = ret;
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*val = 0;
|
||||
*val2 = us5182d_scales[ret & US5182D_AGAIN_MASK];
|
||||
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
|
||||
out_poweroff:
|
||||
us5182d_set_power_state(data, false);
|
||||
out_err:
|
||||
mutex_unlock(&data->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -479,11 +527,201 @@ static int us5182d_write_raw(struct iio_dev *indio_dev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int us5182d_setup_prox(struct iio_dev *indio_dev,
|
||||
enum iio_event_direction dir, u16 val)
|
||||
{
|
||||
struct us5182d_data *data = iio_priv(indio_dev);
|
||||
|
||||
if (dir == IIO_EV_DIR_FALLING)
|
||||
return i2c_smbus_write_word_data(data->client,
|
||||
US5182D_REG_PXL_TH, val);
|
||||
else if (dir == IIO_EV_DIR_RISING)
|
||||
return i2c_smbus_write_word_data(data->client,
|
||||
US5182D_REG_PXH_TH, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int us5182d_read_thresh(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan, enum iio_event_type type,
|
||||
enum iio_event_direction dir, enum iio_event_info info, int *val,
|
||||
int *val2)
|
||||
{
|
||||
struct us5182d_data *data = iio_priv(indio_dev);
|
||||
|
||||
switch (dir) {
|
||||
case IIO_EV_DIR_RISING:
|
||||
mutex_lock(&data->lock);
|
||||
*val = data->px_high_th;
|
||||
mutex_unlock(&data->lock);
|
||||
break;
|
||||
case IIO_EV_DIR_FALLING:
|
||||
mutex_lock(&data->lock);
|
||||
*val = data->px_low_th;
|
||||
mutex_unlock(&data->lock);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return IIO_VAL_INT;
|
||||
}
|
||||
|
||||
static int us5182d_write_thresh(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan, enum iio_event_type type,
|
||||
enum iio_event_direction dir, enum iio_event_info info, int val,
|
||||
int val2)
|
||||
{
|
||||
struct us5182d_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
if (val < 0 || val > USHRT_MAX || val2 != 0)
|
||||
return -EINVAL;
|
||||
|
||||
switch (dir) {
|
||||
case IIO_EV_DIR_RISING:
|
||||
mutex_lock(&data->lock);
|
||||
if (data->rising_en) {
|
||||
ret = us5182d_setup_prox(indio_dev, dir, val);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
}
|
||||
data->px_high_th = val;
|
||||
mutex_unlock(&data->lock);
|
||||
break;
|
||||
case IIO_EV_DIR_FALLING:
|
||||
mutex_lock(&data->lock);
|
||||
if (data->falling_en) {
|
||||
ret = us5182d_setup_prox(indio_dev, dir, val);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
}
|
||||
data->px_low_th = val;
|
||||
mutex_unlock(&data->lock);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
mutex_unlock(&data->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int us5182d_read_event_config(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan, enum iio_event_type type,
|
||||
enum iio_event_direction dir)
|
||||
{
|
||||
struct us5182d_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
switch (dir) {
|
||||
case IIO_EV_DIR_RISING:
|
||||
mutex_lock(&data->lock);
|
||||
ret = data->rising_en;
|
||||
mutex_unlock(&data->lock);
|
||||
break;
|
||||
case IIO_EV_DIR_FALLING:
|
||||
mutex_lock(&data->lock);
|
||||
ret = data->falling_en;
|
||||
mutex_unlock(&data->lock);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int us5182d_write_event_config(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan, enum iio_event_type type,
|
||||
enum iio_event_direction dir, int state)
|
||||
{
|
||||
struct us5182d_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
u16 new_th;
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
|
||||
switch (dir) {
|
||||
case IIO_EV_DIR_RISING:
|
||||
if (data->rising_en == state) {
|
||||
mutex_unlock(&data->lock);
|
||||
return 0;
|
||||
}
|
||||
new_th = US5182D_PXH_TH_DISABLE;
|
||||
if (state) {
|
||||
data->power_mode = US5182D_CONTINUOUS;
|
||||
ret = us5182d_set_power_state(data, true);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
ret = us5182d_px_enable(data);
|
||||
if (ret < 0)
|
||||
goto err_poweroff;
|
||||
new_th = data->px_high_th;
|
||||
}
|
||||
ret = us5182d_setup_prox(indio_dev, dir, new_th);
|
||||
if (ret < 0)
|
||||
goto err_poweroff;
|
||||
data->rising_en = state;
|
||||
break;
|
||||
case IIO_EV_DIR_FALLING:
|
||||
if (data->falling_en == state) {
|
||||
mutex_unlock(&data->lock);
|
||||
return 0;
|
||||
}
|
||||
new_th = US5182D_PXL_TH_DISABLE;
|
||||
if (state) {
|
||||
data->power_mode = US5182D_CONTINUOUS;
|
||||
ret = us5182d_set_power_state(data, true);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
ret = us5182d_px_enable(data);
|
||||
if (ret < 0)
|
||||
goto err_poweroff;
|
||||
new_th = data->px_low_th;
|
||||
}
|
||||
ret = us5182d_setup_prox(indio_dev, dir, new_th);
|
||||
if (ret < 0)
|
||||
goto err_poweroff;
|
||||
data->falling_en = state;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!state) {
|
||||
ret = us5182d_set_power_state(data, false);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!data->falling_en && !data->rising_en && !data->default_continuous)
|
||||
data->power_mode = US5182D_ONESHOT;
|
||||
|
||||
mutex_unlock(&data->lock);
|
||||
return 0;
|
||||
|
||||
err_poweroff:
|
||||
if (state)
|
||||
us5182d_set_power_state(data, false);
|
||||
err:
|
||||
mutex_unlock(&data->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct iio_info us5182d_info = {
|
||||
.driver_module = THIS_MODULE,
|
||||
.read_raw = us5182d_read_raw,
|
||||
.write_raw = us5182d_write_raw,
|
||||
.attrs = &us5182d_attr_group,
|
||||
.read_event_value = &us5182d_read_thresh,
|
||||
.write_event_value = &us5182d_write_thresh,
|
||||
.read_event_config = &us5182d_read_event_config,
|
||||
.write_event_config = &us5182d_write_event_config,
|
||||
};
|
||||
|
||||
static int us5182d_reset(struct iio_dev *indio_dev)
|
||||
@ -505,6 +743,9 @@ static int us5182d_init(struct iio_dev *indio_dev)
|
||||
|
||||
data->opmode = 0;
|
||||
data->power_mode = US5182D_CONTINUOUS;
|
||||
data->px_low_th = US5182D_REG_PXL_TH_DEFAULT;
|
||||
data->px_high_th = US5182D_REG_PXH_TH_DEFAULT;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(us5182d_regvals); i++) {
|
||||
ret = i2c_smbus_write_byte_data(data->client,
|
||||
us5182d_regvals[i].reg,
|
||||
@ -575,6 +816,33 @@ static int us5182d_dark_gain_config(struct iio_dev *indio_dev)
|
||||
US5182D_REG_DARK_AUTO_EN_DEFAULT);
|
||||
}
|
||||
|
||||
static irqreturn_t us5182d_irq_thread_handler(int irq, void *private)
|
||||
{
|
||||
struct iio_dev *indio_dev = private;
|
||||
struct us5182d_data *data = iio_priv(indio_dev);
|
||||
enum iio_event_direction dir;
|
||||
int ret;
|
||||
u64 ev;
|
||||
|
||||
ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0);
|
||||
if (ret < 0) {
|
||||
dev_err(&data->client->dev, "i2c transfer error in irq\n");
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
dir = ret & US5182D_CFG0_PROX ? IIO_EV_DIR_RISING : IIO_EV_DIR_FALLING;
|
||||
ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 1, IIO_EV_TYPE_THRESH, dir);
|
||||
|
||||
iio_push_event(indio_dev, ev, iio_get_time_ns());
|
||||
|
||||
ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0,
|
||||
ret & ~US5182D_CFG0_PX_IRQ);
|
||||
if (ret < 0)
|
||||
dev_err(&data->client->dev, "i2c transfer error in irq\n");
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int us5182d_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
@ -606,6 +874,16 @@ static int us5182d_probe(struct i2c_client *client,
|
||||
return (ret < 0) ? ret : -ENODEV;
|
||||
}
|
||||
|
||||
if (client->irq > 0) {
|
||||
ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
|
||||
us5182d_irq_thread_handler,
|
||||
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||
"us5182d-irq", indio_dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else
|
||||
dev_warn(&client->dev, "no valid irq found\n");
|
||||
|
||||
us5182d_get_platform_data(indio_dev);
|
||||
ret = us5182d_init(indio_dev);
|
||||
if (ret < 0)
|
||||
|
@ -48,7 +48,7 @@ static int sca3000_read_data(struct sca3000_state *st,
|
||||
}
|
||||
};
|
||||
*rx_p = kmalloc(len, GFP_KERNEL);
|
||||
if (*rx_p == NULL) {
|
||||
if (!*rx_p) {
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
|
@ -636,6 +636,8 @@ static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev)
|
||||
}
|
||||
#endif
|
||||
|
||||
ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals);
|
||||
|
||||
int iio_str_to_fixpoint(const char *str, int fract_mult, int *integer,
|
||||
int *fract);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user