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:
Greg Kroah-Hartman 2014-07-13 12:31:47 -07:00
Родитель 01e1162946 90c5f2d1b8
Коммит db7c17ecbf
47 изменённых файлов: 1392 добавлений и 481 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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 @@ read_wai_error:
} }
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, &regval);
if (ret)
return ret;
*val = (regval & ITG3200_DLPF_CFG_MASK) ? 1000 : 8000;
ret = itg3200_read_reg_8(indio_dev,
ITG3200_REG_SAMPLE_RATE_DIV,
&regval);
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 @@ err_ret:
.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 @@ err_ret:
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

Просмотреть файл

@ -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
Просмотреть файл

@ -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 @@ read_error:
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 {

Просмотреть файл