mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-24 17:59:32 +00:00
3rd round of IIO new drivers, cleanups and functionality for the 3.17 cycle.
New drivers * isl29125 digital color light sensor driver * TAOS/AMS tcs3414 digital color sensor Staging graduation * ad7291 ADC driver. New functionality * st_sensors - device tree support and bindings * mma8452 - device tree support Cleanups * Drop redundant variables in a number of drivers. * Reorder a structure definition to ealy wiht a warning about static not being at the beginning in the hid-sensors driver. * Switch a few more drivers away from using explicit sampling_frequency attribute to providing this through the core. * Make hid_sensor_get_reporting_interval static as only used within a single file. * Drop a redundant check for negative values in an unsigned variable from ad9832 * Drop some duplicate case labels in the event monitor example code. * Use devm_ioremap_resource to simplify error handling. * Use devm_kzalloc within the blackfin timer driver to simplify error handling and removal. * A number of cleanups of the ad7291 from Hartmut Knaack in response to a patch moving it out of staging. * Core support for the period info element about events. It has been in the abi for a while, but not added until now to the newer handling of information related to events. * Add HAS_IOMEM dependency to mxs_lradc to avoid build issues when testing enabled. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABAgAGBQJTwtZlAAoJEFSFNJnE9BaIwk0P/AjNATwzEb+ODIeYdQXbliKJ ntQlUXhGa1ronrSD/iDsgW7JUbSDcVDKLfZFtmO0oqdJ8Mofb03jUJqRgivpIlq9 8cbgNZd5Ef4LARHjEsfySAEgZB6x1nnmJkspwcvdAiGqXvooe9HYQuWUkX/e9CYK QSb9BpisaPqvuDV3OfGlzshJIm6ntO9O842xrZdvJDAwi4IAyfabGslflA/AGWU1 ty3duPJvJzNHfq7iJiLhbGcc4yOmtc16lPKdVcpGC8BPdjdQdrw9axFrE0aoCZwF zYTUeQnoZGt9ervGaYRdi6rmcoyu/waRZvJUwIbXpHE4JNgB4waU/4iGqTqfQQnd tV/0RRKcke4QgQ0k9lZZCHUgedW1LSFpXWFWGXezlHyCieCicrx4WVkH4wEFheC1 6fb4OeBQY6nwkAdMOwzzHYEkieeYgKA269uKEeyJ4rMhyS36hoQNpSzMqz31c43w Ct0iaZdlFIEjoXkx8OumGojJ67oOGJECzfuXSn3xkNFAT2enyy/LzTyGvxGxwaMq r3accTdYqd00Z1Jje2MV1KRIcrn9pDJS9obFdesFQj9aV00FSSD8ZyckeHrgLxqV zQN567YGpyr2/q3WEW3ecJksnre1tYSwagRmfGheJIcYV/n4qiXO0R/VbSZbnFIz 68w07E9URklroJn/3wek =n+vY -----END PGP SIGNATURE----- Merge tag 'iio-for-3.17c' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next Jonathan writes: 3rd round of IIO new drivers, cleanups and functionality for the 3.17 cycle. New drivers * isl29125 digital color light sensor driver * TAOS/AMS tcs3414 digital color sensor Staging graduation * ad7291 ADC driver. New functionality * st_sensors - device tree support and bindings * mma8452 - device tree support Cleanups * Drop redundant variables in a number of drivers. * Reorder a structure definition to ealy wiht a warning about static not being at the beginning in the hid-sensors driver. * Switch a few more drivers away from using explicit sampling_frequency attribute to providing this through the core. * Make hid_sensor_get_reporting_interval static as only used within a single file. * Drop a redundant check for negative values in an unsigned variable from ad9832 * Drop some duplicate case labels in the event monitor example code. * Use devm_ioremap_resource to simplify error handling. * Use devm_kzalloc within the blackfin timer driver to simplify error handling and removal. * A number of cleanups of the ad7291 from Hartmut Knaack in response to a patch moving it out of staging. * Core support for the period info element about events. It has been in the abi for a while, but not added until now to the newer handling of information related to events. * Add HAS_IOMEM dependency to mxs_lradc to avoid build issues when testing enabled.
This commit is contained in:
commit
db7c17ecbf
47 changed files with 1392 additions and 481 deletions
|
@ -50,6 +50,7 @@ epson,rx8581 I2C-BUS INTERFACE REAL TIME CLOCK MODULE
|
||||||
fsl,mag3110 MAG3110: Xtrinsic High Accuracy, 3D Magnetometer
|
fsl,mag3110 MAG3110: Xtrinsic High Accuracy, 3D Magnetometer
|
||||||
fsl,mc13892 MC13892: Power Management Integrated Circuit (PMIC) for i.MX35/51
|
fsl,mc13892 MC13892: Power Management Integrated Circuit (PMIC) for i.MX35/51
|
||||||
fsl,mma8450 MMA8450Q: Xtrinsic Low-power, 3-axis Xtrinsic Accelerometer
|
fsl,mma8450 MMA8450Q: Xtrinsic Low-power, 3-axis Xtrinsic Accelerometer
|
||||||
|
fsl,mma8452 MMA8452Q: 3-axis 12-bit / 8-bit Digital Accelerometer
|
||||||
fsl,mpr121 MPR121: Proximity Capacitive Touch Sensor Controller
|
fsl,mpr121 MPR121: Proximity Capacitive Touch Sensor Controller
|
||||||
fsl,sgtl5000 SGTL5000: Ultra Low-Power Audio Codec
|
fsl,sgtl5000 SGTL5000: Ultra Low-Power Audio Codec
|
||||||
gmt,g751 G751: Digital Temperature Sensor and Thermal Watchdog with Two-Wire Interface
|
gmt,g751 G751: Digital Temperature Sensor and Thermal Watchdog with Two-Wire Interface
|
||||||
|
|
54
Documentation/devicetree/bindings/iio/st-sensors.txt
Normal file
54
Documentation/devicetree/bindings/iio/st-sensors.txt
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
STMicroelectronics MEMS sensors
|
||||||
|
|
||||||
|
The STMicroelectronics sensor devices are pretty straight-forward I2C or
|
||||||
|
SPI devices, all sharing the same device tree descriptions no matter what
|
||||||
|
type of sensor it is.
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible: see the list of valid compatible strings below
|
||||||
|
- reg: the I2C or SPI address the device will respond to
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
- vdd-supply: an optional regulator that needs to be on to provide VDD
|
||||||
|
power to the sensor.
|
||||||
|
- vddio-supply: an optional regulator that needs to be on to provide the
|
||||||
|
VDD IO power to the sensor.
|
||||||
|
- st,drdy-int-pin: the pin on the package that will be used to signal
|
||||||
|
"data ready" (valid values: 1 or 2). This property is not configurable
|
||||||
|
on all sensors.
|
||||||
|
|
||||||
|
Sensors may also have applicable pin control settings, those use the
|
||||||
|
standard bindings from pinctrl/pinctrl-bindings.txt.
|
||||||
|
|
||||||
|
Valid compatible strings:
|
||||||
|
|
||||||
|
Accelerometers:
|
||||||
|
- st,lsm303dlh-accel
|
||||||
|
- st,lsm303dlhc-accel
|
||||||
|
- st,lis3dh-accel
|
||||||
|
- st,lsm330d-accel
|
||||||
|
- st,lsm330dl-accel
|
||||||
|
- st,lsm330dlc-accel
|
||||||
|
- st,lis331dlh-accel
|
||||||
|
- st,lsm303dl-accel
|
||||||
|
- st,lsm303dlm-accel
|
||||||
|
- st,lsm330-accel
|
||||||
|
|
||||||
|
Gyroscopes:
|
||||||
|
- st,l3g4200d-gyro
|
||||||
|
- st,lsm330d-gyro
|
||||||
|
- st,lsm330dl-gyro
|
||||||
|
- st,lsm330dlc-gyro
|
||||||
|
- st,l3gd20-gyro
|
||||||
|
- st,l3g4is-gyro
|
||||||
|
- st,lsm330-gyro
|
||||||
|
|
||||||
|
Magnetometers:
|
||||||
|
- st,lsm303dlhc-magn
|
||||||
|
- st,lsm303dlm-magn
|
||||||
|
- st,lis3mdl-magn
|
||||||
|
|
||||||
|
Pressure sensors:
|
||||||
|
- st,lps001wp-press
|
||||||
|
- st,lps25h-press
|
||||||
|
- st,lps331ap-press
|
|
@ -423,9 +423,15 @@ static const struct i2c_device_id mma8452_id[] = {
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, mma8452_id);
|
MODULE_DEVICE_TABLE(i2c, mma8452_id);
|
||||||
|
|
||||||
|
static const struct of_device_id mma8452_dt_ids[] = {
|
||||||
|
{ .compatible = "fsl,mma8452" },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
static struct i2c_driver mma8452_driver = {
|
static struct i2c_driver mma8452_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "mma8452",
|
.name = "mma8452",
|
||||||
|
.of_match_table = of_match_ptr(mma8452_dt_ids),
|
||||||
.pm = MMA8452_PM_OPS,
|
.pm = MMA8452_PM_OPS,
|
||||||
},
|
},
|
||||||
.probe = mma8452_probe,
|
.probe = mma8452_probe,
|
||||||
|
|
|
@ -393,6 +393,9 @@ static int st_accel_read_raw(struct iio_dev *indio_dev,
|
||||||
*val = 0;
|
*val = 0;
|
||||||
*val2 = adata->current_fullscale->gain;
|
*val2 = adata->current_fullscale->gain;
|
||||||
return IIO_VAL_INT_PLUS_MICRO;
|
return IIO_VAL_INT_PLUS_MICRO;
|
||||||
|
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||||
|
*val = adata->odr;
|
||||||
|
return IIO_VAL_INT;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -410,6 +413,13 @@ static int st_accel_write_raw(struct iio_dev *indio_dev,
|
||||||
case IIO_CHAN_INFO_SCALE:
|
case IIO_CHAN_INFO_SCALE:
|
||||||
err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
|
err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
|
||||||
break;
|
break;
|
||||||
|
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||||
|
if (val2)
|
||||||
|
return -EINVAL;
|
||||||
|
mutex_lock(&indio_dev->mlock);
|
||||||
|
err = st_sensors_set_odr(indio_dev, val);
|
||||||
|
mutex_unlock(&indio_dev->mlock);
|
||||||
|
return err;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -417,14 +427,12 @@ static int st_accel_write_raw(struct iio_dev *indio_dev,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
|
|
||||||
static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
|
static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
|
||||||
static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_accel_scale_available);
|
static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_accel_scale_available);
|
||||||
|
|
||||||
static struct attribute *st_accel_attributes[] = {
|
static struct attribute *st_accel_attributes[] = {
|
||||||
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
|
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
|
||||||
&iio_dev_attr_in_accel_scale_available.dev_attr.attr,
|
&iio_dev_attr_in_accel_scale_available.dev_attr.attr,
|
||||||
&iio_dev_attr_sampling_frequency.dev_attr.attr,
|
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,55 @@
|
||||||
#include <linux/iio/common/st_sensors_i2c.h>
|
#include <linux/iio/common/st_sensors_i2c.h>
|
||||||
#include "st_accel.h"
|
#include "st_accel.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
static const struct of_device_id st_accel_of_match[] = {
|
||||||
|
{
|
||||||
|
.compatible = "st,lsm303dlh-accel",
|
||||||
|
.data = LSM303DLH_ACCEL_DEV_NAME,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "st,lsm303dlhc-accel",
|
||||||
|
.data = LSM303DLHC_ACCEL_DEV_NAME,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "st,lis3dh-accel",
|
||||||
|
.data = LIS3DH_ACCEL_DEV_NAME,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "st,lsm330d-accel",
|
||||||
|
.data = LSM330D_ACCEL_DEV_NAME,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "st,lsm330dl-accel",
|
||||||
|
.data = LSM330DL_ACCEL_DEV_NAME,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "st,lsm330dlc-accel",
|
||||||
|
.data = LSM330DLC_ACCEL_DEV_NAME,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "st,lis331dlh-accel",
|
||||||
|
.data = LIS331DLH_ACCEL_DEV_NAME,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "st,lsm303dl-accel",
|
||||||
|
.data = LSM303DL_ACCEL_DEV_NAME,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "st,lsm303dlm-accel",
|
||||||
|
.data = LSM303DLM_ACCEL_DEV_NAME,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "st,lsm330-accel",
|
||||||
|
.data = LSM330_ACCEL_DEV_NAME,
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, st_accel_of_match);
|
||||||
|
#else
|
||||||
|
#define st_accel_of_match NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
static int st_accel_i2c_probe(struct i2c_client *client,
|
static int st_accel_i2c_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
|
@ -31,6 +80,7 @@ static int st_accel_i2c_probe(struct i2c_client *client,
|
||||||
|
|
||||||
adata = iio_priv(indio_dev);
|
adata = iio_priv(indio_dev);
|
||||||
adata->dev = &client->dev;
|
adata->dev = &client->dev;
|
||||||
|
st_sensors_of_i2c_probe(client, st_accel_of_match);
|
||||||
|
|
||||||
st_sensors_i2c_configure(indio_dev, client, adata);
|
st_sensors_i2c_configure(indio_dev, client, adata);
|
||||||
|
|
||||||
|
@ -67,6 +117,7 @@ static struct i2c_driver st_accel_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.name = "st-accel-i2c",
|
.name = "st-accel-i2c",
|
||||||
|
.of_match_table = of_match_ptr(st_accel_of_match),
|
||||||
},
|
},
|
||||||
.probe = st_accel_i2c_probe,
|
.probe = st_accel_i2c_probe,
|
||||||
.remove = st_accel_i2c_remove,
|
.remove = st_accel_i2c_remove,
|
||||||
|
|
|
@ -20,6 +20,16 @@ config AD7266
|
||||||
Say yes here to build support for Analog Devices AD7265 and AD7266
|
Say yes here to build support for Analog Devices AD7265 and AD7266
|
||||||
ADCs.
|
ADCs.
|
||||||
|
|
||||||
|
config AD7291
|
||||||
|
tristate "Analog Devices AD7291 ADC driver"
|
||||||
|
depends on I2C
|
||||||
|
help
|
||||||
|
Say yes here to build support for Analog Devices AD7291
|
||||||
|
8 Channel ADC with temperature sensor.
|
||||||
|
|
||||||
|
To compile this driver as a module, choose M here: the
|
||||||
|
module will be called ad7291.
|
||||||
|
|
||||||
config AD7298
|
config AD7298
|
||||||
tristate "Analog Devices AD7298 ADC driver"
|
tristate "Analog Devices AD7298 ADC driver"
|
||||||
depends on SPI
|
depends on SPI
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
# When adding new entries keep the list in alphabetical order
|
# When adding new entries keep the list in alphabetical order
|
||||||
obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
|
obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
|
||||||
obj-$(CONFIG_AD7266) += ad7266.o
|
obj-$(CONFIG_AD7266) += ad7266.o
|
||||||
|
obj-$(CONFIG_AD7291) += ad7291.o
|
||||||
obj-$(CONFIG_AD7298) += ad7298.o
|
obj-$(CONFIG_AD7298) += ad7298.o
|
||||||
obj-$(CONFIG_AD7923) += ad7923.o
|
obj-$(CONFIG_AD7923) += ad7923.o
|
||||||
obj-$(CONFIG_AD7476) += ad7476.o
|
obj-$(CONFIG_AD7476) += ad7476.o
|
||||||
|
|
|
@ -6,22 +6,22 @@
|
||||||
* Licensed under the GPL-2 or later.
|
* Licensed under the GPL-2 or later.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/interrupt.h>
|
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/err.h>
|
||||||
#include <linux/slab.h>
|
|
||||||
#include <linux/sysfs.h>
|
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
#include <linux/err.h>
|
#include <linux/slab.h>
|
||||||
|
#include <linux/sysfs.h>
|
||||||
|
|
||||||
#include <linux/iio/iio.h>
|
#include <linux/iio/iio.h>
|
||||||
#include <linux/iio/sysfs.h>
|
#include <linux/iio/sysfs.h>
|
||||||
#include <linux/iio/events.h>
|
#include <linux/iio/events.h>
|
||||||
|
|
||||||
#include "ad7291.h"
|
#include <linux/platform_data/ad7291.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Simplified handling
|
* Simplified handling
|
||||||
|
@ -31,7 +31,6 @@
|
||||||
* is in the read mask.
|
* is in the read mask.
|
||||||
*
|
*
|
||||||
* The noise-delayed bit as per datasheet suggestion is always enabled.
|
* The noise-delayed bit as per datasheet suggestion is always enabled.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -47,33 +46,38 @@
|
||||||
#define AD7291_VOLTAGE_ALERT_STATUS 0x1F
|
#define AD7291_VOLTAGE_ALERT_STATUS 0x1F
|
||||||
#define AD7291_T_ALERT_STATUS 0x20
|
#define AD7291_T_ALERT_STATUS 0x20
|
||||||
|
|
||||||
|
#define AD7291_BITS 12
|
||||||
#define AD7291_VOLTAGE_LIMIT_COUNT 8
|
#define AD7291_VOLTAGE_LIMIT_COUNT 8
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AD7291 command
|
* AD7291 command
|
||||||
*/
|
*/
|
||||||
#define AD7291_AUTOCYCLE (1 << 0)
|
#define AD7291_AUTOCYCLE BIT(0)
|
||||||
#define AD7291_RESET (1 << 1)
|
#define AD7291_RESET BIT(1)
|
||||||
#define AD7291_ALERT_CLEAR (1 << 2)
|
#define AD7291_ALERT_CLEAR BIT(2)
|
||||||
#define AD7291_ALERT_POLARITY (1 << 3)
|
#define AD7291_ALERT_POLARITY BIT(3)
|
||||||
#define AD7291_EXT_REF (1 << 4)
|
#define AD7291_EXT_REF BIT(4)
|
||||||
#define AD7291_NOISE_DELAY (1 << 5)
|
#define AD7291_NOISE_DELAY BIT(5)
|
||||||
#define AD7291_T_SENSE_MASK (1 << 7)
|
#define AD7291_T_SENSE_MASK BIT(7)
|
||||||
#define AD7291_VOLTAGE_MASK 0xFF00
|
#define AD7291_VOLTAGE_MASK GENMASK(15, 8)
|
||||||
#define AD7291_VOLTAGE_OFFSET 0x8
|
#define AD7291_VOLTAGE_OFFSET 8
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AD7291 value masks
|
* AD7291 value masks
|
||||||
*/
|
*/
|
||||||
#define AD7291_CHANNEL_MASK 0xF000
|
#define AD7291_VALUE_MASK GENMASK(11, 0)
|
||||||
#define AD7291_BITS 12
|
|
||||||
#define AD7291_VALUE_MASK 0xFFF
|
/*
|
||||||
#define AD7291_T_VALUE_SIGN 0x400
|
* AD7291 alert register bits
|
||||||
#define AD7291_T_VALUE_FLOAT_OFFSET 2
|
*/
|
||||||
#define AD7291_T_VALUE_FLOAT_MASK 0x2
|
#define AD7291_T_LOW BIT(0)
|
||||||
|
#define AD7291_T_HIGH BIT(1)
|
||||||
|
#define AD7291_T_AVG_LOW BIT(2)
|
||||||
|
#define AD7291_T_AVG_HIGH BIT(3)
|
||||||
|
#define AD7291_V_LOW(x) BIT((x) * 2)
|
||||||
|
#define AD7291_V_HIGH(x) BIT((x) * 2 + 1)
|
||||||
|
|
||||||
#define AD7291_BITS 12
|
|
||||||
|
|
||||||
struct ad7291_chip_info {
|
struct ad7291_chip_info {
|
||||||
struct i2c_client *client;
|
struct i2c_client *client;
|
||||||
|
@ -129,14 +133,14 @@ static irqreturn_t ad7291_event_handler(int irq, void *private)
|
||||||
ad7291_i2c_write(chip, AD7291_COMMAND, command);
|
ad7291_i2c_write(chip, AD7291_COMMAND, command);
|
||||||
|
|
||||||
/* For now treat t_sense and t_sense_average the same */
|
/* For now treat t_sense and t_sense_average the same */
|
||||||
if ((t_status & (1 << 0)) || (t_status & (1 << 2)))
|
if ((t_status & AD7291_T_LOW) || (t_status & AD7291_T_AVG_LOW))
|
||||||
iio_push_event(indio_dev,
|
iio_push_event(indio_dev,
|
||||||
IIO_UNMOD_EVENT_CODE(IIO_TEMP,
|
IIO_UNMOD_EVENT_CODE(IIO_TEMP,
|
||||||
0,
|
0,
|
||||||
IIO_EV_TYPE_THRESH,
|
IIO_EV_TYPE_THRESH,
|
||||||
IIO_EV_DIR_FALLING),
|
IIO_EV_DIR_FALLING),
|
||||||
timestamp);
|
timestamp);
|
||||||
if ((t_status & (1 << 1)) || (t_status & (1 << 3)))
|
if ((t_status & AD7291_T_HIGH) || (t_status & AD7291_T_AVG_HIGH))
|
||||||
iio_push_event(indio_dev,
|
iio_push_event(indio_dev,
|
||||||
IIO_UNMOD_EVENT_CODE(IIO_TEMP,
|
IIO_UNMOD_EVENT_CODE(IIO_TEMP,
|
||||||
0,
|
0,
|
||||||
|
@ -144,18 +148,18 @@ static irqreturn_t ad7291_event_handler(int irq, void *private)
|
||||||
IIO_EV_DIR_RISING),
|
IIO_EV_DIR_RISING),
|
||||||
timestamp);
|
timestamp);
|
||||||
|
|
||||||
for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT*2; i += 2) {
|
for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT; i++) {
|
||||||
if (v_status & (1 << i))
|
if (v_status & AD7291_V_LOW(i))
|
||||||
iio_push_event(indio_dev,
|
iio_push_event(indio_dev,
|
||||||
IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
|
IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
|
||||||
i/2,
|
i,
|
||||||
IIO_EV_TYPE_THRESH,
|
IIO_EV_TYPE_THRESH,
|
||||||
IIO_EV_DIR_FALLING),
|
IIO_EV_DIR_FALLING),
|
||||||
timestamp);
|
timestamp);
|
||||||
if (v_status & (1 << (i + 1)))
|
if (v_status & AD7291_V_HIGH(i))
|
||||||
iio_push_event(indio_dev,
|
iio_push_event(indio_dev,
|
||||||
IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
|
IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
|
||||||
i/2,
|
i,
|
||||||
IIO_EV_TYPE_THRESH,
|
IIO_EV_TYPE_THRESH,
|
||||||
IIO_EV_DIR_RISING),
|
IIO_EV_DIR_RISING),
|
||||||
timestamp);
|
timestamp);
|
||||||
|
@ -165,7 +169,8 @@ static irqreturn_t ad7291_event_handler(int irq, void *private)
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int ad7291_threshold_reg(const struct iio_chan_spec *chan,
|
static unsigned int ad7291_threshold_reg(const struct iio_chan_spec *chan,
|
||||||
enum iio_event_direction dir, enum iio_event_info info)
|
enum iio_event_direction dir,
|
||||||
|
enum iio_event_info info)
|
||||||
{
|
{
|
||||||
unsigned int offset;
|
unsigned int offset;
|
||||||
|
|
||||||
|
@ -174,7 +179,7 @@ static unsigned int ad7291_threshold_reg(const struct iio_chan_spec *chan,
|
||||||
offset = chan->channel;
|
offset = chan->channel;
|
||||||
break;
|
break;
|
||||||
case IIO_TEMP:
|
case IIO_TEMP:
|
||||||
offset = 8;
|
offset = AD7291_VOLTAGE_OFFSET;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -182,14 +187,14 @@ static unsigned int ad7291_threshold_reg(const struct iio_chan_spec *chan,
|
||||||
|
|
||||||
switch (info) {
|
switch (info) {
|
||||||
case IIO_EV_INFO_VALUE:
|
case IIO_EV_INFO_VALUE:
|
||||||
if (dir == IIO_EV_DIR_FALLING)
|
if (dir == IIO_EV_DIR_FALLING)
|
||||||
return AD7291_DATA_HIGH(offset);
|
return AD7291_DATA_HIGH(offset);
|
||||||
else
|
else
|
||||||
return AD7291_DATA_LOW(offset);
|
return AD7291_DATA_LOW(offset);
|
||||||
case IIO_EV_INFO_HYSTERESIS:
|
case IIO_EV_INFO_HYSTERESIS:
|
||||||
return AD7291_HYST(offset);
|
return AD7291_HYST(offset);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -206,7 +211,7 @@ static int ad7291_read_event_value(struct iio_dev *indio_dev,
|
||||||
u16 uval;
|
u16 uval;
|
||||||
|
|
||||||
ret = ad7291_i2c_read(chip, ad7291_threshold_reg(chan, dir, info),
|
ret = ad7291_i2c_read(chip, ad7291_threshold_reg(chan, dir, info),
|
||||||
&uval);
|
&uval);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -237,7 +242,7 @@ static int ad7291_write_event_value(struct iio_dev *indio_dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
return ad7291_i2c_write(chip, ad7291_threshold_reg(chan, dir, info),
|
return ad7291_i2c_write(chip, ad7291_threshold_reg(chan, dir, info),
|
||||||
val);
|
val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ad7291_read_event_config(struct iio_dev *indio_dev,
|
static int ad7291_read_event_config(struct iio_dev *indio_dev,
|
||||||
|
@ -246,15 +251,14 @@ static int ad7291_read_event_config(struct iio_dev *indio_dev,
|
||||||
enum iio_event_direction dir)
|
enum iio_event_direction dir)
|
||||||
{
|
{
|
||||||
struct ad7291_chip_info *chip = iio_priv(indio_dev);
|
struct ad7291_chip_info *chip = iio_priv(indio_dev);
|
||||||
/* To be enabled the channel must simply be on. If any are enabled
|
/*
|
||||||
we are in continuous sampling mode */
|
* To be enabled the channel must simply be on. If any are enabled
|
||||||
|
* we are in continuous sampling mode
|
||||||
|
*/
|
||||||
|
|
||||||
switch (chan->type) {
|
switch (chan->type) {
|
||||||
case IIO_VOLTAGE:
|
case IIO_VOLTAGE:
|
||||||
if (chip->c_mask & (1 << (15 - chan->channel)))
|
return !!(chip->c_mask & BIT(15 - chan->channel));
|
||||||
return 1;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
case IIO_TEMP:
|
case IIO_TEMP:
|
||||||
/* always on */
|
/* always on */
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -336,7 +340,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
|
||||||
}
|
}
|
||||||
/* Enable this channel alone */
|
/* Enable this channel alone */
|
||||||
regval = chip->command & (~AD7291_VOLTAGE_MASK);
|
regval = chip->command & (~AD7291_VOLTAGE_MASK);
|
||||||
regval |= 1 << (15 - chan->channel);
|
regval |= BIT(15 - chan->channel);
|
||||||
ret = ad7291_i2c_write(chip, AD7291_COMMAND, regval);
|
ret = ad7291_i2c_write(chip, AD7291_COMMAND, regval);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
mutex_unlock(&chip->state_lock);
|
mutex_unlock(&chip->state_lock);
|
||||||
|
@ -344,7 +348,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
|
||||||
}
|
}
|
||||||
/* Read voltage */
|
/* Read voltage */
|
||||||
ret = i2c_smbus_read_word_swapped(chip->client,
|
ret = i2c_smbus_read_word_swapped(chip->client,
|
||||||
AD7291_VOLTAGE);
|
AD7291_VOLTAGE);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
mutex_unlock(&chip->state_lock);
|
mutex_unlock(&chip->state_lock);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -355,7 +359,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
|
||||||
case IIO_TEMP:
|
case IIO_TEMP:
|
||||||
/* Assumes tsense bit of command register always set */
|
/* Assumes tsense bit of command register always set */
|
||||||
ret = i2c_smbus_read_word_swapped(chip->client,
|
ret = i2c_smbus_read_word_swapped(chip->client,
|
||||||
AD7291_T_SENSE);
|
AD7291_T_SENSE);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
*val = sign_extend32(ret, 11);
|
*val = sign_extend32(ret, 11);
|
||||||
|
@ -365,7 +369,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
|
||||||
}
|
}
|
||||||
case IIO_CHAN_INFO_AVERAGE_RAW:
|
case IIO_CHAN_INFO_AVERAGE_RAW:
|
||||||
ret = i2c_smbus_read_word_swapped(chip->client,
|
ret = i2c_smbus_read_word_swapped(chip->client,
|
||||||
AD7291_T_AVERAGE);
|
AD7291_T_AVERAGE);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
*val = sign_extend32(ret, 11);
|
*val = sign_extend32(ret, 11);
|
||||||
|
@ -375,6 +379,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
|
||||||
case IIO_VOLTAGE:
|
case IIO_VOLTAGE:
|
||||||
if (chip->reg) {
|
if (chip->reg) {
|
||||||
int vref;
|
int vref;
|
||||||
|
|
||||||
vref = regulator_get_voltage(chip->reg);
|
vref = regulator_get_voltage(chip->reg);
|
||||||
if (vref < 0)
|
if (vref < 0)
|
||||||
return vref;
|
return vref;
|
||||||
|
@ -460,7 +465,7 @@ static const struct iio_info ad7291_info = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ad7291_probe(struct i2c_client *client,
|
static int ad7291_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
struct ad7291_platform_data *pdata = client->dev.platform_data;
|
struct ad7291_platform_data *pdata = client->dev.platform_data;
|
||||||
struct ad7291_chip_info *chip;
|
struct ad7291_chip_info *chip;
|
|
@ -31,17 +31,11 @@ static const struct iio_chan_spec *xadc_event_to_channel(
|
||||||
static void xadc_handle_event(struct iio_dev *indio_dev, unsigned int event)
|
static void xadc_handle_event(struct iio_dev *indio_dev, unsigned int event)
|
||||||
{
|
{
|
||||||
const struct iio_chan_spec *chan;
|
const struct iio_chan_spec *chan;
|
||||||
unsigned int offset;
|
|
||||||
|
|
||||||
/* Temperature threshold error, we don't handle this yet */
|
/* Temperature threshold error, we don't handle this yet */
|
||||||
if (event == 0)
|
if (event == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (event < 4)
|
|
||||||
offset = event;
|
|
||||||
else
|
|
||||||
offset = event + 4;
|
|
||||||
|
|
||||||
chan = xadc_event_to_channel(indio_dev, event);
|
chan = xadc_event_to_channel(indio_dev, event);
|
||||||
|
|
||||||
if (chan->type == IIO_TEMP) {
|
if (chan->type == IIO_TEMP) {
|
||||||
|
|
|
@ -26,12 +26,12 @@
|
||||||
#include <linux/iio/iio.h>
|
#include <linux/iio/iio.h>
|
||||||
#include <linux/iio/sysfs.h>
|
#include <linux/iio/sysfs.h>
|
||||||
|
|
||||||
struct {
|
static struct {
|
||||||
u32 usage_id;
|
u32 usage_id;
|
||||||
int unit; /* 0 for default others from HID sensor spec */
|
int unit; /* 0 for default others from HID sensor spec */
|
||||||
int scale_val0; /* scale, whole number */
|
int scale_val0; /* scale, whole number */
|
||||||
int scale_val1; /* scale, fraction in micros */
|
int scale_val1; /* scale, fraction in micros */
|
||||||
} static unit_conversion[] = {
|
} unit_conversion[] = {
|
||||||
{HID_USAGE_SENSOR_ACCEL_3D, 0, 9, 806650},
|
{HID_USAGE_SENSOR_ACCEL_3D, 0, 9, 806650},
|
||||||
{HID_USAGE_SENSOR_ACCEL_3D,
|
{HID_USAGE_SENSOR_ACCEL_3D,
|
||||||
HID_USAGE_SENSOR_UNITS_METERS_PER_SEC_SQRD, 1, 0},
|
HID_USAGE_SENSOR_UNITS_METERS_PER_SEC_SQRD, 1, 0},
|
||||||
|
@ -343,6 +343,7 @@ int hid_sensor_format_scale(u32 usage_id,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(hid_sensor_format_scale);
|
EXPORT_SYMBOL(hid_sensor_format_scale);
|
||||||
|
|
||||||
|
static
|
||||||
int hid_sensor_get_reporting_interval(struct hid_sensor_hub_device *hsdev,
|
int hid_sensor_get_reporting_interval(struct hid_sensor_hub_device *hsdev,
|
||||||
u32 usage_id,
|
u32 usage_id,
|
||||||
struct hid_sensor_common *st)
|
struct hid_sensor_common *st)
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/iio/iio.h>
|
#include <linux/iio/iio.h>
|
||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
|
#include <linux/of.h>
|
||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
|
|
||||||
#include <linux/iio/common/st_sensors.h>
|
#include <linux/iio/common/st_sensors.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -265,14 +265,47 @@ static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev,
|
||||||
|
struct st_sensors_platform_data *defdata)
|
||||||
|
{
|
||||||
|
struct st_sensors_platform_data *pdata;
|
||||||
|
struct device_node *np = dev->of_node;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
if (!np)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
|
||||||
|
if (!of_property_read_u32(np, "st,drdy-int-pin", &val) && (val <= 2))
|
||||||
|
pdata->drdy_int_pin = (u8) val;
|
||||||
|
else
|
||||||
|
pdata->drdy_int_pin = defdata ? defdata->drdy_int_pin : 1;
|
||||||
|
|
||||||
|
return pdata;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev,
|
||||||
|
struct st_sensors_platform_data *defdata)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int st_sensors_init_sensor(struct iio_dev *indio_dev,
|
int st_sensors_init_sensor(struct iio_dev *indio_dev,
|
||||||
struct st_sensors_platform_data *pdata)
|
struct st_sensors_platform_data *pdata)
|
||||||
{
|
{
|
||||||
struct st_sensor_data *sdata = iio_priv(indio_dev);
|
struct st_sensor_data *sdata = iio_priv(indio_dev);
|
||||||
|
struct st_sensors_platform_data *of_pdata;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
mutex_init(&sdata->tb.buf_lock);
|
mutex_init(&sdata->tb.buf_lock);
|
||||||
|
|
||||||
|
/* If OF/DT pdata exists, it will take precedence of anything else */
|
||||||
|
of_pdata = st_sensors_of_probe(indio_dev->dev.parent, pdata);
|
||||||
|
if (of_pdata)
|
||||||
|
pdata = of_pdata;
|
||||||
|
|
||||||
if (pdata)
|
if (pdata)
|
||||||
err = st_sensors_set_drdy_int_pin(indio_dev, pdata);
|
err = st_sensors_set_drdy_int_pin(indio_dev, pdata);
|
||||||
|
|
||||||
|
@ -463,35 +496,6 @@ int st_sensors_check_device_support(struct iio_dev *indio_dev,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(st_sensors_check_device_support);
|
EXPORT_SYMBOL(st_sensors_check_device_support);
|
||||||
|
|
||||||
ssize_t st_sensors_sysfs_get_sampling_frequency(struct device *dev,
|
|
||||||
struct device_attribute *attr, char *buf)
|
|
||||||
{
|
|
||||||
struct st_sensor_data *adata = iio_priv(dev_get_drvdata(dev));
|
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", adata->odr);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(st_sensors_sysfs_get_sampling_frequency);
|
|
||||||
|
|
||||||
ssize_t st_sensors_sysfs_set_sampling_frequency(struct device *dev,
|
|
||||||
struct device_attribute *attr, const char *buf, size_t size)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
unsigned int odr;
|
|
||||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
|
||||||
|
|
||||||
err = kstrtoint(buf, 10, &odr);
|
|
||||||
if (err < 0)
|
|
||||||
goto conversion_error;
|
|
||||||
|
|
||||||
mutex_lock(&indio_dev->mlock);
|
|
||||||
err = st_sensors_set_odr(indio_dev, odr);
|
|
||||||
mutex_unlock(&indio_dev->mlock);
|
|
||||||
|
|
||||||
conversion_error:
|
|
||||||
return err < 0 ? err : size;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(st_sensors_sysfs_set_sampling_frequency);
|
|
||||||
|
|
||||||
ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev,
|
ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/iio/iio.h>
|
#include <linux/iio/iio.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
|
|
||||||
#include <linux/iio/common/st_sensors_i2c.h>
|
#include <linux/iio/common/st_sensors_i2c.h>
|
||||||
|
|
||||||
|
@ -76,6 +77,35 @@ void st_sensors_i2c_configure(struct iio_dev *indio_dev,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(st_sensors_i2c_configure);
|
EXPORT_SYMBOL(st_sensors_i2c_configure);
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
/**
|
||||||
|
* st_sensors_of_i2c_probe() - device tree probe for ST I2C sensors
|
||||||
|
* @client: the I2C client device for the sensor
|
||||||
|
* @match: the OF match table for the device, containing compatible strings
|
||||||
|
* but also a .data field with the corresponding internal kernel name
|
||||||
|
* used by this sensor.
|
||||||
|
*
|
||||||
|
* In effect this function matches a compatible string to an internal kernel
|
||||||
|
* name for a certain sensor device, so that the rest of the autodetection can
|
||||||
|
* rely on that name from this point on. I2C client devices will be renamed
|
||||||
|
* to match the internal kernel convention.
|
||||||
|
*/
|
||||||
|
void st_sensors_of_i2c_probe(struct i2c_client *client,
|
||||||
|
const struct of_device_id *match)
|
||||||
|
{
|
||||||
|
const struct of_device_id *of_id;
|
||||||
|
|
||||||
|
of_id = of_match_device(match, &client->dev);
|
||||||
|
if (!of_id)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* The name from the OF match takes precedence if present */
|
||||||
|
strncpy(client->name, of_id->data, sizeof(client->name));
|
||||||
|
client->name[sizeof(client->name) - 1] = '\0';
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(st_sensors_of_i2c_probe);
|
||||||
|
#endif
|
||||||
|
|
||||||
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
|
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
|
||||||
MODULE_DESCRIPTION("STMicroelectronics ST-sensors i2c driver");
|
MODULE_DESCRIPTION("STMicroelectronics ST-sensors i2c driver");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
|
|
@ -125,7 +125,6 @@ static int ad5504_write_raw(struct iio_dev *indio_dev,
|
||||||
long mask)
|
long mask)
|
||||||
{
|
{
|
||||||
struct ad5504_state *st = iio_priv(indio_dev);
|
struct ad5504_state *st = iio_priv(indio_dev);
|
||||||
int ret;
|
|
||||||
|
|
||||||
switch (mask) {
|
switch (mask) {
|
||||||
case IIO_CHAN_INFO_RAW:
|
case IIO_CHAN_INFO_RAW:
|
||||||
|
@ -134,10 +133,8 @@ static int ad5504_write_raw(struct iio_dev *indio_dev,
|
||||||
|
|
||||||
return ad5504_spi_write(st, chan->address, val);
|
return ad5504_spi_write(st, chan->address, val);
|
||||||
default:
|
default:
|
||||||
ret = -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char * const ad5504_powerdown_modes[] = {
|
static const char * const ad5504_powerdown_modes[] = {
|
||||||
|
|
|
@ -67,7 +67,6 @@ static int ad5624r_write_raw(struct iio_dev *indio_dev,
|
||||||
long mask)
|
long mask)
|
||||||
{
|
{
|
||||||
struct ad5624r_state *st = iio_priv(indio_dev);
|
struct ad5624r_state *st = iio_priv(indio_dev);
|
||||||
int ret;
|
|
||||||
|
|
||||||
switch (mask) {
|
switch (mask) {
|
||||||
case IIO_CHAN_INFO_RAW:
|
case IIO_CHAN_INFO_RAW:
|
||||||
|
@ -79,10 +78,8 @@ static int ad5624r_write_raw(struct iio_dev *indio_dev,
|
||||||
chan->address, val,
|
chan->address, val,
|
||||||
chan->scan_type.shift);
|
chan->scan_type.shift);
|
||||||
default:
|
default:
|
||||||
ret = -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char * const ad5624r_powerdown_modes[] = {
|
static const char * const ad5624r_powerdown_modes[] = {
|
||||||
|
|
|
@ -313,7 +313,7 @@ static int ad5686_probe(struct spi_device *spi)
|
||||||
{
|
{
|
||||||
struct ad5686_state *st;
|
struct ad5686_state *st;
|
||||||
struct iio_dev *indio_dev;
|
struct iio_dev *indio_dev;
|
||||||
int ret, regdone = 0, voltage_uv = 0;
|
int ret, voltage_uv = 0;
|
||||||
|
|
||||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||||
if (indio_dev == NULL)
|
if (indio_dev == NULL)
|
||||||
|
@ -355,7 +355,6 @@ static int ad5686_probe(struct spi_device *spi)
|
||||||
indio_dev->channels = st->chip_info->channel;
|
indio_dev->channels = st->chip_info->channel;
|
||||||
indio_dev->num_channels = AD5686_DAC_CHANNELS;
|
indio_dev->num_channels = AD5686_DAC_CHANNELS;
|
||||||
|
|
||||||
regdone = 1;
|
|
||||||
ret = ad5686_spi_write(st, AD5686_CMD_INTERNAL_REFER_SETUP, 0,
|
ret = ad5686_spi_write(st, AD5686_CMD_INTERNAL_REFER_SETUP, 0,
|
||||||
!!voltage_uv, 0);
|
!!voltage_uv, 0);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|
|
@ -101,65 +101,6 @@
|
||||||
#define ADIS16260_SCAN_TEMP 3
|
#define ADIS16260_SCAN_TEMP 3
|
||||||
#define ADIS16260_SCAN_ANGL 4
|
#define ADIS16260_SCAN_ANGL 4
|
||||||
|
|
||||||
static ssize_t adis16260_read_frequency(struct device *dev,
|
|
||||||
struct device_attribute *attr,
|
|
||||||
char *buf)
|
|
||||||
{
|
|
||||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
|
||||||
struct adis *adis = iio_priv(indio_dev);
|
|
||||||
int ret, len = 0;
|
|
||||||
u16 t;
|
|
||||||
int sps;
|
|
||||||
ret = adis_read_reg_16(adis, ADIS16260_SMPL_PRD, &t);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (spi_get_device_id(adis->spi)->driver_data) /* If an adis16251 */
|
|
||||||
sps = (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 8 : 256;
|
|
||||||
else
|
|
||||||
sps = (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 66 : 2048;
|
|
||||||
sps /= (t & ADIS16260_SMPL_PRD_DIV_MASK) + 1;
|
|
||||||
len = sprintf(buf, "%d\n", sps);
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t adis16260_write_frequency(struct device *dev,
|
|
||||||
struct device_attribute *attr,
|
|
||||||
const char *buf,
|
|
||||||
size_t len)
|
|
||||||
{
|
|
||||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
|
||||||
struct adis *adis = iio_priv(indio_dev);
|
|
||||||
unsigned int val;
|
|
||||||
int ret;
|
|
||||||
u8 t;
|
|
||||||
|
|
||||||
ret = kstrtouint(buf, 10, &val);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
mutex_lock(&indio_dev->mlock);
|
|
||||||
if (spi_get_device_id(adis->spi)->driver_data)
|
|
||||||
t = 256 / val;
|
|
||||||
else
|
|
||||||
t = 2048 / val;
|
|
||||||
|
|
||||||
if (t > ADIS16260_SMPL_PRD_DIV_MASK)
|
|
||||||
t = ADIS16260_SMPL_PRD_DIV_MASK;
|
|
||||||
else if (t > 0)
|
|
||||||
t--;
|
|
||||||
|
|
||||||
if (t >= 0x0A)
|
|
||||||
adis->spi->max_speed_hz = ADIS16260_SPI_SLOW;
|
|
||||||
else
|
|
||||||
adis->spi->max_speed_hz = ADIS16260_SPI_FAST;
|
|
||||||
ret = adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t);
|
|
||||||
|
|
||||||
mutex_unlock(&indio_dev->mlock);
|
|
||||||
|
|
||||||
return ret ? ret : len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Power down the device */
|
/* Power down the device */
|
||||||
static int adis16260_stop_device(struct iio_dev *indio_dev)
|
static int adis16260_stop_device(struct iio_dev *indio_dev)
|
||||||
{
|
{
|
||||||
|
@ -174,18 +115,19 @@ static int adis16260_stop_device(struct iio_dev *indio_dev)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
|
|
||||||
adis16260_read_frequency,
|
|
||||||
adis16260_write_frequency);
|
|
||||||
|
|
||||||
static const struct iio_chan_spec adis16260_channels[] = {
|
static const struct iio_chan_spec adis16260_channels[] = {
|
||||||
ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,
|
ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,
|
||||||
BIT(IIO_CHAN_INFO_CALIBBIAS) |
|
BIT(IIO_CHAN_INFO_CALIBBIAS) |
|
||||||
BIT(IIO_CHAN_INFO_CALIBSCALE), 14),
|
BIT(IIO_CHAN_INFO_CALIBSCALE),
|
||||||
ADIS_INCLI_CHAN(X, ADIS16260_ANGL_OUT, ADIS16260_SCAN_ANGL, 0, 14),
|
BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),
|
||||||
ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP, 12),
|
ADIS_INCLI_CHAN(X, ADIS16260_ANGL_OUT, ADIS16260_SCAN_ANGL, 0,
|
||||||
ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY, 12),
|
BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),
|
||||||
ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC, 12),
|
ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP,
|
||||||
|
BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
|
||||||
|
ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY,
|
||||||
|
BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
|
||||||
|
ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC,
|
||||||
|
BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
|
||||||
IIO_CHAN_SOFT_TIMESTAMP(5),
|
IIO_CHAN_SOFT_TIMESTAMP(5),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -258,6 +200,20 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
|
||||||
|
|
||||||
*val = val16;
|
*val = val16;
|
||||||
return IIO_VAL_INT;
|
return IIO_VAL_INT;
|
||||||
|
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||||
|
ret = adis_read_reg_16(adis, ADIS16260_SMPL_PRD, &val16);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (spi_get_device_id(adis->spi)->driver_data)
|
||||||
|
/* If an adis16251 */
|
||||||
|
*val = (val16 & ADIS16260_SMPL_PRD_TIME_BASE) ?
|
||||||
|
8 : 256;
|
||||||
|
else
|
||||||
|
*val = (val16 & ADIS16260_SMPL_PRD_TIME_BASE) ?
|
||||||
|
66 : 2048;
|
||||||
|
*val /= (val16 & ADIS16260_SMPL_PRD_DIV_MASK) + 1;
|
||||||
|
return IIO_VAL_INT;
|
||||||
}
|
}
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -269,7 +225,9 @@ static int adis16260_write_raw(struct iio_dev *indio_dev,
|
||||||
long mask)
|
long mask)
|
||||||
{
|
{
|
||||||
struct adis *adis = iio_priv(indio_dev);
|
struct adis *adis = iio_priv(indio_dev);
|
||||||
|
int ret;
|
||||||
u8 addr;
|
u8 addr;
|
||||||
|
u8 t;
|
||||||
|
|
||||||
switch (mask) {
|
switch (mask) {
|
||||||
case IIO_CHAN_INFO_CALIBBIAS:
|
case IIO_CHAN_INFO_CALIBBIAS:
|
||||||
|
@ -284,21 +242,31 @@ static int adis16260_write_raw(struct iio_dev *indio_dev,
|
||||||
|
|
||||||
addr = adis16260_addresses[chan->scan_index][1];
|
addr = adis16260_addresses[chan->scan_index][1];
|
||||||
return adis_write_reg_16(adis, addr, val);
|
return adis_write_reg_16(adis, addr, val);
|
||||||
|
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||||
|
mutex_lock(&indio_dev->mlock);
|
||||||
|
if (spi_get_device_id(adis->spi)->driver_data)
|
||||||
|
t = 256 / val;
|
||||||
|
else
|
||||||
|
t = 2048 / val;
|
||||||
|
|
||||||
|
if (t > ADIS16260_SMPL_PRD_DIV_MASK)
|
||||||
|
t = ADIS16260_SMPL_PRD_DIV_MASK;
|
||||||
|
else if (t > 0)
|
||||||
|
t--;
|
||||||
|
|
||||||
|
if (t >= 0x0A)
|
||||||
|
adis->spi->max_speed_hz = ADIS16260_SPI_SLOW;
|
||||||
|
else
|
||||||
|
adis->spi->max_speed_hz = ADIS16260_SPI_FAST;
|
||||||
|
ret = adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t);
|
||||||
|
|
||||||
|
mutex_unlock(&indio_dev->mlock);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct attribute *adis16260_attributes[] = {
|
|
||||||
&iio_dev_attr_sampling_frequency.dev_attr.attr,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct attribute_group adis16260_attribute_group = {
|
|
||||||
.attrs = adis16260_attributes,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct iio_info adis16260_info = {
|
static const struct iio_info adis16260_info = {
|
||||||
.attrs = &adis16260_attribute_group,
|
|
||||||
.read_raw = &adis16260_read_raw,
|
.read_raw = &adis16260_read_raw,
|
||||||
.write_raw = &adis16260_write_raw,
|
.write_raw = &adis16260_write_raw,
|
||||||
.update_scan_mode = adis_update_scan_mode,
|
.update_scan_mode = adis_update_scan_mode,
|
||||||
|
|
|
@ -90,6 +90,7 @@ static int itg3200_read_raw(struct iio_dev *indio_dev,
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
u8 reg;
|
u8 reg;
|
||||||
|
u8 regval;
|
||||||
|
|
||||||
switch (info) {
|
switch (info) {
|
||||||
case IIO_CHAN_INFO_RAW:
|
case IIO_CHAN_INFO_RAW:
|
||||||
|
@ -107,65 +108,60 @@ static int itg3200_read_raw(struct iio_dev *indio_dev,
|
||||||
/* Only the temperature channel has an offset */
|
/* Only the temperature channel has an offset */
|
||||||
*val = 23000;
|
*val = 23000;
|
||||||
return IIO_VAL_INT;
|
return IIO_VAL_INT;
|
||||||
|
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||||
|
ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_DLPF, ®val);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
*val = (regval & ITG3200_DLPF_CFG_MASK) ? 1000 : 8000;
|
||||||
|
|
||||||
|
ret = itg3200_read_reg_8(indio_dev,
|
||||||
|
ITG3200_REG_SAMPLE_RATE_DIV,
|
||||||
|
®val);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
*val /= regval + 1;
|
||||||
|
return IIO_VAL_INT;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t itg3200_read_frequency(struct device *dev,
|
static int itg3200_write_raw(struct iio_dev *indio_dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct iio_chan_spec const *chan,
|
||||||
|
int val,
|
||||||
|
int val2,
|
||||||
|
long mask)
|
||||||
{
|
{
|
||||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
|
||||||
int ret, sps;
|
|
||||||
u8 val;
|
|
||||||
|
|
||||||
ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_DLPF, &val);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
sps = (val & ITG3200_DLPF_CFG_MASK) ? 1000 : 8000;
|
|
||||||
|
|
||||||
ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_SAMPLE_RATE_DIV, &val);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
sps /= val + 1;
|
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", sps);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t itg3200_write_frequency(struct device *dev,
|
|
||||||
struct device_attribute *attr,
|
|
||||||
const char *buf,
|
|
||||||
size_t len)
|
|
||||||
{
|
|
||||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
|
||||||
unsigned val;
|
|
||||||
int ret;
|
int ret;
|
||||||
u8 t;
|
u8 t;
|
||||||
|
|
||||||
ret = kstrtouint(buf, 10, &val);
|
switch (mask) {
|
||||||
if (ret)
|
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||||
return ret;
|
if (val == 0 || val2 != 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&indio_dev->mlock);
|
mutex_lock(&indio_dev->mlock);
|
||||||
|
|
||||||
ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_DLPF, &t);
|
ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_DLPF, &t);
|
||||||
if (ret)
|
if (ret) {
|
||||||
goto err_ret;
|
mutex_unlock(&indio_dev->mlock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
t = ((t & ITG3200_DLPF_CFG_MASK) ? 1000u : 8000u) / val - 1;
|
||||||
|
|
||||||
if (val == 0) {
|
ret = itg3200_write_reg_8(indio_dev,
|
||||||
ret = -EINVAL;
|
ITG3200_REG_SAMPLE_RATE_DIV,
|
||||||
goto err_ret;
|
t);
|
||||||
|
|
||||||
|
mutex_unlock(&indio_dev->mlock);
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
t = ((t & ITG3200_DLPF_CFG_MASK) ? 1000u : 8000u) / val - 1;
|
|
||||||
|
|
||||||
ret = itg3200_write_reg_8(indio_dev, ITG3200_REG_SAMPLE_RATE_DIV, t);
|
|
||||||
|
|
||||||
err_ret:
|
|
||||||
mutex_unlock(&indio_dev->mlock);
|
|
||||||
|
|
||||||
return ret ? ret : len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -255,6 +251,7 @@ static int itg3200_initial_setup(struct iio_dev *indio_dev)
|
||||||
.channel2 = IIO_MOD_ ## _mod, \
|
.channel2 = IIO_MOD_ ## _mod, \
|
||||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
|
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
|
||||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
|
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
|
||||||
|
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
|
||||||
.address = ITG3200_REG_GYRO_ ## _mod ## OUT_H, \
|
.address = ITG3200_REG_GYRO_ ## _mod ## OUT_H, \
|
||||||
.scan_index = ITG3200_SCAN_GYRO_ ## _mod, \
|
.scan_index = ITG3200_SCAN_GYRO_ ## _mod, \
|
||||||
.scan_type = ITG3200_ST, \
|
.scan_type = ITG3200_ST, \
|
||||||
|
@ -267,6 +264,7 @@ static const struct iio_chan_spec itg3200_channels[] = {
|
||||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
||||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
|
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
|
||||||
BIT(IIO_CHAN_INFO_SCALE),
|
BIT(IIO_CHAN_INFO_SCALE),
|
||||||
|
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
|
||||||
.address = ITG3200_REG_TEMP_OUT_H,
|
.address = ITG3200_REG_TEMP_OUT_H,
|
||||||
.scan_index = ITG3200_SCAN_TEMP,
|
.scan_index = ITG3200_SCAN_TEMP,
|
||||||
.scan_type = ITG3200_ST,
|
.scan_type = ITG3200_ST,
|
||||||
|
@ -277,22 +275,9 @@ static const struct iio_chan_spec itg3200_channels[] = {
|
||||||
IIO_CHAN_SOFT_TIMESTAMP(ITG3200_SCAN_ELEMENTS),
|
IIO_CHAN_SOFT_TIMESTAMP(ITG3200_SCAN_ELEMENTS),
|
||||||
};
|
};
|
||||||
|
|
||||||
/* IIO device attributes */
|
|
||||||
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, itg3200_read_frequency,
|
|
||||||
itg3200_write_frequency);
|
|
||||||
|
|
||||||
static struct attribute *itg3200_attributes[] = {
|
|
||||||
&iio_dev_attr_sampling_frequency.dev_attr.attr,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct attribute_group itg3200_attribute_group = {
|
|
||||||
.attrs = itg3200_attributes,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct iio_info itg3200_info = {
|
static const struct iio_info itg3200_info = {
|
||||||
.attrs = &itg3200_attribute_group,
|
|
||||||
.read_raw = &itg3200_read_raw,
|
.read_raw = &itg3200_read_raw,
|
||||||
|
.write_raw = &itg3200_write_raw,
|
||||||
.driver_module = THIS_MODULE,
|
.driver_module = THIS_MODULE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -245,6 +245,9 @@ static int st_gyro_read_raw(struct iio_dev *indio_dev,
|
||||||
*val = 0;
|
*val = 0;
|
||||||
*val2 = gdata->current_fullscale->gain;
|
*val2 = gdata->current_fullscale->gain;
|
||||||
return IIO_VAL_INT_PLUS_MICRO;
|
return IIO_VAL_INT_PLUS_MICRO;
|
||||||
|
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||||
|
*val = gdata->odr;
|
||||||
|
return IIO_VAL_INT;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -262,6 +265,13 @@ static int st_gyro_write_raw(struct iio_dev *indio_dev,
|
||||||
case IIO_CHAN_INFO_SCALE:
|
case IIO_CHAN_INFO_SCALE:
|
||||||
err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
|
err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
|
||||||
break;
|
break;
|
||||||
|
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||||
|
if (val2)
|
||||||
|
return -EINVAL;
|
||||||
|
mutex_lock(&indio_dev->mlock);
|
||||||
|
err = st_sensors_set_odr(indio_dev, val);
|
||||||
|
mutex_unlock(&indio_dev->mlock);
|
||||||
|
return err;
|
||||||
default:
|
default:
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -269,14 +279,12 @@ static int st_gyro_write_raw(struct iio_dev *indio_dev,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
|
|
||||||
static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
|
static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
|
||||||
static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_anglvel_scale_available);
|
static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_anglvel_scale_available);
|
||||||
|
|
||||||
static struct attribute *st_gyro_attributes[] = {
|
static struct attribute *st_gyro_attributes[] = {
|
||||||
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
|
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
|
||||||
&iio_dev_attr_in_anglvel_scale_available.dev_attr.attr,
|
&iio_dev_attr_in_anglvel_scale_available.dev_attr.attr,
|
||||||
&iio_dev_attr_sampling_frequency.dev_attr.attr,
|
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,43 @@
|
||||||
#include <linux/iio/common/st_sensors_i2c.h>
|
#include <linux/iio/common/st_sensors_i2c.h>
|
||||||
#include "st_gyro.h"
|
#include "st_gyro.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
static const struct of_device_id st_gyro_of_match[] = {
|
||||||
|
{
|
||||||
|
.compatible = "st,l3g4200d-gyro",
|
||||||
|
.data = L3G4200D_GYRO_DEV_NAME,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "st,lsm330d-gyro",
|
||||||
|
.data = LSM330D_GYRO_DEV_NAME,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "st,lsm330dl-gyro",
|
||||||
|
.data = LSM330DL_GYRO_DEV_NAME,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "st,lsm330dlc-gyro",
|
||||||
|
.data = LSM330DLC_GYRO_DEV_NAME,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "st,l3gd20-gyro",
|
||||||
|
.data = L3GD20_GYRO_DEV_NAME,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "st,l3g4is-gyro",
|
||||||
|
.data = L3G4IS_GYRO_DEV_NAME,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "st,lsm330-gyro",
|
||||||
|
.data = LSM330_GYRO_DEV_NAME,
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, st_gyro_of_match);
|
||||||
|
#else
|
||||||
|
#define st_gyro_of_match NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
static int st_gyro_i2c_probe(struct i2c_client *client,
|
static int st_gyro_i2c_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
|
@ -31,6 +68,7 @@ static int st_gyro_i2c_probe(struct i2c_client *client,
|
||||||
|
|
||||||
gdata = iio_priv(indio_dev);
|
gdata = iio_priv(indio_dev);
|
||||||
gdata->dev = &client->dev;
|
gdata->dev = &client->dev;
|
||||||
|
st_sensors_of_i2c_probe(client, st_gyro_of_match);
|
||||||
|
|
||||||
st_sensors_i2c_configure(indio_dev, client, gdata);
|
st_sensors_i2c_configure(indio_dev, client, gdata);
|
||||||
|
|
||||||
|
@ -65,6 +103,7 @@ static struct i2c_driver st_gyro_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.name = "st-gyro-i2c",
|
.name = "st-gyro-i2c",
|
||||||
|
.of_match_table = of_match_ptr(st_gyro_of_match),
|
||||||
},
|
},
|
||||||
.probe = st_gyro_i2c_probe,
|
.probe = st_gyro_i2c_probe,
|
||||||
.remove = st_gyro_i2c_remove,
|
.remove = st_gyro_i2c_remove,
|
||||||
|
|
|
@ -18,7 +18,7 @@ int adis16400_update_scan_mode(struct iio_dev *indio_dev,
|
||||||
{
|
{
|
||||||
struct adis16400_state *st = iio_priv(indio_dev);
|
struct adis16400_state *st = iio_priv(indio_dev);
|
||||||
struct adis *adis = &st->adis;
|
struct adis *adis = &st->adis;
|
||||||
uint16_t *tx, *rx;
|
uint16_t *tx;
|
||||||
|
|
||||||
if (st->variant->flags & ADIS16400_NO_BURST)
|
if (st->variant->flags & ADIS16400_NO_BURST)
|
||||||
return adis_update_scan_mode(indio_dev, scan_mask);
|
return adis_update_scan_mode(indio_dev, scan_mask);
|
||||||
|
@ -35,7 +35,6 @@ int adis16400_update_scan_mode(struct iio_dev *indio_dev,
|
||||||
if (!adis->buffer)
|
if (!adis->buffer)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
rx = adis->buffer;
|
|
||||||
tx = adis->buffer + indio_dev->scan_bytes;
|
tx = adis->buffer + indio_dev->scan_bytes;
|
||||||
|
|
||||||
tx[0] = ADIS_READ_REG(ADIS16400_GLOB_CMD);
|
tx[0] = ADIS_READ_REG(ADIS16400_GLOB_CMD);
|
||||||
|
|
|
@ -214,21 +214,6 @@ static int adis16400_set_freq(struct adis16400_state *st, unsigned int freq)
|
||||||
return adis_write_reg_8(&st->adis, ADIS16400_SMPL_PRD, val);
|
return adis_write_reg_8(&st->adis, ADIS16400_SMPL_PRD, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t adis16400_read_frequency(struct device *dev,
|
|
||||||
struct device_attribute *attr,
|
|
||||||
char *buf)
|
|
||||||
{
|
|
||||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
|
||||||
struct adis16400_state *st = iio_priv(indio_dev);
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = st->variant->get_freq(st);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return sprintf(buf, "%d.%.3d\n", ret / 1000, ret % 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const unsigned adis16400_3db_divisors[] = {
|
static const unsigned adis16400_3db_divisors[] = {
|
||||||
[0] = 2, /* Special case */
|
[0] = 2, /* Special case */
|
||||||
[1] = 6,
|
[1] = 6,
|
||||||
|
@ -260,30 +245,6 @@ static int adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t adis16400_write_frequency(struct device *dev,
|
|
||||||
struct device_attribute *attr, const char *buf, size_t len)
|
|
||||||
{
|
|
||||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
|
||||||
struct adis16400_state *st = iio_priv(indio_dev);
|
|
||||||
int i, f, val;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = iio_str_to_fixpoint(buf, 100, &i, &f);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
val = i * 1000 + f;
|
|
||||||
|
|
||||||
if (val <= 0)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
mutex_lock(&indio_dev->mlock);
|
|
||||||
st->variant->set_freq(st, val);
|
|
||||||
mutex_unlock(&indio_dev->mlock);
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Power down the device */
|
/* Power down the device */
|
||||||
static int adis16400_stop_device(struct iio_dev *indio_dev)
|
static int adis16400_stop_device(struct iio_dev *indio_dev)
|
||||||
{
|
{
|
||||||
|
@ -350,10 +311,6 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
|
|
||||||
adis16400_read_frequency,
|
|
||||||
adis16400_write_frequency);
|
|
||||||
|
|
||||||
static const uint8_t adis16400_addresses[] = {
|
static const uint8_t adis16400_addresses[] = {
|
||||||
[ADIS16400_SCAN_GYRO_X] = ADIS16400_XGYRO_OFF,
|
[ADIS16400_SCAN_GYRO_X] = ADIS16400_XGYRO_OFF,
|
||||||
[ADIS16400_SCAN_GYRO_Y] = ADIS16400_YGYRO_OFF,
|
[ADIS16400_SCAN_GYRO_Y] = ADIS16400_YGYRO_OFF,
|
||||||
|
@ -394,6 +351,16 @@ static int adis16400_write_raw(struct iio_dev *indio_dev,
|
||||||
val * 1000 + val2 / 1000);
|
val * 1000 + val2 / 1000);
|
||||||
mutex_unlock(&indio_dev->mlock);
|
mutex_unlock(&indio_dev->mlock);
|
||||||
return ret;
|
return ret;
|
||||||
|
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||||
|
sps = val * 1000 + val2 / 1000;
|
||||||
|
|
||||||
|
if (sps <= 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
mutex_lock(&indio_dev->mlock);
|
||||||
|
ret = st->variant->set_freq(st, sps);
|
||||||
|
mutex_unlock(&indio_dev->mlock);
|
||||||
|
return ret;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -474,6 +441,13 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
return IIO_VAL_INT_PLUS_MICRO;
|
return IIO_VAL_INT_PLUS_MICRO;
|
||||||
|
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||||
|
ret = st->variant->get_freq(st);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
*val = ret / 1000;
|
||||||
|
*val2 = (ret % 1000) * 1000;
|
||||||
|
return IIO_VAL_INT_PLUS_MICRO;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -486,6 +460,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
|
||||||
.extend_name = name, \
|
.extend_name = name, \
|
||||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||||
BIT(IIO_CHAN_INFO_SCALE), \
|
BIT(IIO_CHAN_INFO_SCALE), \
|
||||||
|
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
|
||||||
.address = (addr), \
|
.address = (addr), \
|
||||||
.scan_index = (si), \
|
.scan_index = (si), \
|
||||||
.scan_type = { \
|
.scan_type = { \
|
||||||
|
@ -511,6 +486,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
|
||||||
BIT(IIO_CHAN_INFO_CALIBBIAS), \
|
BIT(IIO_CHAN_INFO_CALIBBIAS), \
|
||||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
|
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
|
||||||
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
|
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
|
||||||
|
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
|
||||||
.address = addr, \
|
.address = addr, \
|
||||||
.scan_index = ADIS16400_SCAN_GYRO_ ## mod, \
|
.scan_index = ADIS16400_SCAN_GYRO_ ## mod, \
|
||||||
.scan_type = { \
|
.scan_type = { \
|
||||||
|
@ -530,6 +506,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
|
||||||
BIT(IIO_CHAN_INFO_CALIBBIAS), \
|
BIT(IIO_CHAN_INFO_CALIBBIAS), \
|
||||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
|
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
|
||||||
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
|
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
|
||||||
|
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
|
||||||
.address = (addr), \
|
.address = (addr), \
|
||||||
.scan_index = ADIS16400_SCAN_ACC_ ## mod, \
|
.scan_index = ADIS16400_SCAN_ACC_ ## mod, \
|
||||||
.scan_type = { \
|
.scan_type = { \
|
||||||
|
@ -548,6 +525,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
|
||||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
|
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
|
||||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
|
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
|
||||||
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
|
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
|
||||||
|
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
|
||||||
.address = (addr), \
|
.address = (addr), \
|
||||||
.scan_index = ADIS16400_SCAN_MAGN_ ## mod, \
|
.scan_index = ADIS16400_SCAN_MAGN_ ## mod, \
|
||||||
.scan_type = { \
|
.scan_type = { \
|
||||||
|
@ -573,6 +551,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
|
||||||
BIT(IIO_CHAN_INFO_SCALE), \
|
BIT(IIO_CHAN_INFO_SCALE), \
|
||||||
.info_mask_shared_by_type = \
|
.info_mask_shared_by_type = \
|
||||||
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
|
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
|
||||||
|
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
|
||||||
.address = (addr), \
|
.address = (addr), \
|
||||||
.scan_index = ADIS16350_SCAN_TEMP_ ## mod, \
|
.scan_index = ADIS16350_SCAN_TEMP_ ## mod, \
|
||||||
.scan_type = { \
|
.scan_type = { \
|
||||||
|
@ -591,6 +570,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
|
||||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||||
BIT(IIO_CHAN_INFO_OFFSET) | \
|
BIT(IIO_CHAN_INFO_OFFSET) | \
|
||||||
BIT(IIO_CHAN_INFO_SCALE), \
|
BIT(IIO_CHAN_INFO_SCALE), \
|
||||||
|
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
|
||||||
.address = (addr), \
|
.address = (addr), \
|
||||||
.scan_index = ADIS16350_SCAN_TEMP_X, \
|
.scan_index = ADIS16350_SCAN_TEMP_X, \
|
||||||
.scan_type = { \
|
.scan_type = { \
|
||||||
|
@ -608,6 +588,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
|
||||||
.channel2 = IIO_MOD_ ## mod, \
|
.channel2 = IIO_MOD_ ## mod, \
|
||||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
|
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
|
||||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
|
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
|
||||||
|
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
|
||||||
.address = (addr), \
|
.address = (addr), \
|
||||||
.scan_index = ADIS16300_SCAN_INCLI_ ## mod, \
|
.scan_index = ADIS16300_SCAN_INCLI_ ## mod, \
|
||||||
.scan_type = { \
|
.scan_type = { \
|
||||||
|
@ -649,6 +630,7 @@ static const struct iio_chan_spec adis16448_channels[] = {
|
||||||
.type = IIO_PRESSURE,
|
.type = IIO_PRESSURE,
|
||||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
||||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
|
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
|
||||||
|
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
|
||||||
.address = ADIS16448_BARO_OUT,
|
.address = ADIS16448_BARO_OUT,
|
||||||
.scan_index = ADIS16400_SCAN_BARO,
|
.scan_index = ADIS16400_SCAN_BARO,
|
||||||
.scan_type = {
|
.scan_type = {
|
||||||
|
@ -704,15 +686,6 @@ static const struct iio_chan_spec adis16334_channels[] = {
|
||||||
IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
|
IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attribute *adis16400_attributes[] = {
|
|
||||||
&iio_dev_attr_sampling_frequency.dev_attr.attr,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct attribute_group adis16400_attribute_group = {
|
|
||||||
.attrs = adis16400_attributes,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct adis16400_chip_info adis16400_chips[] = {
|
static struct adis16400_chip_info adis16400_chips[] = {
|
||||||
[ADIS16300] = {
|
[ADIS16300] = {
|
||||||
.channels = adis16300_channels,
|
.channels = adis16300_channels,
|
||||||
|
@ -813,7 +786,6 @@ static const struct iio_info adis16400_info = {
|
||||||
.driver_module = THIS_MODULE,
|
.driver_module = THIS_MODULE,
|
||||||
.read_raw = &adis16400_read_raw,
|
.read_raw = &adis16400_read_raw,
|
||||||
.write_raw = &adis16400_write_raw,
|
.write_raw = &adis16400_write_raw,
|
||||||
.attrs = &adis16400_attribute_group,
|
|
||||||
.update_scan_mode = adis16400_update_scan_mode,
|
.update_scan_mode = adis16400_update_scan_mode,
|
||||||
.debugfs_reg_access = adis_debugfs_reg_access,
|
.debugfs_reg_access = adis_debugfs_reg_access,
|
||||||
};
|
};
|
||||||
|
|
|
@ -257,11 +257,16 @@ static int adis16480_debugfs_init(struct iio_dev *indio_dev)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int adis16480_set_freq(struct adis16480 *st, unsigned int freq)
|
static int adis16480_set_freq(struct iio_dev *indio_dev, int val, int val2)
|
||||||
{
|
{
|
||||||
|
struct adis16480 *st = iio_priv(indio_dev);
|
||||||
unsigned int t;
|
unsigned int t;
|
||||||
|
|
||||||
t = 2460000 / freq;
|
t = val * 1000 + val2 / 1000;
|
||||||
|
if (t <= 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
t = 2460000 / t;
|
||||||
if (t > 2048)
|
if (t > 2048)
|
||||||
t = 2048;
|
t = 2048;
|
||||||
|
|
||||||
|
@ -271,65 +276,24 @@ static int adis16480_set_freq(struct adis16480 *st, unsigned int freq)
|
||||||
return adis_write_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, t);
|
return adis_write_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int adis16480_get_freq(struct adis16480 *st, unsigned int *freq)
|
static int adis16480_get_freq(struct iio_dev *indio_dev, int *val, int *val2)
|
||||||
{
|
{
|
||||||
|
struct adis16480 *st = iio_priv(indio_dev);
|
||||||
uint16_t t;
|
uint16_t t;
|
||||||
int ret;
|
int ret;
|
||||||
|
unsigned freq;
|
||||||
|
|
||||||
ret = adis_read_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, &t);
|
ret = adis_read_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, &t);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
*freq = 2460000 / (t + 1);
|
freq = 2460000 / (t + 1);
|
||||||
|
*val = freq / 1000;
|
||||||
|
*val2 = (freq % 1000) * 1000;
|
||||||
|
|
||||||
return 0;
|
return IIO_VAL_INT_PLUS_MICRO;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t adis16480_read_frequency(struct device *dev,
|
|
||||||
struct device_attribute *attr,
|
|
||||||
char *buf)
|
|
||||||
{
|
|
||||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
|
||||||
struct adis16480 *st = iio_priv(indio_dev);
|
|
||||||
unsigned int freq;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = adis16480_get_freq(st, &freq);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return sprintf(buf, "%d.%.3d\n", freq / 1000, freq % 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t adis16480_write_frequency(struct device *dev,
|
|
||||||
struct device_attribute *attr,
|
|
||||||
const char *buf,
|
|
||||||
size_t len)
|
|
||||||
{
|
|
||||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
|
||||||
struct adis16480 *st = iio_priv(indio_dev);
|
|
||||||
int freq_int, freq_fract;
|
|
||||||
long val;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = iio_str_to_fixpoint(buf, 100, &freq_int, &freq_fract);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
val = freq_int * 1000 + freq_fract;
|
|
||||||
|
|
||||||
if (val <= 0)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
ret = adis16480_set_freq(st, val);
|
|
||||||
|
|
||||||
return ret ? ret : len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
|
|
||||||
adis16480_read_frequency,
|
|
||||||
adis16480_write_frequency);
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ADIS16480_SCAN_GYRO_X,
|
ADIS16480_SCAN_GYRO_X,
|
||||||
ADIS16480_SCAN_GYRO_Y,
|
ADIS16480_SCAN_GYRO_Y,
|
||||||
|
@ -571,6 +535,8 @@ static int adis16480_read_raw(struct iio_dev *indio_dev,
|
||||||
return adis16480_get_calibscale(indio_dev, chan, val);
|
return adis16480_get_calibscale(indio_dev, chan, val);
|
||||||
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
|
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
|
||||||
return adis16480_get_filter_freq(indio_dev, chan, val);
|
return adis16480_get_filter_freq(indio_dev, chan, val);
|
||||||
|
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||||
|
return adis16480_get_freq(indio_dev, val, val2);
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -586,6 +552,9 @@ static int adis16480_write_raw(struct iio_dev *indio_dev,
|
||||||
return adis16480_set_calibscale(indio_dev, chan, val);
|
return adis16480_set_calibscale(indio_dev, chan, val);
|
||||||
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
|
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
|
||||||
return adis16480_set_filter_freq(indio_dev, chan, val);
|
return adis16480_set_filter_freq(indio_dev, chan, val);
|
||||||
|
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||||
|
return adis16480_set_freq(indio_dev, val, val2);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -600,6 +569,7 @@ static int adis16480_write_raw(struct iio_dev *indio_dev,
|
||||||
BIT(IIO_CHAN_INFO_CALIBBIAS) | \
|
BIT(IIO_CHAN_INFO_CALIBBIAS) | \
|
||||||
_info_sep, \
|
_info_sep, \
|
||||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
|
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
|
||||||
|
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
|
||||||
.address = (_address), \
|
.address = (_address), \
|
||||||
.scan_index = (_si), \
|
.scan_index = (_si), \
|
||||||
.scan_type = { \
|
.scan_type = { \
|
||||||
|
@ -638,6 +608,7 @@ static int adis16480_write_raw(struct iio_dev *indio_dev,
|
||||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||||
BIT(IIO_CHAN_INFO_CALIBBIAS) | \
|
BIT(IIO_CHAN_INFO_CALIBBIAS) | \
|
||||||
BIT(IIO_CHAN_INFO_SCALE), \
|
BIT(IIO_CHAN_INFO_SCALE), \
|
||||||
|
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
|
||||||
.address = ADIS16480_REG_BAROM_OUT, \
|
.address = ADIS16480_REG_BAROM_OUT, \
|
||||||
.scan_index = ADIS16480_SCAN_BARO, \
|
.scan_index = ADIS16480_SCAN_BARO, \
|
||||||
.scan_type = { \
|
.scan_type = { \
|
||||||
|
@ -655,6 +626,7 @@ static int adis16480_write_raw(struct iio_dev *indio_dev,
|
||||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||||
BIT(IIO_CHAN_INFO_SCALE) | \
|
BIT(IIO_CHAN_INFO_SCALE) | \
|
||||||
BIT(IIO_CHAN_INFO_OFFSET), \
|
BIT(IIO_CHAN_INFO_OFFSET), \
|
||||||
|
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
|
||||||
.address = ADIS16480_REG_TEMP_OUT, \
|
.address = ADIS16480_REG_TEMP_OUT, \
|
||||||
.scan_index = ADIS16480_SCAN_TEMP, \
|
.scan_index = ADIS16480_SCAN_TEMP, \
|
||||||
.scan_type = { \
|
.scan_type = { \
|
||||||
|
@ -717,17 +689,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attribute *adis16480_attributes[] = {
|
|
||||||
&iio_dev_attr_sampling_frequency.dev_attr.attr,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct attribute_group adis16480_attribute_group = {
|
|
||||||
.attrs = adis16480_attributes,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct iio_info adis16480_info = {
|
static const struct iio_info adis16480_info = {
|
||||||
.attrs = &adis16480_attribute_group,
|
|
||||||
.read_raw = &adis16480_read_raw,
|
.read_raw = &adis16480_read_raw,
|
||||||
.write_raw = &adis16480_write_raw,
|
.write_raw = &adis16480_write_raw,
|
||||||
.update_scan_mode = adis_update_scan_mode,
|
.update_scan_mode = adis_update_scan_mode,
|
||||||
|
|
|
@ -209,6 +209,7 @@ static const char * const iio_ev_info_text[] = {
|
||||||
[IIO_EV_INFO_ENABLE] = "en",
|
[IIO_EV_INFO_ENABLE] = "en",
|
||||||
[IIO_EV_INFO_VALUE] = "value",
|
[IIO_EV_INFO_VALUE] = "value",
|
||||||
[IIO_EV_INFO_HYSTERESIS] = "hysteresis",
|
[IIO_EV_INFO_HYSTERESIS] = "hysteresis",
|
||||||
|
[IIO_EV_INFO_PERIOD] = "period",
|
||||||
};
|
};
|
||||||
|
|
||||||
static enum iio_event_direction iio_ev_attr_dir(struct iio_dev_attr *attr)
|
static enum iio_event_direction iio_ev_attr_dir(struct iio_dev_attr *attr)
|
||||||
|
|
|
@ -62,6 +62,18 @@ config GP2AP020A00F
|
||||||
To compile this driver as a module, choose M here: the
|
To compile this driver as a module, choose M here: the
|
||||||
module will be called gp2ap020a00f.
|
module will be called gp2ap020a00f.
|
||||||
|
|
||||||
|
config ISL29125
|
||||||
|
tristate "Intersil ISL29125 digital color light sensor"
|
||||||
|
depends on I2C
|
||||||
|
select IIO_BUFFER
|
||||||
|
select IIO_TRIGGERED_BUFFER
|
||||||
|
help
|
||||||
|
Say Y here if you want to build a driver for the Intersil ISL29125
|
||||||
|
RGB light sensor for I2C.
|
||||||
|
|
||||||
|
To compile this driver as a module, choose M here: the module will be
|
||||||
|
called isl29125.
|
||||||
|
|
||||||
config HID_SENSOR_ALS
|
config HID_SENSOR_ALS
|
||||||
depends on HID_SENSOR_HUB
|
depends on HID_SENSOR_HUB
|
||||||
select IIO_BUFFER
|
select IIO_BUFFER
|
||||||
|
@ -116,6 +128,18 @@ config LTR501
|
||||||
This driver can also be built as a module. If so, the module
|
This driver can also be built as a module. If so, the module
|
||||||
will be called ltr501.
|
will be called ltr501.
|
||||||
|
|
||||||
|
config TCS3414
|
||||||
|
tristate "TAOS TCS3414 digital color sensor"
|
||||||
|
depends on I2C
|
||||||
|
select IIO_BUFFER
|
||||||
|
select IIO_TRIGGERED_BUFFER
|
||||||
|
help
|
||||||
|
If you say yes here you get support for the TAOS TCS3414
|
||||||
|
family of digital color sensors.
|
||||||
|
|
||||||
|
This driver can also be built as a module. If so, the module
|
||||||
|
will be called tcs3414.
|
||||||
|
|
||||||
config TCS3472
|
config TCS3472
|
||||||
tristate "TAOS TCS3472 color light-to-digital converter"
|
tristate "TAOS TCS3472 color light-to-digital converter"
|
||||||
depends on I2C
|
depends on I2C
|
||||||
|
|
|
@ -10,9 +10,11 @@ obj-$(CONFIG_CM36651) += cm36651.o
|
||||||
obj-$(CONFIG_GP2AP020A00F) += gp2ap020a00f.o
|
obj-$(CONFIG_GP2AP020A00F) += gp2ap020a00f.o
|
||||||
obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o
|
obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o
|
||||||
obj-$(CONFIG_HID_SENSOR_PROX) += hid-sensor-prox.o
|
obj-$(CONFIG_HID_SENSOR_PROX) += hid-sensor-prox.o
|
||||||
|
obj-$(CONFIG_ISL29125) += isl29125.o
|
||||||
obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o
|
obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o
|
||||||
obj-$(CONFIG_LTR501) += ltr501.o
|
obj-$(CONFIG_LTR501) += ltr501.o
|
||||||
obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o
|
obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o
|
||||||
|
obj-$(CONFIG_TCS3414) += tcs3414.o
|
||||||
obj-$(CONFIG_TCS3472) += tcs3472.o
|
obj-$(CONFIG_TCS3472) += tcs3472.o
|
||||||
obj-$(CONFIG_TSL4531) += tsl4531.o
|
obj-$(CONFIG_TSL4531) += tsl4531.o
|
||||||
obj-$(CONFIG_VCNL4000) += vcnl4000.o
|
obj-$(CONFIG_VCNL4000) += vcnl4000.o
|
||||||
|
|
347
drivers/iio/light/isl29125.c
Normal file
347
drivers/iio/light/isl29125.c
Normal file
|
@ -0,0 +1,347 @@
|
||||||
|
/*
|
||||||
|
* isl29125.c - Support for Intersil ISL29125 RGB light sensor
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of version 2 of
|
||||||
|
* the GNU General Public License. See the file COPYING in the main
|
||||||
|
* directory of this archive for more details.
|
||||||
|
*
|
||||||
|
* RGB light sensor with 16-bit channels for red, green, blue);
|
||||||
|
* 7-bit I2C slave address 0x44
|
||||||
|
*
|
||||||
|
* TODO: interrupt support, IR compensation, thresholds, 12bit
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/pm.h>
|
||||||
|
|
||||||
|
#include <linux/iio/iio.h>
|
||||||
|
#include <linux/iio/sysfs.h>
|
||||||
|
#include <linux/iio/trigger_consumer.h>
|
||||||
|
#include <linux/iio/buffer.h>
|
||||||
|
#include <linux/iio/triggered_buffer.h>
|
||||||
|
|
||||||
|
#define ISL29125_DRV_NAME "isl29125"
|
||||||
|
|
||||||
|
#define ISL29125_DEVICE_ID 0x00
|
||||||
|
#define ISL29125_CONF1 0x01
|
||||||
|
#define ISL29125_CONF2 0x02
|
||||||
|
#define ISL29125_CONF3 0x03
|
||||||
|
#define ISL29125_STATUS 0x08
|
||||||
|
#define ISL29125_GREEN_DATA 0x09
|
||||||
|
#define ISL29125_RED_DATA 0x0b
|
||||||
|
#define ISL29125_BLUE_DATA 0x0d
|
||||||
|
|
||||||
|
#define ISL29125_ID 0x7d
|
||||||
|
|
||||||
|
#define ISL29125_MODE_MASK GENMASK(2, 0)
|
||||||
|
#define ISL29125_MODE_PD 0x0
|
||||||
|
#define ISL29125_MODE_G 0x1
|
||||||
|
#define ISL29125_MODE_R 0x2
|
||||||
|
#define ISL29125_MODE_B 0x3
|
||||||
|
#define ISL29125_MODE_RGB 0x5
|
||||||
|
|
||||||
|
#define ISL29125_MODE_RANGE BIT(3)
|
||||||
|
|
||||||
|
#define ISL29125_STATUS_CONV BIT(1)
|
||||||
|
|
||||||
|
struct isl29125_data {
|
||||||
|
struct i2c_client *client;
|
||||||
|
struct mutex lock;
|
||||||
|
u8 conf1;
|
||||||
|
u16 buffer[8]; /* 3x 16-bit, padding, 8 bytes timestamp */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ISL29125_CHANNEL(_color, _si) { \
|
||||||
|
.type = IIO_INTENSITY, \
|
||||||
|
.modified = 1, \
|
||||||
|
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
|
||||||
|
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
|
||||||
|
.channel2 = IIO_MOD_LIGHT_##_color, \
|
||||||
|
.scan_index = _si, \
|
||||||
|
.scan_type = { \
|
||||||
|
.sign = 'u', \
|
||||||
|
.realbits = 16, \
|
||||||
|
.storagebits = 16, \
|
||||||
|
.endianness = IIO_CPU, \
|
||||||
|
}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct iio_chan_spec isl29125_channels[] = {
|
||||||
|
ISL29125_CHANNEL(GREEN, 0),
|
||||||
|
ISL29125_CHANNEL(RED, 1),
|
||||||
|
ISL29125_CHANNEL(BLUE, 2),
|
||||||
|
IIO_CHAN_SOFT_TIMESTAMP(3),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct {
|
||||||
|
u8 mode, data;
|
||||||
|
} isl29125_regs[] = {
|
||||||
|
{ISL29125_MODE_G, ISL29125_GREEN_DATA},
|
||||||
|
{ISL29125_MODE_R, ISL29125_RED_DATA},
|
||||||
|
{ISL29125_MODE_B, ISL29125_BLUE_DATA},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int isl29125_read_data(struct isl29125_data *data, int si)
|
||||||
|
{
|
||||||
|
int tries = 5;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
|
||||||
|
data->conf1 | isl29125_regs[si].mode);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
msleep(101);
|
||||||
|
|
||||||
|
while (tries--) {
|
||||||
|
ret = i2c_smbus_read_byte_data(data->client, ISL29125_STATUS);
|
||||||
|
if (ret < 0)
|
||||||
|
goto fail;
|
||||||
|
if (ret & ISL29125_STATUS_CONV)
|
||||||
|
break;
|
||||||
|
msleep(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tries < 0) {
|
||||||
|
dev_err(&data->client->dev, "data not ready\n");
|
||||||
|
ret = -EIO;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = i2c_smbus_read_word_data(data->client, isl29125_regs[si].data);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
i2c_smbus_write_byte_data(data->client, ISL29125_CONF1, data->conf1);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int isl29125_read_raw(struct iio_dev *indio_dev,
|
||||||
|
struct iio_chan_spec const *chan,
|
||||||
|
int *val, int *val2, long mask)
|
||||||
|
{
|
||||||
|
struct isl29125_data *data = iio_priv(indio_dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
switch (mask) {
|
||||||
|
case IIO_CHAN_INFO_RAW:
|
||||||
|
if (iio_buffer_enabled(indio_dev))
|
||||||
|
return -EBUSY;
|
||||||
|
mutex_lock(&data->lock);
|
||||||
|
ret = isl29125_read_data(data, chan->scan_index);
|
||||||
|
mutex_unlock(&data->lock);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
*val = ret;
|
||||||
|
return IIO_VAL_INT;
|
||||||
|
case IIO_CHAN_INFO_SCALE:
|
||||||
|
*val = 0;
|
||||||
|
if (data->conf1 & ISL29125_MODE_RANGE)
|
||||||
|
*val2 = 152590; /* 10k lux full range */
|
||||||
|
else
|
||||||
|
*val2 = 5722; /* 375 lux full range */
|
||||||
|
return IIO_VAL_INT_PLUS_MICRO;
|
||||||
|
}
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int isl29125_write_raw(struct iio_dev *indio_dev,
|
||||||
|
struct iio_chan_spec const *chan,
|
||||||
|
int val, int val2, long mask)
|
||||||
|
{
|
||||||
|
struct isl29125_data *data = iio_priv(indio_dev);
|
||||||
|
|
||||||
|
switch (mask) {
|
||||||
|
case IIO_CHAN_INFO_SCALE:
|
||||||
|
if (val != 0)
|
||||||
|
return -EINVAL;
|
||||||
|
if (val2 == 152590)
|
||||||
|
data->conf1 |= ISL29125_MODE_RANGE;
|
||||||
|
else if (val2 == 5722)
|
||||||
|
data->conf1 &= ~ISL29125_MODE_RANGE;
|
||||||
|
else
|
||||||
|
return -EINVAL;
|
||||||
|
return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
|
||||||
|
data->conf1);
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t isl29125_trigger_handler(int irq, void *p)
|
||||||
|
{
|
||||||
|
struct iio_poll_func *pf = p;
|
||||||
|
struct iio_dev *indio_dev = pf->indio_dev;
|
||||||
|
struct isl29125_data *data = iio_priv(indio_dev);
|
||||||
|
int i, j = 0;
|
||||||
|
|
||||||
|
for_each_set_bit(i, indio_dev->active_scan_mask,
|
||||||
|
indio_dev->masklength) {
|
||||||
|
int ret = i2c_smbus_read_word_data(data->client,
|
||||||
|
isl29125_regs[i].data);
|
||||||
|
if (ret < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
data->buffer[j++] = ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
|
||||||
|
iio_get_time_ns());
|
||||||
|
|
||||||
|
done:
|
||||||
|
iio_trigger_notify_done(indio_dev->trig);
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct iio_info isl29125_info = {
|
||||||
|
.read_raw = isl29125_read_raw,
|
||||||
|
.write_raw = isl29125_write_raw,
|
||||||
|
.driver_module = THIS_MODULE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int isl29125_buffer_preenable(struct iio_dev *indio_dev)
|
||||||
|
{
|
||||||
|
struct isl29125_data *data = iio_priv(indio_dev);
|
||||||
|
|
||||||
|
data->conf1 |= ISL29125_MODE_RGB;
|
||||||
|
return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
|
||||||
|
data->conf1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int isl29125_buffer_predisable(struct iio_dev *indio_dev)
|
||||||
|
{
|
||||||
|
struct isl29125_data *data = iio_priv(indio_dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = iio_triggered_buffer_predisable(indio_dev);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
data->conf1 &= ~ISL29125_MODE_MASK;
|
||||||
|
data->conf1 |= ISL29125_MODE_PD;
|
||||||
|
return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
|
||||||
|
data->conf1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct iio_buffer_setup_ops isl29125_buffer_setup_ops = {
|
||||||
|
.preenable = isl29125_buffer_preenable,
|
||||||
|
.postenable = &iio_triggered_buffer_postenable,
|
||||||
|
.predisable = isl29125_buffer_predisable,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int isl29125_probe(struct i2c_client *client,
|
||||||
|
const struct i2c_device_id *id)
|
||||||
|
{
|
||||||
|
struct isl29125_data *data;
|
||||||
|
struct iio_dev *indio_dev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
|
||||||
|
if (indio_dev == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
data = iio_priv(indio_dev);
|
||||||
|
i2c_set_clientdata(client, indio_dev);
|
||||||
|
data->client = client;
|
||||||
|
mutex_init(&data->lock);
|
||||||
|
|
||||||
|
indio_dev->dev.parent = &client->dev;
|
||||||
|
indio_dev->info = &isl29125_info;
|
||||||
|
indio_dev->name = ISL29125_DRV_NAME;
|
||||||
|
indio_dev->channels = isl29125_channels;
|
||||||
|
indio_dev->num_channels = ARRAY_SIZE(isl29125_channels);
|
||||||
|
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||||
|
|
||||||
|
ret = i2c_smbus_read_byte_data(data->client, ISL29125_DEVICE_ID);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
if (ret != ISL29125_ID)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
data->conf1 = ISL29125_MODE_PD | ISL29125_MODE_RANGE;
|
||||||
|
ret = i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
|
||||||
|
data->conf1);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = i2c_smbus_write_byte_data(data->client, ISL29125_STATUS, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = iio_triggered_buffer_setup(indio_dev, NULL,
|
||||||
|
isl29125_trigger_handler, &isl29125_buffer_setup_ops);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = iio_device_register(indio_dev);
|
||||||
|
if (ret < 0)
|
||||||
|
goto buffer_cleanup;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
buffer_cleanup:
|
||||||
|
iio_triggered_buffer_cleanup(indio_dev);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int isl29125_powerdown(struct isl29125_data *data)
|
||||||
|
{
|
||||||
|
return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
|
||||||
|
(data->conf1 & ~ISL29125_MODE_MASK) | ISL29125_MODE_PD);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int isl29125_remove(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
struct iio_dev *indio_dev = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
iio_device_unregister(indio_dev);
|
||||||
|
iio_triggered_buffer_cleanup(indio_dev);
|
||||||
|
isl29125_powerdown(iio_priv(indio_dev));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
static int isl29125_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct isl29125_data *data = iio_priv(i2c_get_clientdata(
|
||||||
|
to_i2c_client(dev)));
|
||||||
|
return isl29125_powerdown(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int isl29125_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct isl29125_data *data = iio_priv(i2c_get_clientdata(
|
||||||
|
to_i2c_client(dev)));
|
||||||
|
return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
|
||||||
|
data->conf1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static SIMPLE_DEV_PM_OPS(isl29125_pm_ops, isl29125_suspend, isl29125_resume);
|
||||||
|
|
||||||
|
static const struct i2c_device_id isl29125_id[] = {
|
||||||
|
{ "isl29125", 0 },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(i2c, isl29125_id);
|
||||||
|
|
||||||
|
static struct i2c_driver isl29125_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = ISL29125_DRV_NAME,
|
||||||
|
.pm = &isl29125_pm_ops,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
},
|
||||||
|
.probe = isl29125_probe,
|
||||||
|
.remove = isl29125_remove,
|
||||||
|
.id_table = isl29125_id,
|
||||||
|
};
|
||||||
|
module_i2c_driver(isl29125_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
|
||||||
|
MODULE_DESCRIPTION("ISL29125 RGB light sensor driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
405
drivers/iio/light/tcs3414.c
Normal file
405
drivers/iio/light/tcs3414.c
Normal file
|
@ -0,0 +1,405 @@
|
||||||
|
/*
|
||||||
|
* tcs3414.c - Support for TAOS TCS3414 digital color sensor
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of version 2 of
|
||||||
|
* the GNU General Public License. See the file COPYING in the main
|
||||||
|
* directory of this archive for more details.
|
||||||
|
*
|
||||||
|
* Digital color sensor with 16-bit channels for red, green, blue, clear);
|
||||||
|
* 7-bit I2C slave address 0x39 (TCS3414) or 0x29, 0x49, 0x59 (TCS3413,
|
||||||
|
* TCS3415, TCS3416, resp.)
|
||||||
|
*
|
||||||
|
* TODO: sync, interrupt support, thresholds, prescaler
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/pm.h>
|
||||||
|
|
||||||
|
#include <linux/iio/iio.h>
|
||||||
|
#include <linux/iio/sysfs.h>
|
||||||
|
#include <linux/iio/trigger_consumer.h>
|
||||||
|
#include <linux/iio/buffer.h>
|
||||||
|
#include <linux/iio/triggered_buffer.h>
|
||||||
|
|
||||||
|
#define TCS3414_DRV_NAME "tcs3414"
|
||||||
|
|
||||||
|
#define TCS3414_COMMAND BIT(7)
|
||||||
|
#define TCS3414_COMMAND_WORD (TCS3414_COMMAND | BIT(5))
|
||||||
|
|
||||||
|
#define TCS3414_CONTROL (TCS3414_COMMAND | 0x00)
|
||||||
|
#define TCS3414_TIMING (TCS3414_COMMAND | 0x01)
|
||||||
|
#define TCS3414_ID (TCS3414_COMMAND | 0x04)
|
||||||
|
#define TCS3414_GAIN (TCS3414_COMMAND | 0x07)
|
||||||
|
#define TCS3414_DATA_GREEN (TCS3414_COMMAND_WORD | 0x10)
|
||||||
|
#define TCS3414_DATA_RED (TCS3414_COMMAND_WORD | 0x12)
|
||||||
|
#define TCS3414_DATA_BLUE (TCS3414_COMMAND_WORD | 0x14)
|
||||||
|
#define TCS3414_DATA_CLEAR (TCS3414_COMMAND_WORD | 0x16)
|
||||||
|
|
||||||
|
#define TCS3414_CONTROL_ADC_VALID BIT(4)
|
||||||
|
#define TCS3414_CONTROL_ADC_EN BIT(1)
|
||||||
|
#define TCS3414_CONTROL_POWER BIT(0)
|
||||||
|
|
||||||
|
#define TCS3414_INTEG_MASK GENMASK(1, 0)
|
||||||
|
#define TCS3414_INTEG_12MS 0x0
|
||||||
|
#define TCS3414_INTEG_100MS 0x1
|
||||||
|
#define TCS3414_INTEG_400MS 0x2
|
||||||
|
|
||||||
|
#define TCS3414_GAIN_MASK GENMASK(5, 4)
|
||||||
|
#define TCS3414_GAIN_SHIFT 4
|
||||||
|
|
||||||
|
struct tcs3414_data {
|
||||||
|
struct i2c_client *client;
|
||||||
|
struct mutex lock;
|
||||||
|
u8 control;
|
||||||
|
u8 gain;
|
||||||
|
u8 timing;
|
||||||
|
u16 buffer[8]; /* 4x 16-bit + 8 bytes timestamp */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TCS3414_CHANNEL(_color, _si, _addr) { \
|
||||||
|
.type = IIO_INTENSITY, \
|
||||||
|
.modified = 1, \
|
||||||
|
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
|
||||||
|
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
|
||||||
|
BIT(IIO_CHAN_INFO_INT_TIME), \
|
||||||
|
.channel2 = IIO_MOD_LIGHT_##_color, \
|
||||||
|
.address = _addr, \
|
||||||
|
.scan_index = _si, \
|
||||||
|
.scan_type = { \
|
||||||
|
.sign = 'u', \
|
||||||
|
.realbits = 16, \
|
||||||
|
.storagebits = 16, \
|
||||||
|
.endianness = IIO_CPU, \
|
||||||
|
}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* scale factors: 1/gain */
|
||||||
|
static const int tcs3414_scales[][2] = {
|
||||||
|
{1, 0}, {0, 250000}, {0, 62500}, {0, 15625}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* integration time in ms */
|
||||||
|
static const int tcs3414_times[] = { 12, 100, 400 };
|
||||||
|
|
||||||
|
static const struct iio_chan_spec tcs3414_channels[] = {
|
||||||
|
TCS3414_CHANNEL(GREEN, 0, TCS3414_DATA_GREEN),
|
||||||
|
TCS3414_CHANNEL(RED, 1, TCS3414_DATA_RED),
|
||||||
|
TCS3414_CHANNEL(BLUE, 2, TCS3414_DATA_BLUE),
|
||||||
|
TCS3414_CHANNEL(CLEAR, 3, TCS3414_DATA_CLEAR),
|
||||||
|
IIO_CHAN_SOFT_TIMESTAMP(4),
|
||||||
|
};
|
||||||
|
|
||||||
|
static int tcs3414_req_data(struct tcs3414_data *data)
|
||||||
|
{
|
||||||
|
int tries = 25;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
|
||||||
|
data->control | TCS3414_CONTROL_ADC_EN);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
while (tries--) {
|
||||||
|
ret = i2c_smbus_read_byte_data(data->client, TCS3414_CONTROL);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
if (ret & TCS3414_CONTROL_ADC_VALID)
|
||||||
|
break;
|
||||||
|
msleep(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
|
||||||
|
data->control);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (tries < 0) {
|
||||||
|
dev_err(&data->client->dev, "data not ready\n");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tcs3414_read_raw(struct iio_dev *indio_dev,
|
||||||
|
struct iio_chan_spec const *chan,
|
||||||
|
int *val, int *val2, long mask)
|
||||||
|
{
|
||||||
|
struct tcs3414_data *data = iio_priv(indio_dev);
|
||||||
|
int i, ret;
|
||||||
|
|
||||||
|
switch (mask) {
|
||||||
|
case IIO_CHAN_INFO_RAW:
|
||||||
|
if (iio_buffer_enabled(indio_dev))
|
||||||
|
return -EBUSY;
|
||||||
|
mutex_lock(&data->lock);
|
||||||
|
ret = tcs3414_req_data(data);
|
||||||
|
if (ret < 0) {
|
||||||
|
mutex_unlock(&data->lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ret = i2c_smbus_read_word_data(data->client, chan->address);
|
||||||
|
mutex_unlock(&data->lock);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
*val = ret;
|
||||||
|
return IIO_VAL_INT;
|
||||||
|
case IIO_CHAN_INFO_SCALE:
|
||||||
|
i = (data->gain & TCS3414_GAIN_MASK) >> TCS3414_GAIN_SHIFT;
|
||||||
|
*val = tcs3414_scales[i][0];
|
||||||
|
*val2 = tcs3414_scales[i][1];
|
||||||
|
return IIO_VAL_INT_PLUS_MICRO;
|
||||||
|
case IIO_CHAN_INFO_INT_TIME:
|
||||||
|
*val = 0;
|
||||||
|
*val2 = tcs3414_times[data->timing & TCS3414_INTEG_MASK] * 1000;
|
||||||
|
return IIO_VAL_INT_PLUS_MICRO;
|
||||||
|
}
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tcs3414_write_raw(struct iio_dev *indio_dev,
|
||||||
|
struct iio_chan_spec const *chan,
|
||||||
|
int val, int val2, long mask)
|
||||||
|
{
|
||||||
|
struct tcs3414_data *data = iio_priv(indio_dev);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
switch (mask) {
|
||||||
|
case IIO_CHAN_INFO_SCALE:
|
||||||
|
for (i = 0; i < ARRAY_SIZE(tcs3414_scales); i++) {
|
||||||
|
if (val == tcs3414_scales[i][0] &&
|
||||||
|
val2 == tcs3414_scales[i][1]) {
|
||||||
|
data->gain &= ~TCS3414_GAIN_MASK;
|
||||||
|
data->gain |= i << TCS3414_GAIN_SHIFT;
|
||||||
|
return i2c_smbus_write_byte_data(
|
||||||
|
data->client, TCS3414_GAIN,
|
||||||
|
data->gain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -EINVAL;
|
||||||
|
case IIO_CHAN_INFO_INT_TIME:
|
||||||
|
if (val != 0)
|
||||||
|
return -EINVAL;
|
||||||
|
for (i = 0; i < ARRAY_SIZE(tcs3414_times); i++) {
|
||||||
|
if (val == tcs3414_times[i] * 1000) {
|
||||||
|
data->timing &= ~TCS3414_INTEG_MASK;
|
||||||
|
data->timing |= i;
|
||||||
|
return i2c_smbus_write_byte_data(
|
||||||
|
data->client, TCS3414_TIMING,
|
||||||
|
data->timing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -EINVAL;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t tcs3414_trigger_handler(int irq, void *p)
|
||||||
|
{
|
||||||
|
struct iio_poll_func *pf = p;
|
||||||
|
struct iio_dev *indio_dev = pf->indio_dev;
|
||||||
|
struct tcs3414_data *data = iio_priv(indio_dev);
|
||||||
|
int i, j = 0;
|
||||||
|
|
||||||
|
for_each_set_bit(i, indio_dev->active_scan_mask,
|
||||||
|
indio_dev->masklength) {
|
||||||
|
int ret = i2c_smbus_read_word_data(data->client,
|
||||||
|
TCS3414_DATA_GREEN + 2*i);
|
||||||
|
if (ret < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
data->buffer[j++] = ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
|
||||||
|
iio_get_time_ns());
|
||||||
|
|
||||||
|
done:
|
||||||
|
iio_trigger_notify_done(indio_dev->trig);
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static IIO_CONST_ATTR(scale_available, "1 0.25 0.0625 0.015625");
|
||||||
|
static IIO_CONST_ATTR_INT_TIME_AVAIL("0.012 0.1 0.4");
|
||||||
|
|
||||||
|
static struct attribute *tcs3414_attributes[] = {
|
||||||
|
&iio_const_attr_scale_available.dev_attr.attr,
|
||||||
|
&iio_const_attr_integration_time_available.dev_attr.attr,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct attribute_group tcs3414_attribute_group = {
|
||||||
|
.attrs = tcs3414_attributes,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct iio_info tcs3414_info = {
|
||||||
|
.read_raw = tcs3414_read_raw,
|
||||||
|
.write_raw = tcs3414_write_raw,
|
||||||
|
.attrs = &tcs3414_attribute_group,
|
||||||
|
.driver_module = THIS_MODULE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int tcs3414_buffer_preenable(struct iio_dev *indio_dev)
|
||||||
|
{
|
||||||
|
struct tcs3414_data *data = iio_priv(indio_dev);
|
||||||
|
|
||||||
|
data->control |= TCS3414_CONTROL_ADC_EN;
|
||||||
|
return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
|
||||||
|
data->control);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tcs3414_buffer_predisable(struct iio_dev *indio_dev)
|
||||||
|
{
|
||||||
|
struct tcs3414_data *data = iio_priv(indio_dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = iio_triggered_buffer_predisable(indio_dev);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
data->control &= ~TCS3414_CONTROL_ADC_EN;
|
||||||
|
return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
|
||||||
|
data->control);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct iio_buffer_setup_ops tcs3414_buffer_setup_ops = {
|
||||||
|
.preenable = tcs3414_buffer_preenable,
|
||||||
|
.postenable = &iio_triggered_buffer_postenable,
|
||||||
|
.predisable = tcs3414_buffer_predisable,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int tcs3414_probe(struct i2c_client *client,
|
||||||
|
const struct i2c_device_id *id)
|
||||||
|
{
|
||||||
|
struct tcs3414_data *data;
|
||||||
|
struct iio_dev *indio_dev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
|
||||||
|
if (indio_dev == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
data = iio_priv(indio_dev);
|
||||||
|
i2c_set_clientdata(client, indio_dev);
|
||||||
|
data->client = client;
|
||||||
|
mutex_init(&data->lock);
|
||||||
|
|
||||||
|
indio_dev->dev.parent = &client->dev;
|
||||||
|
indio_dev->info = &tcs3414_info;
|
||||||
|
indio_dev->name = TCS3414_DRV_NAME;
|
||||||
|
indio_dev->channels = tcs3414_channels;
|
||||||
|
indio_dev->num_channels = ARRAY_SIZE(tcs3414_channels);
|
||||||
|
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||||
|
|
||||||
|
ret = i2c_smbus_read_byte_data(data->client, TCS3414_ID);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
switch (ret & 0xf0) {
|
||||||
|
case 0x00:
|
||||||
|
dev_info(&client->dev, "TCS3404 found\n");
|
||||||
|
break;
|
||||||
|
case 0x10:
|
||||||
|
dev_info(&client->dev, "TCS3413/14/15/16 found\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->control = TCS3414_CONTROL_POWER;
|
||||||
|
ret = i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
|
||||||
|
data->control);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
data->timing = TCS3414_INTEG_12MS; /* free running */
|
||||||
|
ret = i2c_smbus_write_byte_data(data->client, TCS3414_TIMING,
|
||||||
|
data->timing);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = i2c_smbus_read_byte_data(data->client, TCS3414_GAIN);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
data->gain = ret;
|
||||||
|
|
||||||
|
ret = iio_triggered_buffer_setup(indio_dev, NULL,
|
||||||
|
tcs3414_trigger_handler, &tcs3414_buffer_setup_ops);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = iio_device_register(indio_dev);
|
||||||
|
if (ret < 0)
|
||||||
|
goto buffer_cleanup;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
buffer_cleanup:
|
||||||
|
iio_triggered_buffer_cleanup(indio_dev);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tcs3414_powerdown(struct tcs3414_data *data)
|
||||||
|
{
|
||||||
|
return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
|
||||||
|
data->control & ~(TCS3414_CONTROL_POWER |
|
||||||
|
TCS3414_CONTROL_ADC_EN));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tcs3414_remove(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
struct iio_dev *indio_dev = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
iio_device_unregister(indio_dev);
|
||||||
|
iio_triggered_buffer_cleanup(indio_dev);
|
||||||
|
tcs3414_powerdown(iio_priv(indio_dev));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
static int tcs3414_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct tcs3414_data *data = iio_priv(i2c_get_clientdata(
|
||||||
|
to_i2c_client(dev)));
|
||||||
|
return tcs3414_powerdown(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tcs3414_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct tcs3414_data *data = iio_priv(i2c_get_clientdata(
|
||||||
|
to_i2c_client(dev)));
|
||||||
|
return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
|
||||||
|
data->control);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static SIMPLE_DEV_PM_OPS(tcs3414_pm_ops, tcs3414_suspend, tcs3414_resume);
|
||||||
|
|
||||||
|
static const struct i2c_device_id tcs3414_id[] = {
|
||||||
|
{ "tcs3414", 0 },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(i2c, tcs3414_id);
|
||||||
|
|
||||||
|
static struct i2c_driver tcs3414_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = TCS3414_DRV_NAME,
|
||||||
|
.pm = &tcs3414_pm_ops,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
},
|
||||||
|
.probe = tcs3414_probe,
|
||||||
|
.remove = tcs3414_remove,
|
||||||
|
.id_table = tcs3414_id,
|
||||||
|
};
|
||||||
|
module_i2c_driver(tcs3414_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
|
||||||
|
MODULE_DESCRIPTION("TCS3414 digital color sensors driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
|
@ -299,6 +299,9 @@ static int st_magn_read_raw(struct iio_dev *indio_dev,
|
||||||
else
|
else
|
||||||
*val2 = mdata->current_fullscale->gain;
|
*val2 = mdata->current_fullscale->gain;
|
||||||
return IIO_VAL_INT_PLUS_MICRO;
|
return IIO_VAL_INT_PLUS_MICRO;
|
||||||
|
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||||
|
*val = mdata->odr;
|
||||||
|
return IIO_VAL_INT;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -316,6 +319,13 @@ static int st_magn_write_raw(struct iio_dev *indio_dev,
|
||||||
case IIO_CHAN_INFO_SCALE:
|
case IIO_CHAN_INFO_SCALE:
|
||||||
err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
|
err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
|
||||||
break;
|
break;
|
||||||
|
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||||
|
if (val2)
|
||||||
|
return -EINVAL;
|
||||||
|
mutex_lock(&indio_dev->mlock);
|
||||||
|
err = st_sensors_set_odr(indio_dev, val);
|
||||||
|
mutex_unlock(&indio_dev->mlock);
|
||||||
|
return err;
|
||||||
default:
|
default:
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -323,14 +333,12 @@ static int st_magn_write_raw(struct iio_dev *indio_dev,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
|
|
||||||
static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
|
static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
|
||||||
static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_magn_scale_available);
|
static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_magn_scale_available);
|
||||||
|
|
||||||
static struct attribute *st_magn_attributes[] = {
|
static struct attribute *st_magn_attributes[] = {
|
||||||
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
|
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
|
||||||
&iio_dev_attr_in_magn_scale_available.dev_attr.attr,
|
&iio_dev_attr_in_magn_scale_available.dev_attr.attr,
|
||||||
&iio_dev_attr_sampling_frequency.dev_attr.attr,
|
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,27 @@
|
||||||
#include <linux/iio/common/st_sensors_i2c.h>
|
#include <linux/iio/common/st_sensors_i2c.h>
|
||||||
#include "st_magn.h"
|
#include "st_magn.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
static const struct of_device_id st_magn_of_match[] = {
|
||||||
|
{
|
||||||
|
.compatible = "st,lsm303dlhc-magn",
|
||||||
|
.data = LSM303DLHC_MAGN_DEV_NAME,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "st,lsm303dlm-magn",
|
||||||
|
.data = LSM303DLM_MAGN_DEV_NAME,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "st,lis3mdl-magn",
|
||||||
|
.data = LIS3MDL_MAGN_DEV_NAME,
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, st_magn_of_match);
|
||||||
|
#else
|
||||||
|
#define st_magn_of_match NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
static int st_magn_i2c_probe(struct i2c_client *client,
|
static int st_magn_i2c_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
|
@ -31,6 +52,7 @@ static int st_magn_i2c_probe(struct i2c_client *client,
|
||||||
|
|
||||||
mdata = iio_priv(indio_dev);
|
mdata = iio_priv(indio_dev);
|
||||||
mdata->dev = &client->dev;
|
mdata->dev = &client->dev;
|
||||||
|
st_sensors_of_i2c_probe(client, st_magn_of_match);
|
||||||
|
|
||||||
st_sensors_i2c_configure(indio_dev, client, mdata);
|
st_sensors_i2c_configure(indio_dev, client, mdata);
|
||||||
|
|
||||||
|
@ -61,6 +83,7 @@ static struct i2c_driver st_magn_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.name = "st-magn-i2c",
|
.name = "st-magn-i2c",
|
||||||
|
.of_match_table = of_match_ptr(st_magn_of_match),
|
||||||
},
|
},
|
||||||
.probe = st_magn_i2c_probe,
|
.probe = st_magn_i2c_probe,
|
||||||
.remove = st_magn_i2c_remove,
|
.remove = st_magn_i2c_remove,
|
||||||
|
|
|
@ -307,6 +307,27 @@ static const struct st_sensors st_press_sensors[] = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int st_press_write_raw(struct iio_dev *indio_dev,
|
||||||
|
struct iio_chan_spec const *ch,
|
||||||
|
int val,
|
||||||
|
int val2,
|
||||||
|
long mask)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
switch (mask) {
|
||||||
|
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||||
|
if (val2)
|
||||||
|
return -EINVAL;
|
||||||
|
mutex_lock(&indio_dev->mlock);
|
||||||
|
err = st_sensors_set_odr(indio_dev, val);
|
||||||
|
mutex_unlock(&indio_dev->mlock);
|
||||||
|
return err;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int st_press_read_raw(struct iio_dev *indio_dev,
|
static int st_press_read_raw(struct iio_dev *indio_dev,
|
||||||
struct iio_chan_spec const *ch, int *val,
|
struct iio_chan_spec const *ch, int *val,
|
||||||
int *val2, long mask)
|
int *val2, long mask)
|
||||||
|
@ -349,6 +370,9 @@ static int st_press_read_raw(struct iio_dev *indio_dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
return IIO_VAL_FRACTIONAL;
|
return IIO_VAL_FRACTIONAL;
|
||||||
|
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||||
|
*val = pdata->odr;
|
||||||
|
return IIO_VAL_INT;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -357,12 +381,10 @@ static int st_press_read_raw(struct iio_dev *indio_dev,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
|
|
||||||
static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
|
static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
|
||||||
|
|
||||||
static struct attribute *st_press_attributes[] = {
|
static struct attribute *st_press_attributes[] = {
|
||||||
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
|
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
|
||||||
&iio_dev_attr_sampling_frequency.dev_attr.attr,
|
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -374,6 +396,7 @@ static const struct iio_info press_info = {
|
||||||
.driver_module = THIS_MODULE,
|
.driver_module = THIS_MODULE,
|
||||||
.attrs = &st_press_attribute_group,
|
.attrs = &st_press_attribute_group,
|
||||||
.read_raw = &st_press_read_raw,
|
.read_raw = &st_press_read_raw,
|
||||||
|
.write_raw = &st_press_write_raw,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_IIO_TRIGGER
|
#ifdef CONFIG_IIO_TRIGGER
|
||||||
|
|
|
@ -18,6 +18,27 @@
|
||||||
#include <linux/iio/common/st_sensors_i2c.h>
|
#include <linux/iio/common/st_sensors_i2c.h>
|
||||||
#include "st_pressure.h"
|
#include "st_pressure.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
static const struct of_device_id st_press_of_match[] = {
|
||||||
|
{
|
||||||
|
.compatible = "st,lps001wp-press",
|
||||||
|
.data = LPS001WP_PRESS_DEV_NAME,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "st,lps25h-press",
|
||||||
|
.data = LPS25H_PRESS_DEV_NAME,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "st,lps331ap-press",
|
||||||
|
.data = LPS331AP_PRESS_DEV_NAME,
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, st_press_of_match);
|
||||||
|
#else
|
||||||
|
#define st_press_of_match NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
static int st_press_i2c_probe(struct i2c_client *client,
|
static int st_press_i2c_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
|
@ -31,6 +52,7 @@ static int st_press_i2c_probe(struct i2c_client *client,
|
||||||
|
|
||||||
pdata = iio_priv(indio_dev);
|
pdata = iio_priv(indio_dev);
|
||||||
pdata->dev = &client->dev;
|
pdata->dev = &client->dev;
|
||||||
|
st_sensors_of_i2c_probe(client, st_press_of_match);
|
||||||
|
|
||||||
st_sensors_i2c_configure(indio_dev, client, pdata);
|
st_sensors_i2c_configure(indio_dev, client, pdata);
|
||||||
|
|
||||||
|
@ -60,6 +82,7 @@ static struct i2c_driver st_press_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.name = "st-press-i2c",
|
.name = "st-press-i2c",
|
||||||
|
.of_match_table = of_match_ptr(st_press_of_match),
|
||||||
},
|
},
|
||||||
.probe = st_press_i2c_probe,
|
.probe = st_press_i2c_probe,
|
||||||
.remove = st_press_i2c_remove,
|
.remove = st_press_i2c_remove,
|
||||||
|
|
|
@ -122,8 +122,6 @@ static bool event_is_known(struct iio_event_data *event)
|
||||||
case IIO_MOD_LIGHT_IR:
|
case IIO_MOD_LIGHT_IR:
|
||||||
case IIO_MOD_ROOT_SUM_SQUARED_X_Y:
|
case IIO_MOD_ROOT_SUM_SQUARED_X_Y:
|
||||||
case IIO_MOD_SUM_SQUARED_X_Y_Z:
|
case IIO_MOD_SUM_SQUARED_X_Y_Z:
|
||||||
case IIO_MOD_LIGHT_BOTH:
|
|
||||||
case IIO_MOD_LIGHT_IR:
|
|
||||||
case IIO_MOD_LIGHT_CLEAR:
|
case IIO_MOD_LIGHT_CLEAR:
|
||||||
case IIO_MOD_LIGHT_RED:
|
case IIO_MOD_LIGHT_RED:
|
||||||
case IIO_MOD_LIGHT_GREEN:
|
case IIO_MOD_LIGHT_GREEN:
|
||||||
|
|
|
@ -131,17 +131,17 @@ static int adis16201_write_raw(struct iio_dev *indio_dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct iio_chan_spec adis16201_channels[] = {
|
static const struct iio_chan_spec adis16201_channels[] = {
|
||||||
ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT, ADIS16201_SCAN_SUPPLY, 12),
|
ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT, ADIS16201_SCAN_SUPPLY, 0, 12),
|
||||||
ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT, ADIS16201_SCAN_TEMP, 12),
|
ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT, ADIS16201_SCAN_TEMP, 0, 12),
|
||||||
ADIS_ACCEL_CHAN(X, ADIS16201_XACCL_OUT, ADIS16201_SCAN_ACC_X,
|
ADIS_ACCEL_CHAN(X, ADIS16201_XACCL_OUT, ADIS16201_SCAN_ACC_X,
|
||||||
BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
|
BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
|
||||||
ADIS_ACCEL_CHAN(Y, ADIS16201_YACCL_OUT, ADIS16201_SCAN_ACC_Y,
|
ADIS_ACCEL_CHAN(Y, ADIS16201_YACCL_OUT, ADIS16201_SCAN_ACC_Y,
|
||||||
BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
|
BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
|
||||||
ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC, ADIS16201_SCAN_AUX_ADC, 12),
|
ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC, ADIS16201_SCAN_AUX_ADC, 0, 12),
|
||||||
ADIS_INCLI_CHAN(X, ADIS16201_XINCL_OUT, ADIS16201_SCAN_INCLI_X,
|
ADIS_INCLI_CHAN(X, ADIS16201_XINCL_OUT, ADIS16201_SCAN_INCLI_X,
|
||||||
BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
|
BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
|
||||||
ADIS_INCLI_CHAN(X, ADIS16201_YINCL_OUT, ADIS16201_SCAN_INCLI_Y,
|
ADIS_INCLI_CHAN(X, ADIS16201_YINCL_OUT, ADIS16201_SCAN_INCLI_Y,
|
||||||
BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
|
BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
|
||||||
IIO_CHAN_SOFT_TIMESTAMP(7)
|
IIO_CHAN_SOFT_TIMESTAMP(7)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -99,13 +99,14 @@ static int adis16203_read_raw(struct iio_dev *indio_dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct iio_chan_spec adis16203_channels[] = {
|
static const struct iio_chan_spec adis16203_channels[] = {
|
||||||
ADIS_SUPPLY_CHAN(ADIS16203_SUPPLY_OUT, ADIS16203_SCAN_SUPPLY, 12),
|
ADIS_SUPPLY_CHAN(ADIS16203_SUPPLY_OUT, ADIS16203_SCAN_SUPPLY, 0, 12),
|
||||||
ADIS_AUX_ADC_CHAN(ADIS16203_AUX_ADC, ADIS16203_SCAN_AUX_ADC, 12),
|
ADIS_AUX_ADC_CHAN(ADIS16203_AUX_ADC, ADIS16203_SCAN_AUX_ADC, 0, 12),
|
||||||
ADIS_INCLI_CHAN(X, ADIS16203_XINCL_OUT, ADIS16203_SCAN_INCLI_X,
|
ADIS_INCLI_CHAN(X, ADIS16203_XINCL_OUT, ADIS16203_SCAN_INCLI_X,
|
||||||
BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
|
BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
|
||||||
/* Fixme: Not what it appears to be - see data sheet */
|
/* Fixme: Not what it appears to be - see data sheet */
|
||||||
ADIS_INCLI_CHAN(Y, ADIS16203_YINCL_OUT, ADIS16203_SCAN_INCLI_Y, 0, 14),
|
ADIS_INCLI_CHAN(Y, ADIS16203_YINCL_OUT, ADIS16203_SCAN_INCLI_Y,
|
||||||
ADIS_TEMP_CHAN(ADIS16203_TEMP_OUT, ADIS16203_SCAN_TEMP, 12),
|
0, 0, 14),
|
||||||
|
ADIS_TEMP_CHAN(ADIS16203_TEMP_OUT, ADIS16203_SCAN_TEMP, 0, 12),
|
||||||
IIO_CHAN_SOFT_TIMESTAMP(5),
|
IIO_CHAN_SOFT_TIMESTAMP(5),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -136,15 +136,15 @@ static int adis16204_write_raw(struct iio_dev *indio_dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct iio_chan_spec adis16204_channels[] = {
|
static const struct iio_chan_spec adis16204_channels[] = {
|
||||||
ADIS_SUPPLY_CHAN(ADIS16204_SUPPLY_OUT, ADIS16204_SCAN_SUPPLY, 12),
|
ADIS_SUPPLY_CHAN(ADIS16204_SUPPLY_OUT, ADIS16204_SCAN_SUPPLY, 0, 12),
|
||||||
ADIS_AUX_ADC_CHAN(ADIS16204_AUX_ADC, ADIS16204_SCAN_AUX_ADC, 12),
|
ADIS_AUX_ADC_CHAN(ADIS16204_AUX_ADC, ADIS16204_SCAN_AUX_ADC, 0, 12),
|
||||||
ADIS_TEMP_CHAN(ADIS16204_TEMP_OUT, ADIS16204_SCAN_TEMP, 12),
|
ADIS_TEMP_CHAN(ADIS16204_TEMP_OUT, ADIS16204_SCAN_TEMP, 0, 12),
|
||||||
ADIS_ACCEL_CHAN(X, ADIS16204_XACCL_OUT, ADIS16204_SCAN_ACC_X,
|
ADIS_ACCEL_CHAN(X, ADIS16204_XACCL_OUT, ADIS16204_SCAN_ACC_X,
|
||||||
BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 14),
|
BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 14),
|
||||||
ADIS_ACCEL_CHAN(Y, ADIS16204_YACCL_OUT, ADIS16204_SCAN_ACC_Y,
|
ADIS_ACCEL_CHAN(Y, ADIS16204_YACCL_OUT, ADIS16204_SCAN_ACC_Y,
|
||||||
BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 14),
|
BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 14),
|
||||||
ADIS_ACCEL_CHAN(ROOT_SUM_SQUARED_X_Y, ADIS16204_XY_RSS_OUT,
|
ADIS_ACCEL_CHAN(ROOT_SUM_SQUARED_X_Y, ADIS16204_XY_RSS_OUT,
|
||||||
ADIS16204_SCAN_ACC_XY, BIT(IIO_CHAN_INFO_PEAK), 14),
|
ADIS16204_SCAN_ACC_XY, BIT(IIO_CHAN_INFO_PEAK), 0, 14),
|
||||||
IIO_CHAN_SOFT_TIMESTAMP(5),
|
IIO_CHAN_SOFT_TIMESTAMP(5),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -130,16 +130,18 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct iio_chan_spec adis16209_channels[] = {
|
static const struct iio_chan_spec adis16209_channels[] = {
|
||||||
ADIS_SUPPLY_CHAN(ADIS16209_SUPPLY_OUT, ADIS16209_SCAN_SUPPLY, 14),
|
ADIS_SUPPLY_CHAN(ADIS16209_SUPPLY_OUT, ADIS16209_SCAN_SUPPLY, 0, 14),
|
||||||
ADIS_TEMP_CHAN(ADIS16209_TEMP_OUT, ADIS16209_SCAN_TEMP, 12),
|
ADIS_TEMP_CHAN(ADIS16209_TEMP_OUT, ADIS16209_SCAN_TEMP, 0, 12),
|
||||||
ADIS_ACCEL_CHAN(X, ADIS16209_XACCL_OUT, ADIS16209_SCAN_ACC_X,
|
ADIS_ACCEL_CHAN(X, ADIS16209_XACCL_OUT, ADIS16209_SCAN_ACC_X,
|
||||||
BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
|
BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
|
||||||
ADIS_ACCEL_CHAN(Y, ADIS16209_YACCL_OUT, ADIS16209_SCAN_ACC_Y,
|
ADIS_ACCEL_CHAN(Y, ADIS16209_YACCL_OUT, ADIS16209_SCAN_ACC_Y,
|
||||||
BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
|
BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
|
||||||
ADIS_AUX_ADC_CHAN(ADIS16209_AUX_ADC, ADIS16209_SCAN_AUX_ADC, 12),
|
ADIS_AUX_ADC_CHAN(ADIS16209_AUX_ADC, ADIS16209_SCAN_AUX_ADC, 0, 12),
|
||||||
ADIS_INCLI_CHAN(X, ADIS16209_XINCL_OUT, ADIS16209_SCAN_INCLI_X, 0, 14),
|
ADIS_INCLI_CHAN(X, ADIS16209_XINCL_OUT, ADIS16209_SCAN_INCLI_X,
|
||||||
ADIS_INCLI_CHAN(Y, ADIS16209_YINCL_OUT, ADIS16209_SCAN_INCLI_Y, 0, 14),
|
0, 0, 14),
|
||||||
ADIS_ROT_CHAN(X, ADIS16209_ROT_OUT, ADIS16209_SCAN_ROT, 0, 14),
|
ADIS_INCLI_CHAN(Y, ADIS16209_YINCL_OUT, ADIS16209_SCAN_INCLI_Y,
|
||||||
|
0, 0, 14),
|
||||||
|
ADIS_ROT_CHAN(X, ADIS16209_ROT_OUT, ADIS16209_SCAN_ROT, 0, 0, 14),
|
||||||
IIO_CHAN_SOFT_TIMESTAMP(8)
|
IIO_CHAN_SOFT_TIMESTAMP(8)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -173,15 +173,15 @@ static int adis16240_write_raw(struct iio_dev *indio_dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct iio_chan_spec adis16240_channels[] = {
|
static const struct iio_chan_spec adis16240_channels[] = {
|
||||||
ADIS_SUPPLY_CHAN(ADIS16240_SUPPLY_OUT, ADIS16240_SCAN_SUPPLY, 10),
|
ADIS_SUPPLY_CHAN(ADIS16240_SUPPLY_OUT, ADIS16240_SCAN_SUPPLY, 0, 10),
|
||||||
ADIS_AUX_ADC_CHAN(ADIS16240_AUX_ADC, ADIS16240_SCAN_AUX_ADC, 10),
|
ADIS_AUX_ADC_CHAN(ADIS16240_AUX_ADC, ADIS16240_SCAN_AUX_ADC, 0, 10),
|
||||||
ADIS_ACCEL_CHAN(X, ADIS16240_XACCL_OUT, ADIS16240_SCAN_ACC_X,
|
ADIS_ACCEL_CHAN(X, ADIS16240_XACCL_OUT, ADIS16240_SCAN_ACC_X,
|
||||||
BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 10),
|
BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 10),
|
||||||
ADIS_ACCEL_CHAN(Y, ADIS16240_YACCL_OUT, ADIS16240_SCAN_ACC_Y,
|
ADIS_ACCEL_CHAN(Y, ADIS16240_YACCL_OUT, ADIS16240_SCAN_ACC_Y,
|
||||||
BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 10),
|
BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 10),
|
||||||
ADIS_ACCEL_CHAN(Z, ADIS16240_ZACCL_OUT, ADIS16240_SCAN_ACC_Z,
|
ADIS_ACCEL_CHAN(Z, ADIS16240_ZACCL_OUT, ADIS16240_SCAN_ACC_Z,
|
||||||
BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 10),
|
BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 10),
|
||||||
ADIS_TEMP_CHAN(ADIS16240_TEMP_OUT, ADIS16240_SCAN_TEMP, 10),
|
ADIS_TEMP_CHAN(ADIS16240_TEMP_OUT, ADIS16240_SCAN_TEMP, 0, 10),
|
||||||
IIO_CHAN_SOFT_TIMESTAMP(6)
|
IIO_CHAN_SOFT_TIMESTAMP(6)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,6 @@
|
||||||
#
|
#
|
||||||
menu "Analog to digital converters"
|
menu "Analog to digital converters"
|
||||||
|
|
||||||
config AD7291
|
|
||||||
tristate "Analog Devices AD7291 ADC driver"
|
|
||||||
depends on I2C
|
|
||||||
help
|
|
||||||
Say yes here to build support for Analog Devices AD7291
|
|
||||||
8 Channel ADC with temperature sensor.
|
|
||||||
|
|
||||||
config AD7606
|
config AD7606
|
||||||
tristate "Analog Devices AD7606 ADC driver"
|
tristate "Analog Devices AD7606 ADC driver"
|
||||||
depends on GPIOLIB
|
depends on GPIOLIB
|
||||||
|
@ -94,7 +87,7 @@ config LPC32XX_ADC
|
||||||
|
|
||||||
config MXS_LRADC
|
config MXS_LRADC
|
||||||
tristate "Freescale i.MX23/i.MX28 LRADC"
|
tristate "Freescale i.MX23/i.MX28 LRADC"
|
||||||
depends on ARCH_MXS || COMPILE_TEST
|
depends on (ARCH_MXS || COMPILE_TEST) && HAS_IOMEM
|
||||||
depends on INPUT
|
depends on INPUT
|
||||||
select STMP_DEVICE
|
select STMP_DEVICE
|
||||||
select IIO_BUFFER
|
select IIO_BUFFER
|
||||||
|
|
|
@ -8,7 +8,6 @@ ad7606-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o
|
||||||
ad7606-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o
|
ad7606-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o
|
||||||
obj-$(CONFIG_AD7606) += ad7606.o
|
obj-$(CONFIG_AD7606) += ad7606.o
|
||||||
|
|
||||||
obj-$(CONFIG_AD7291) += ad7291.o
|
|
||||||
obj-$(CONFIG_AD7780) += ad7780.o
|
obj-$(CONFIG_AD7780) += ad7780.o
|
||||||
obj-$(CONFIG_AD7816) += ad7816.o
|
obj-$(CONFIG_AD7816) += ad7816.o
|
||||||
obj-$(CONFIG_AD7192) += ad7192.o
|
obj-$(CONFIG_AD7192) += ad7192.o
|
||||||
|
|
|
@ -53,7 +53,7 @@ static int ad7606_par_probe(struct platform_device *pdev)
|
||||||
struct iio_dev *indio_dev;
|
struct iio_dev *indio_dev;
|
||||||
void __iomem *addr;
|
void __iomem *addr;
|
||||||
resource_size_t remap_size;
|
resource_size_t remap_size;
|
||||||
int ret, irq;
|
int irq;
|
||||||
|
|
||||||
irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (irq < 0) {
|
if (irq < 0) {
|
||||||
|
@ -62,56 +62,31 @@ static int ad7606_par_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
if (!res)
|
addr = devm_ioremap_resource(&pdev->dev, res);
|
||||||
return -ENODEV;
|
if (IS_ERR(addr))
|
||||||
|
return PTR_ERR(addr);
|
||||||
|
|
||||||
remap_size = resource_size(res);
|
remap_size = resource_size(res);
|
||||||
|
|
||||||
/* Request the regions */
|
|
||||||
if (!request_mem_region(res->start, remap_size, "iio-ad7606")) {
|
|
||||||
ret = -EBUSY;
|
|
||||||
goto out1;
|
|
||||||
}
|
|
||||||
addr = ioremap(res->start, remap_size);
|
|
||||||
if (!addr) {
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto out1;
|
|
||||||
}
|
|
||||||
|
|
||||||
indio_dev = ad7606_probe(&pdev->dev, irq, addr,
|
indio_dev = ad7606_probe(&pdev->dev, irq, addr,
|
||||||
platform_get_device_id(pdev)->driver_data,
|
platform_get_device_id(pdev)->driver_data,
|
||||||
remap_size > 1 ? &ad7606_par16_bops :
|
remap_size > 1 ? &ad7606_par16_bops :
|
||||||
&ad7606_par8_bops);
|
&ad7606_par8_bops);
|
||||||
|
|
||||||
if (IS_ERR(indio_dev)) {
|
if (IS_ERR(indio_dev))
|
||||||
ret = PTR_ERR(indio_dev);
|
return PTR_ERR(indio_dev);
|
||||||
goto out2;
|
|
||||||
}
|
|
||||||
|
|
||||||
platform_set_drvdata(pdev, indio_dev);
|
platform_set_drvdata(pdev, indio_dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out2:
|
|
||||||
iounmap(addr);
|
|
||||||
out1:
|
|
||||||
release_mem_region(res->start, remap_size);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ad7606_par_remove(struct platform_device *pdev)
|
static int ad7606_par_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
|
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
struct resource *res;
|
|
||||||
struct ad7606_state *st = iio_priv(indio_dev);
|
|
||||||
|
|
||||||
ad7606_remove(indio_dev, platform_get_irq(pdev, 0));
|
ad7606_remove(indio_dev, platform_get_irq(pdev, 0));
|
||||||
|
|
||||||
iounmap(st->base_address);
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
||||||
release_mem_region(res->start, resource_size(res));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,7 @@ static ssize_t ad9832_write(struct device *dev, struct device_attribute *attr,
|
||||||
ret = spi_sync(st->spi, &st->msg);
|
ret = spi_sync(st->spi, &st->msg);
|
||||||
break;
|
break;
|
||||||
case AD9832_PHASE_SYM:
|
case AD9832_PHASE_SYM:
|
||||||
if (val < 0 || val > 3) {
|
if (val > 3) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,45 +182,40 @@ static int iio_bfin_tmr_trigger_probe(struct platform_device *pdev)
|
||||||
unsigned int config;
|
unsigned int config;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
st = kzalloc(sizeof(*st), GFP_KERNEL);
|
st = devm_kzalloc(&pdev->dev, sizeof(*st), GFP_KERNEL);
|
||||||
if (st == NULL) {
|
if (st == NULL)
|
||||||
ret = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
st->irq = platform_get_irq(pdev, 0);
|
st->irq = platform_get_irq(pdev, 0);
|
||||||
if (!st->irq) {
|
if (!st->irq) {
|
||||||
dev_err(&pdev->dev, "No IRQs specified");
|
dev_err(&pdev->dev, "No IRQs specified");
|
||||||
ret = -ENODEV;
|
return -ENODEV;
|
||||||
goto out1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = iio_bfin_tmr_get_number(st->irq);
|
ret = iio_bfin_tmr_get_number(st->irq);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out1;
|
return ret;
|
||||||
|
|
||||||
st->timer_num = ret;
|
st->timer_num = ret;
|
||||||
st->t = &iio_bfin_timer_code[st->timer_num];
|
st->t = &iio_bfin_timer_code[st->timer_num];
|
||||||
|
|
||||||
st->trig = iio_trigger_alloc("bfintmr%d", st->timer_num);
|
st->trig = iio_trigger_alloc("bfintmr%d", st->timer_num);
|
||||||
if (!st->trig) {
|
if (!st->trig)
|
||||||
ret = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto out1;
|
|
||||||
}
|
|
||||||
|
|
||||||
st->trig->ops = &iio_bfin_tmr_trigger_ops;
|
st->trig->ops = &iio_bfin_tmr_trigger_ops;
|
||||||
st->trig->dev.groups = iio_bfin_tmr_trigger_attr_groups;
|
st->trig->dev.groups = iio_bfin_tmr_trigger_attr_groups;
|
||||||
iio_trigger_set_drvdata(st->trig, st);
|
iio_trigger_set_drvdata(st->trig, st);
|
||||||
ret = iio_trigger_register(st->trig);
|
ret = iio_trigger_register(st->trig);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out2;
|
goto out;
|
||||||
|
|
||||||
ret = request_irq(st->irq, iio_bfin_tmr_trigger_isr,
|
ret = request_irq(st->irq, iio_bfin_tmr_trigger_isr,
|
||||||
0, st->trig->name, st);
|
0, st->trig->name, st);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&pdev->dev,
|
dev_err(&pdev->dev,
|
||||||
"request IRQ-%d failed", st->irq);
|
"request IRQ-%d failed", st->irq);
|
||||||
goto out4;
|
goto out1;
|
||||||
}
|
}
|
||||||
|
|
||||||
config = PWM_OUT | PERIOD_CNT | IRQ_ENA;
|
config = PWM_OUT | PERIOD_CNT | IRQ_ENA;
|
||||||
|
@ -260,13 +255,10 @@ static int iio_bfin_tmr_trigger_probe(struct platform_device *pdev)
|
||||||
return 0;
|
return 0;
|
||||||
out_free_irq:
|
out_free_irq:
|
||||||
free_irq(st->irq, st);
|
free_irq(st->irq, st);
|
||||||
out4:
|
|
||||||
iio_trigger_unregister(st->trig);
|
|
||||||
out2:
|
|
||||||
iio_trigger_put(st->trig);
|
|
||||||
out1:
|
out1:
|
||||||
kfree(st);
|
iio_trigger_unregister(st->trig);
|
||||||
out:
|
out:
|
||||||
|
iio_trigger_put(st->trig);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +272,6 @@ static int iio_bfin_tmr_trigger_remove(struct platform_device *pdev)
|
||||||
free_irq(st->irq, st);
|
free_irq(st->irq, st);
|
||||||
iio_trigger_unregister(st->trig);
|
iio_trigger_unregister(st->trig);
|
||||||
iio_trigger_put(st->trig);
|
iio_trigger_put(st->trig);
|
||||||
kfree(st);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
.type = device_type, \
|
.type = device_type, \
|
||||||
.modified = mod, \
|
.modified = mod, \
|
||||||
.info_mask_separate = mask, \
|
.info_mask_separate = mask, \
|
||||||
|
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
|
||||||
.scan_index = index, \
|
.scan_index = index, \
|
||||||
.channel2 = ch2, \
|
.channel2 = ch2, \
|
||||||
.address = addr, \
|
.address = addr, \
|
||||||
|
@ -59,11 +60,6 @@
|
||||||
}, \
|
}, \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ST_SENSOR_DEV_ATTR_SAMP_FREQ() \
|
|
||||||
IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, \
|
|
||||||
st_sensors_sysfs_get_sampling_frequency, \
|
|
||||||
st_sensors_sysfs_set_sampling_frequency)
|
|
||||||
|
|
||||||
#define ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL() \
|
#define ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL() \
|
||||||
IIO_DEV_ATTR_SAMP_FREQ_AVAIL( \
|
IIO_DEV_ATTR_SAMP_FREQ_AVAIL( \
|
||||||
st_sensors_sysfs_sampling_frequency_avail)
|
st_sensors_sysfs_sampling_frequency_avail)
|
||||||
|
@ -285,12 +281,6 @@ int st_sensors_read_info_raw(struct iio_dev *indio_dev,
|
||||||
int st_sensors_check_device_support(struct iio_dev *indio_dev,
|
int st_sensors_check_device_support(struct iio_dev *indio_dev,
|
||||||
int num_sensors_list, const struct st_sensors *sensors);
|
int num_sensors_list, const struct st_sensors *sensors);
|
||||||
|
|
||||||
ssize_t st_sensors_sysfs_get_sampling_frequency(struct device *dev,
|
|
||||||
struct device_attribute *attr, char *buf);
|
|
||||||
|
|
||||||
ssize_t st_sensors_sysfs_set_sampling_frequency(struct device *dev,
|
|
||||||
struct device_attribute *attr, const char *buf, size_t size);
|
|
||||||
|
|
||||||
ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev,
|
ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf);
|
struct device_attribute *attr, char *buf);
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,19 @@
|
||||||
|
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/iio/common/st_sensors.h>
|
#include <linux/iio/common/st_sensors.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
|
||||||
void st_sensors_i2c_configure(struct iio_dev *indio_dev,
|
void st_sensors_i2c_configure(struct iio_dev *indio_dev,
|
||||||
struct i2c_client *client, struct st_sensor_data *sdata);
|
struct i2c_client *client, struct st_sensor_data *sdata);
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
void st_sensors_of_i2c_probe(struct i2c_client *client,
|
||||||
|
const struct of_device_id *match);
|
||||||
|
#else
|
||||||
|
static inline void st_sensors_of_i2c_probe(struct i2c_client *client,
|
||||||
|
const struct of_device_id *match)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* ST_SENSORS_I2C_H */
|
#endif /* ST_SENSORS_I2C_H */
|
||||||
|
|
|
@ -157,13 +157,14 @@ int adis_single_conversion(struct iio_dev *indio_dev,
|
||||||
const struct iio_chan_spec *chan, unsigned int error_mask,
|
const struct iio_chan_spec *chan, unsigned int error_mask,
|
||||||
int *val);
|
int *val);
|
||||||
|
|
||||||
#define ADIS_VOLTAGE_CHAN(addr, si, chan, name, bits) { \
|
#define ADIS_VOLTAGE_CHAN(addr, si, chan, name, info_all, bits) { \
|
||||||
.type = IIO_VOLTAGE, \
|
.type = IIO_VOLTAGE, \
|
||||||
.indexed = 1, \
|
.indexed = 1, \
|
||||||
.channel = (chan), \
|
.channel = (chan), \
|
||||||
.extend_name = name, \
|
.extend_name = name, \
|
||||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||||
BIT(IIO_CHAN_INFO_SCALE), \
|
BIT(IIO_CHAN_INFO_SCALE), \
|
||||||
|
.info_mask_shared_by_all = info_all, \
|
||||||
.address = (addr), \
|
.address = (addr), \
|
||||||
.scan_index = (si), \
|
.scan_index = (si), \
|
||||||
.scan_type = { \
|
.scan_type = { \
|
||||||
|
@ -174,19 +175,20 @@ int adis_single_conversion(struct iio_dev *indio_dev,
|
||||||
}, \
|
}, \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ADIS_SUPPLY_CHAN(addr, si, bits) \
|
#define ADIS_SUPPLY_CHAN(addr, si, info_all, bits) \
|
||||||
ADIS_VOLTAGE_CHAN(addr, si, 0, "supply", bits)
|
ADIS_VOLTAGE_CHAN(addr, si, 0, "supply", info_all, bits)
|
||||||
|
|
||||||
#define ADIS_AUX_ADC_CHAN(addr, si, bits) \
|
#define ADIS_AUX_ADC_CHAN(addr, si, info_all, bits) \
|
||||||
ADIS_VOLTAGE_CHAN(addr, si, 1, NULL, bits)
|
ADIS_VOLTAGE_CHAN(addr, si, 1, NULL, info_all, bits)
|
||||||
|
|
||||||
#define ADIS_TEMP_CHAN(addr, si, bits) { \
|
#define ADIS_TEMP_CHAN(addr, si, info_all, bits) { \
|
||||||
.type = IIO_TEMP, \
|
.type = IIO_TEMP, \
|
||||||
.indexed = 1, \
|
.indexed = 1, \
|
||||||
.channel = 0, \
|
.channel = 0, \
|
||||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||||
BIT(IIO_CHAN_INFO_SCALE) | \
|
BIT(IIO_CHAN_INFO_SCALE) | \
|
||||||
BIT(IIO_CHAN_INFO_OFFSET), \
|
BIT(IIO_CHAN_INFO_OFFSET), \
|
||||||
|
.info_mask_shared_by_all = info_all, \
|
||||||
.address = (addr), \
|
.address = (addr), \
|
||||||
.scan_index = (si), \
|
.scan_index = (si), \
|
||||||
.scan_type = { \
|
.scan_type = { \
|
||||||
|
@ -197,13 +199,14 @@ int adis_single_conversion(struct iio_dev *indio_dev,
|
||||||
}, \
|
}, \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ADIS_MOD_CHAN(_type, mod, addr, si, info_sep, bits) { \
|
#define ADIS_MOD_CHAN(_type, mod, addr, si, info_sep, info_all, bits) { \
|
||||||
.type = (_type), \
|
.type = (_type), \
|
||||||
.modified = 1, \
|
.modified = 1, \
|
||||||
.channel2 = IIO_MOD_ ## mod, \
|
.channel2 = IIO_MOD_ ## mod, \
|
||||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||||
info_sep, \
|
info_sep, \
|
||||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
|
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
|
||||||
|
.info_mask_shared_by_all = info_all, \
|
||||||
.address = (addr), \
|
.address = (addr), \
|
||||||
.scan_index = (si), \
|
.scan_index = (si), \
|
||||||
.scan_type = { \
|
.scan_type = { \
|
||||||
|
@ -214,17 +217,17 @@ int adis_single_conversion(struct iio_dev *indio_dev,
|
||||||
}, \
|
}, \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ADIS_ACCEL_CHAN(mod, addr, si, info_sep, bits) \
|
#define ADIS_ACCEL_CHAN(mod, addr, si, info_sep, info_all, bits) \
|
||||||
ADIS_MOD_CHAN(IIO_ACCEL, mod, addr, si, info_sep, bits)
|
ADIS_MOD_CHAN(IIO_ACCEL, mod, addr, si, info_sep, info_all, bits)
|
||||||
|
|
||||||
#define ADIS_GYRO_CHAN(mod, addr, si, info_sep, bits) \
|
#define ADIS_GYRO_CHAN(mod, addr, si, info_sep, info_all, bits) \
|
||||||
ADIS_MOD_CHAN(IIO_ANGL_VEL, mod, addr, si, info_sep, bits)
|
ADIS_MOD_CHAN(IIO_ANGL_VEL, mod, addr, si, info_sep, info_all, bits)
|
||||||
|
|
||||||
#define ADIS_INCLI_CHAN(mod, addr, si, info_sep, bits) \
|
#define ADIS_INCLI_CHAN(mod, addr, si, info_sep, info_all, bits) \
|
||||||
ADIS_MOD_CHAN(IIO_INCLI, mod, addr, si, info_sep, bits)
|
ADIS_MOD_CHAN(IIO_INCLI, mod, addr, si, info_sep, info_all, bits)
|
||||||
|
|
||||||
#define ADIS_ROT_CHAN(mod, addr, si, info_sep, bits) \
|
#define ADIS_ROT_CHAN(mod, addr, si, info_sep, info_all, bits) \
|
||||||
ADIS_MOD_CHAN(IIO_ROT, mod, addr, si, info_sep, bits)
|
ADIS_MOD_CHAN(IIO_ROT, mod, addr, si, info_sep, info_all, bits)
|
||||||
|
|
||||||
#ifdef CONFIG_IIO_ADIS_LIB_BUFFER
|
#ifdef CONFIG_IIO_ADIS_LIB_BUFFER
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ enum iio_event_info {
|
||||||
IIO_EV_INFO_ENABLE,
|
IIO_EV_INFO_ENABLE,
|
||||||
IIO_EV_INFO_VALUE,
|
IIO_EV_INFO_VALUE,
|
||||||
IIO_EV_INFO_HYSTERESIS,
|
IIO_EV_INFO_HYSTERESIS,
|
||||||
|
IIO_EV_INFO_PERIOD,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum iio_event_direction {
|
enum iio_event_direction {
|
||||||
|
|
Loading…
Reference in a new issue