summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-07-13 12:31:47 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-07-13 12:31:47 -0700
commitdb7c17ecbf4d6328597047c4e4d6e8914945477c (patch)
tree476ddb4200fd400f61d86893e97fb19a0e0bdfdb
parent01e1162946d4eb42119efa316ee01c4c50dc25ad (diff)
parent90c5f2d1b8212dde11a3dcc9e87ba3593beeb3ac (diff)
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.
-rw-r--r--Documentation/devicetree/bindings/i2c/trivial-devices.txt1
-rw-r--r--Documentation/devicetree/bindings/iio/st-sensors.txt54
-rw-r--r--drivers/iio/accel/mma8452.c6
-rw-r--r--drivers/iio/accel/st_accel_core.c12
-rw-r--r--drivers/iio/accel/st_accel_i2c.c51
-rw-r--r--drivers/iio/adc/Kconfig10
-rw-r--r--drivers/iio/adc/Makefile1
-rw-r--r--drivers/iio/adc/ad7291.c (renamed from drivers/staging/iio/adc/ad7291.c)107
-rw-r--r--drivers/iio/adc/xilinx-xadc-events.c6
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-attributes.c5
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_core.c64
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_i2c.c30
-rw-r--r--drivers/iio/dac/ad5504.c5
-rw-r--r--drivers/iio/dac/ad5624r_spi.c5
-rw-r--r--drivers/iio/dac/ad5686.c3
-rw-r--r--drivers/iio/gyro/adis16260.c124
-rw-r--r--drivers/iio/gyro/itg3200_core.c101
-rw-r--r--drivers/iio/gyro/st_gyro_core.c12
-rw-r--r--drivers/iio/gyro/st_gyro_i2c.c39
-rw-r--r--drivers/iio/imu/adis16400_buffer.c3
-rw-r--r--drivers/iio/imu/adis16400_core.c78
-rw-r--r--drivers/iio/imu/adis16480.c82
-rw-r--r--drivers/iio/industrialio-event.c1
-rw-r--r--drivers/iio/light/Kconfig24
-rw-r--r--drivers/iio/light/Makefile2
-rw-r--r--drivers/iio/light/isl29125.c347
-rw-r--r--drivers/iio/light/tcs3414.c405
-rw-r--r--drivers/iio/magnetometer/st_magn_core.c12
-rw-r--r--drivers/iio/magnetometer/st_magn_i2c.c23
-rw-r--r--drivers/iio/pressure/st_pressure_core.c27
-rw-r--r--drivers/iio/pressure/st_pressure_i2c.c23
-rw-r--r--drivers/staging/iio/Documentation/iio_event_monitor.c2
-rw-r--r--drivers/staging/iio/accel/adis16201_core.c14
-rw-r--r--drivers/staging/iio/accel/adis16203_core.c11
-rw-r--r--drivers/staging/iio/accel/adis16204_core.c12
-rw-r--r--drivers/staging/iio/accel/adis16209_core.c18
-rw-r--r--drivers/staging/iio/accel/adis16240_core.c12
-rw-r--r--drivers/staging/iio/adc/Kconfig9
-rw-r--r--drivers/staging/iio/adc/Makefile1
-rw-r--r--drivers/staging/iio/adc/ad7606_par.c37
-rw-r--r--drivers/staging/iio/frequency/ad9832.c2
-rw-r--r--drivers/staging/iio/trigger/iio-trig-bfin-timer.c31
-rw-r--r--include/linux/iio/common/st_sensors.h12
-rw-r--r--include/linux/iio/common/st_sensors_i2c.h11
-rw-r--r--include/linux/iio/imu/adis.h33
-rw-r--r--include/linux/iio/types.h1
-rw-r--r--include/linux/platform_data/ad7291.h (renamed from drivers/staging/iio/adc/ad7291.h)0
47 files changed, 1390 insertions, 479 deletions
diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
index bef86e57c388..1a794213f7d1 100644
--- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
+++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
@@ -50,6 +50,7 @@ epson,rx8581 I2C-BUS INTERFACE REAL TIME CLOCK MODULE
fsl,mag3110 MAG3110: Xtrinsic High Accuracy, 3D Magnetometer
fsl,mc13892 MC13892: Power Management Integrated Circuit (PMIC) for i.MX35/51
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,sgtl5000 SGTL5000: Ultra Low-Power Audio Codec
gmt,g751 G751: Digital Temperature Sensor and Thermal Watchdog with Two-Wire Interface
diff --git a/Documentation/devicetree/bindings/iio/st-sensors.txt b/Documentation/devicetree/bindings/iio/st-sensors.txt
new file mode 100644
index 000000000000..a7a0a15913ad
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/st-sensors.txt
@@ -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
diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c
index 17aeea170566..9231f8a65e79 100644
--- a/drivers/iio/accel/mma8452.c
+++ b/drivers/iio/accel/mma8452.c
@@ -423,9 +423,15 @@ static const struct i2c_device_id 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 = {
.driver = {
.name = "mma8452",
+ .of_match_table = of_match_ptr(mma8452_dt_ids),
.pm = MMA8452_PM_OPS,
},
.probe = mma8452_probe,
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
index a2abf7c2ce3b..087864854c61 100644
--- a/drivers/iio/accel/st_accel_core.c
+++ b/drivers/iio/accel/st_accel_core.c
@@ -393,6 +393,9 @@ static int st_accel_read_raw(struct iio_dev *indio_dev,
*val = 0;
*val2 = adata->current_fullscale->gain;
return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = adata->odr;
+ return IIO_VAL_INT;
default:
return -EINVAL;
}
@@ -410,6 +413,13 @@ static int st_accel_write_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE:
err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
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:
return -EINVAL;
}
@@ -417,14 +427,12 @@ static int st_accel_write_raw(struct iio_dev *indio_dev,
return err;
}
-static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_accel_scale_available);
static struct attribute *st_accel_attributes[] = {
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_in_accel_scale_available.dev_attr.attr,
- &iio_dev_attr_sampling_frequency.dev_attr.attr,
NULL,
};
diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c
index d7bedbdfc81d..7164aeff3ab1 100644
--- a/drivers/iio/accel/st_accel_i2c.c
+++ b/drivers/iio/accel/st_accel_i2c.c
@@ -18,6 +18,55 @@
#include <linux/iio/common/st_sensors_i2c.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,
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->dev = &client->dev;
+ st_sensors_of_i2c_probe(client, st_accel_of_match);
st_sensors_i2c_configure(indio_dev, client, adata);
@@ -67,6 +117,7 @@ static struct i2c_driver st_accel_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "st-accel-i2c",
+ .of_match_table = of_match_ptr(st_accel_of_match),
},
.probe = st_accel_i2c_probe,
.remove = st_accel_i2c_remove,
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 20a7073f1dd6..11b048a59fde 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -20,6 +20,16 @@ config AD7266
Say yes here to build support for Analog Devices AD7265 and AD7266
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
tristate "Analog Devices AD7298 ADC driver"
depends on SPI
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 38cf5c3f5631..ad81b512aa3d 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -5,6 +5,7 @@
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
obj-$(CONFIG_AD7266) += ad7266.o
+obj-$(CONFIG_AD7291) += ad7291.o
obj-$(CONFIG_AD7298) += ad7298.o
obj-$(CONFIG_AD7923) += ad7923.o
obj-$(CONFIG_AD7476) += ad7476.o
diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/iio/adc/ad7291.c
index 7194bd138762..c0eabf156702 100644
--- a/drivers/staging/iio/adc/ad7291.c
+++ b/drivers/iio/adc/ad7291.c
@@ -6,22 +6,22 @@
* Licensed under the GPL-2 or later.
*/
-#include <linux/interrupt.h>
#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
+#include <linux/err.h>
#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.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/sysfs.h>
#include <linux/iio/events.h>
-#include "ad7291.h"
+#include <linux/platform_data/ad7291.h>
/*
* Simplified handling
@@ -31,7 +31,6 @@
* is in the read mask.
*
* The noise-delayed bit as per datasheet suggestion is always enabled.
- *
*/
/*
@@ -47,33 +46,38 @@
#define AD7291_VOLTAGE_ALERT_STATUS 0x1F
#define AD7291_T_ALERT_STATUS 0x20
+#define AD7291_BITS 12
#define AD7291_VOLTAGE_LIMIT_COUNT 8
/*
* AD7291 command
*/
-#define AD7291_AUTOCYCLE (1 << 0)
-#define AD7291_RESET (1 << 1)
-#define AD7291_ALERT_CLEAR (1 << 2)
-#define AD7291_ALERT_POLARITY (1 << 3)
-#define AD7291_EXT_REF (1 << 4)
-#define AD7291_NOISE_DELAY (1 << 5)
-#define AD7291_T_SENSE_MASK (1 << 7)
-#define AD7291_VOLTAGE_MASK 0xFF00
-#define AD7291_VOLTAGE_OFFSET 0x8
+#define AD7291_AUTOCYCLE BIT(0)
+#define AD7291_RESET BIT(1)
+#define AD7291_ALERT_CLEAR BIT(2)
+#define AD7291_ALERT_POLARITY BIT(3)
+#define AD7291_EXT_REF BIT(4)
+#define AD7291_NOISE_DELAY BIT(5)
+#define AD7291_T_SENSE_MASK BIT(7)
+#define AD7291_VOLTAGE_MASK GENMASK(15, 8)
+#define AD7291_VOLTAGE_OFFSET 8
/*
* AD7291 value masks
*/
-#define AD7291_CHANNEL_MASK 0xF000
-#define AD7291_BITS 12
-#define AD7291_VALUE_MASK 0xFFF
-#define AD7291_T_VALUE_SIGN 0x400
-#define AD7291_T_VALUE_FLOAT_OFFSET 2
-#define AD7291_T_VALUE_FLOAT_MASK 0x2
+#define AD7291_VALUE_MASK GENMASK(11, 0)
+
+/*
+ * AD7291 alert register bits
+ */
+#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 i2c_client *client;
@@ -129,14 +133,14 @@ static irqreturn_t ad7291_event_handler(int irq, void *private)
ad7291_i2c_write(chip, AD7291_COMMAND, command);
/* 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_UNMOD_EVENT_CODE(IIO_TEMP,
0,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING),
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_UNMOD_EVENT_CODE(IIO_TEMP,
0,
@@ -144,18 +148,18 @@ static irqreturn_t ad7291_event_handler(int irq, void *private)
IIO_EV_DIR_RISING),
timestamp);
- for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT*2; i += 2) {
- if (v_status & (1 << i))
+ for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT; i++) {
+ if (v_status & AD7291_V_LOW(i))
iio_push_event(indio_dev,
IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
- i/2,
+ i,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING),
timestamp);
- if (v_status & (1 << (i + 1)))
+ if (v_status & AD7291_V_HIGH(i))
iio_push_event(indio_dev,
IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
- i/2,
+ i,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING),
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,
- enum iio_event_direction dir, enum iio_event_info info)
+ enum iio_event_direction dir,
+ enum iio_event_info info)
{
unsigned int offset;
@@ -174,7 +179,7 @@ static unsigned int ad7291_threshold_reg(const struct iio_chan_spec *chan,
offset = chan->channel;
break;
case IIO_TEMP:
- offset = 8;
+ offset = AD7291_VOLTAGE_OFFSET;
break;
default:
return 0;
@@ -182,14 +187,14 @@ static unsigned int ad7291_threshold_reg(const struct iio_chan_spec *chan,
switch (info) {
case IIO_EV_INFO_VALUE:
- if (dir == IIO_EV_DIR_FALLING)
- return AD7291_DATA_HIGH(offset);
- else
- return AD7291_DATA_LOW(offset);
+ if (dir == IIO_EV_DIR_FALLING)
+ return AD7291_DATA_HIGH(offset);
+ else
+ return AD7291_DATA_LOW(offset);
case IIO_EV_INFO_HYSTERESIS:
- return AD7291_HYST(offset);
+ return AD7291_HYST(offset);
default:
- break;
+ break;
}
return 0;
}
@@ -206,7 +211,7 @@ static int ad7291_read_event_value(struct iio_dev *indio_dev,
u16 uval;
ret = ad7291_i2c_read(chip, ad7291_threshold_reg(chan, dir, info),
- &uval);
+ &uval);
if (ret < 0)
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),
- val);
+ val);
}
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)
{
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) {
case IIO_VOLTAGE:
- if (chip->c_mask & (1 << (15 - chan->channel)))
- return 1;
- else
- return 0;
+ return !!(chip->c_mask & BIT(15 - chan->channel));
case IIO_TEMP:
/* always on */
return 1;
@@ -336,7 +340,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
}
/* Enable this channel alone */
regval = chip->command & (~AD7291_VOLTAGE_MASK);
- regval |= 1 << (15 - chan->channel);
+ regval |= BIT(15 - chan->channel);
ret = ad7291_i2c_write(chip, AD7291_COMMAND, regval);
if (ret < 0) {
mutex_unlock(&chip->state_lock);
@@ -344,7 +348,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
}
/* Read voltage */
ret = i2c_smbus_read_word_swapped(chip->client,
- AD7291_VOLTAGE);
+ AD7291_VOLTAGE);
if (ret < 0) {
mutex_unlock(&chip->state_lock);
return ret;
@@ -355,7 +359,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
case IIO_TEMP:
/* Assumes tsense bit of command register always set */
ret = i2c_smbus_read_word_swapped(chip->client,
- AD7291_T_SENSE);
+ AD7291_T_SENSE);
if (ret < 0)
return ret;
*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:
ret = i2c_smbus_read_word_swapped(chip->client,
- AD7291_T_AVERAGE);
+ AD7291_T_AVERAGE);
if (ret < 0)
return ret;
*val = sign_extend32(ret, 11);
@@ -375,6 +379,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
case IIO_VOLTAGE:
if (chip->reg) {
int vref;
+
vref = regulator_get_voltage(chip->reg);
if (vref < 0)
return vref;
@@ -460,7 +465,7 @@ static const struct iio_info ad7291_info = {
};
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_chip_info *chip;
diff --git a/drivers/iio/adc/xilinx-xadc-events.c b/drivers/iio/adc/xilinx-xadc-events.c
index 3e7f0d7a80c3..edcf3aabd70d 100644
--- a/drivers/iio/adc/xilinx-xadc-events.c
+++ b/drivers/iio/adc/xilinx-xadc-events.c
@@ -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)
{
const struct iio_chan_spec *chan;
- unsigned int offset;
/* Temperature threshold error, we don't handle this yet */
if (event == 0)
return;
- if (event < 4)
- offset = event;
- else
- offset = event + 4;
-
chan = xadc_event_to_channel(indio_dev, event);
if (chan->type == IIO_TEMP) {
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
index 403dd3d8986e..25b01e156d82 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
@@ -26,12 +26,12 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
-struct {
+static struct {
u32 usage_id;
int unit; /* 0 for default others from HID sensor spec */
int scale_val0; /* scale, whole number */
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,
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);
+static
int hid_sensor_get_reporting_interval(struct hid_sensor_hub_device *hsdev,
u32 usage_id,
struct hid_sensor_common *st)
diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c
index e8b932fed70e..8a4ec00a91a0 100644
--- a/drivers/iio/common/st_sensors/st_sensors_core.c
+++ b/drivers/iio/common/st_sensors/st_sensors_core.c
@@ -14,8 +14,8 @@
#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/regulator/consumer.h>
+#include <linux/of.h>
#include <asm/unaligned.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;
}
+#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,
struct st_sensors_platform_data *pdata)
{
struct st_sensor_data *sdata = iio_priv(indio_dev);
+ struct st_sensors_platform_data *of_pdata;
int err = 0;
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)
err = st_sensors_set_drdy_int_pin(indio_dev, pdata);
@@ -463,35 +496,6 @@ read_wai_error:
}
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,
struct device_attribute *attr, char *buf)
{
diff --git a/drivers/iio/common/st_sensors/st_sensors_i2c.c b/drivers/iio/common/st_sensors/st_sensors_i2c.c
index 38af9440c103..bb6f3085f57b 100644
--- a/drivers/iio/common/st_sensors/st_sensors_i2c.c
+++ b/drivers/iio/common/st_sensors/st_sensors_i2c.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/iio/iio.h>
+#include <linux/of_device.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);
+#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_DESCRIPTION("STMicroelectronics ST-sensors i2c driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c
index c917dd24090a..581ec141de3d 100644
--- a/drivers/iio/dac/ad5504.c
+++ b/drivers/iio/dac/ad5504.c
@@ -125,7 +125,6 @@ static int ad5504_write_raw(struct iio_dev *indio_dev,
long mask)
{
struct ad5504_state *st = iio_priv(indio_dev);
- int ret;
switch (mask) {
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);
default:
- ret = -EINVAL;
+ return -EINVAL;
}
-
- return -EINVAL;
}
static const char * const ad5504_powerdown_modes[] = {
diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c
index e8199cce2aea..61bb9d4239ea 100644
--- a/drivers/iio/dac/ad5624r_spi.c
+++ b/drivers/iio/dac/ad5624r_spi.c
@@ -67,7 +67,6 @@ static int ad5624r_write_raw(struct iio_dev *indio_dev,
long mask)
{
struct ad5624r_state *st = iio_priv(indio_dev);
- int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
@@ -79,10 +78,8 @@ static int ad5624r_write_raw(struct iio_dev *indio_dev,
chan->address, val,
chan->scan_type.shift);
default:
- ret = -EINVAL;
+ return -EINVAL;
}
-
- return -EINVAL;
}
static const char * const ad5624r_powerdown_modes[] = {
diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 17aca4d9bd06..f57562aa396f 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -313,7 +313,7 @@ static int ad5686_probe(struct spi_device *spi)
{
struct ad5686_state *st;
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));
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->num_channels = AD5686_DAC_CHANNELS;
- regdone = 1;
ret = ad5686_spi_write(st, AD5686_CMD_INTERNAL_REFER_SETUP, 0,
!!voltage_uv, 0);
if (ret)
diff --git a/drivers/iio/gyro/adis16260.c b/drivers/iio/gyro/adis16260.c
index 22b6fb80fa1a..75fe0edd3d0f 100644
--- a/drivers/iio/gyro/adis16260.c
+++ b/drivers/iio/gyro/adis16260.c
@@ -101,65 +101,6 @@
#define ADIS16260_SCAN_TEMP 3
#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 */
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;
}
-static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
- adis16260_read_frequency,
- adis16260_write_frequency);
-
static const struct iio_chan_spec adis16260_channels[] = {
ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,
BIT(IIO_CHAN_INFO_CALIBBIAS) |
- BIT(IIO_CHAN_INFO_CALIBSCALE), 14),
- ADIS_INCLI_CHAN(X, ADIS16260_ANGL_OUT, ADIS16260_SCAN_ANGL, 0, 14),
- ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP, 12),
- ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY, 12),
- ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC, 12),
+ BIT(IIO_CHAN_INFO_CALIBSCALE),
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),
+ ADIS_INCLI_CHAN(X, ADIS16260_ANGL_OUT, ADIS16260_SCAN_ANGL, 0,
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),
+ 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),
};
@@ -258,6 +200,20 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
*val = val16;
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;
}
@@ -269,7 +225,9 @@ static int adis16260_write_raw(struct iio_dev *indio_dev,
long mask)
{
struct adis *adis = iio_priv(indio_dev);
+ int ret;
u8 addr;
+ u8 t;
switch (mask) {
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];
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;
}
-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 = {
- .attrs = &adis16260_attribute_group,
.read_raw = &adis16260_read_raw,
.write_raw = &adis16260_write_raw,
.update_scan_mode = adis_update_scan_mode,
diff --git a/drivers/iio/gyro/itg3200_core.c b/drivers/iio/gyro/itg3200_core.c
index 8295e318399f..6a8020d48140 100644
--- a/drivers/iio/gyro/itg3200_core.c
+++ b/drivers/iio/gyro/itg3200_core.c
@@ -90,6 +90,7 @@ static int itg3200_read_raw(struct iio_dev *indio_dev,
{
int ret = 0;
u8 reg;
+ u8 regval;
switch (info) {
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 */
*val = 23000;
return IIO_VAL_INT;
- default:
- return -EINVAL;
- }
-}
-
-static ssize_t itg3200_read_frequency(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- 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;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_DLPF, &regval);
+ if (ret)
+ return ret;
- sps = (val & ITG3200_DLPF_CFG_MASK) ? 1000 : 8000;
+ *val = (regval & ITG3200_DLPF_CFG_MASK) ? 1000 : 8000;
- ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_SAMPLE_RATE_DIV, &val);
- if (ret)
- return ret;
+ ret = itg3200_read_reg_8(indio_dev,
+ ITG3200_REG_SAMPLE_RATE_DIV,
+ &regval);
+ if (ret)
+ return ret;
- sps /= val + 1;
+ *val /= regval + 1;
+ return IIO_VAL_INT;
- return sprintf(buf, "%d\n", sps);
+ default:
+ return -EINVAL;
+ }
}
-static ssize_t itg3200_write_frequency(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
+static int itg3200_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- unsigned val;
int ret;
u8 t;
- ret = kstrtouint(buf, 10, &val);
- if (ret)
- return ret;
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ 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);
- if (ret)
- goto err_ret;
+ ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_DLPF, &t);
+ if (ret) {
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
+ }
+ t = ((t & ITG3200_DLPF_CFG_MASK) ? 1000u : 8000u) / val - 1;
- if (val == 0) {
- ret = -EINVAL;
- goto err_ret;
- }
- t = ((t & ITG3200_DLPF_CFG_MASK) ? 1000u : 8000u) / val - 1;
+ ret = itg3200_write_reg_8(indio_dev,
+ ITG3200_REG_SAMPLE_RATE_DIV,
+ t);
- ret = itg3200_write_reg_8(indio_dev, ITG3200_REG_SAMPLE_RATE_DIV, t);
-
-err_ret:
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
- return ret ? ret : len;
+ default:
+ return -EINVAL;
+ }
}
/*
@@ -255,6 +251,7 @@ err_ret:
.channel2 = IIO_MOD_ ## _mod, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.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, \
.scan_index = ITG3200_SCAN_GYRO_ ## _mod, \
.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_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
.address = ITG3200_REG_TEMP_OUT_H,
.scan_index = ITG3200_SCAN_TEMP,
.scan_type = ITG3200_ST,
@@ -277,22 +275,9 @@ static const struct iio_chan_spec itg3200_channels[] = {
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 = {
- .attrs = &itg3200_attribute_group,
.read_raw = &itg3200_read_raw,
+ .write_raw = &itg3200_write_raw,
.driver_module = THIS_MODULE,
};
diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c
index ed74a9069989..f156fc6c5c6c 100644
--- a/drivers/iio/gyro/st_gyro_core.c
+++ b/drivers/iio/gyro/st_gyro_core.c
@@ -245,6 +245,9 @@ static int st_gyro_read_raw(struct iio_dev *indio_dev,
*val = 0;
*val2 = gdata->current_fullscale->gain;
return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = gdata->odr;
+ return IIO_VAL_INT;
default:
return -EINVAL;
}
@@ -262,6 +265,13 @@ static int st_gyro_write_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE:
err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
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:
err = -EINVAL;
}
@@ -269,14 +279,12 @@ static int st_gyro_write_raw(struct iio_dev *indio_dev,
return err;
}
-static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_anglvel_scale_available);
static struct attribute *st_gyro_attributes[] = {
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_in_anglvel_scale_available.dev_attr.attr,
- &iio_dev_attr_sampling_frequency.dev_attr.attr,
NULL,
};
diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c
index 23c12f361b05..8fa0ad2ef4ef 100644
--- a/drivers/iio/gyro/st_gyro_i2c.c
+++ b/drivers/iio/gyro/st_gyro_i2c.c
@@ -18,6 +18,43 @@
#include <linux/iio/common/st_sensors_i2c.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,
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->dev = &client->dev;
+ st_sensors_of_i2c_probe(client, st_gyro_of_match);
st_sensors_i2c_configure(indio_dev, client, gdata);
@@ -65,6 +103,7 @@ static struct i2c_driver st_gyro_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "st-gyro-i2c",
+ .of_match_table = of_match_ptr(st_gyro_of_match),
},
.probe = st_gyro_i2c_probe,
.remove = st_gyro_i2c_remove,
diff --git a/drivers/iio/imu/adis16400_buffer.c b/drivers/iio/imu/adis16400_buffer.c
index f2cf829e5df1..6e727ffe5262 100644
--- a/drivers/iio/imu/adis16400_buffer.c
+++ b/drivers/iio/imu/adis16400_buffer.c
@@ -18,7 +18,7 @@ int adis16400_update_scan_mode(struct iio_dev *indio_dev,
{
struct adis16400_state *st = iio_priv(indio_dev);
struct adis *adis = &st->adis;
- uint16_t *tx, *rx;
+ uint16_t *tx;
if (st->variant->flags & ADIS16400_NO_BURST)
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)
return -ENOMEM;
- rx = adis->buffer;
tx = adis->buffer + indio_dev->scan_bytes;
tx[0] = ADIS_READ_REG(ADIS16400_GLOB_CMD);
diff --git a/drivers/iio/imu/adis16400_core.c b/drivers/iio/imu/adis16400_core.c
index 433583b6f800..b70873de04ea 100644
--- a/drivers/iio/imu/adis16400_core.c
+++ b/drivers/iio/imu/adis16400_core.c
@@ -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);
}
-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[] = {
[0] = 2, /* Special case */
[1] = 6,
@@ -260,30 +245,6 @@ static int adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val)
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 */
static int adis16400_stop_device(struct iio_dev *indio_dev)
{
@@ -350,10 +311,6 @@ err_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[] = {
[ADIS16400_SCAN_GYRO_X] = ADIS16400_XGYRO_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);
mutex_unlock(&indio_dev->mlock);
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:
return -EINVAL;
}
@@ -474,6 +441,13 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
if (ret < 0)
return ret;
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:
return -EINVAL;
}
@@ -486,6 +460,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
.extend_name = name, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.address = (addr), \
.scan_index = (si), \
.scan_type = { \
@@ -511,6 +486,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
BIT(IIO_CHAN_INFO_CALIBBIAS), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.address = addr, \
.scan_index = ADIS16400_SCAN_GYRO_ ## mod, \
.scan_type = { \
@@ -530,6 +506,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
BIT(IIO_CHAN_INFO_CALIBBIAS), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.address = (addr), \
.scan_index = ADIS16400_SCAN_ACC_ ## mod, \
.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_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.address = (addr), \
.scan_index = ADIS16400_SCAN_MAGN_ ## mod, \
.scan_type = { \
@@ -573,6 +551,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
BIT(IIO_CHAN_INFO_SCALE), \
.info_mask_shared_by_type = \
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.address = (addr), \
.scan_index = ADIS16350_SCAN_TEMP_ ## mod, \
.scan_type = { \
@@ -591,6 +570,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_OFFSET) | \
BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.address = (addr), \
.scan_index = ADIS16350_SCAN_TEMP_X, \
.scan_type = { \
@@ -608,6 +588,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
.channel2 = IIO_MOD_ ## mod, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.address = (addr), \
.scan_index = ADIS16300_SCAN_INCLI_ ## mod, \
.scan_type = { \
@@ -649,6 +630,7 @@ static const struct iio_chan_spec adis16448_channels[] = {
.type = IIO_PRESSURE,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.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,
.scan_index = ADIS16400_SCAN_BARO,
.scan_type = {
@@ -704,15 +686,6 @@ static const struct iio_chan_spec adis16334_channels[] = {
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[] = {
[ADIS16300] = {
.channels = adis16300_channels,
@@ -813,7 +786,6 @@ static const struct iio_info adis16400_info = {
.driver_module = THIS_MODULE,
.read_raw = &adis16400_read_raw,
.write_raw = &adis16400_write_raw,
- .attrs = &adis16400_attribute_group,
.update_scan_mode = adis16400_update_scan_mode,
.debugfs_reg_access = adis_debugfs_reg_access,
};
diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c
index dd4206cac62d..989605dd6f78 100644
--- a/drivers/iio/imu/adis16480.c
+++ b/drivers/iio/imu/adis16480.c
@@ -257,11 +257,16 @@ static int adis16480_debugfs_init(struct iio_dev *indio_dev)
#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;
- t = 2460000 / freq;
+ t = val * 1000 + val2 / 1000;
+ if (t <= 0)
+ return -EINVAL;
+
+ t = 2460000 / t;
if (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);
}
-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;
int ret;
+ unsigned freq;
ret = adis_read_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, &t);
if (ret < 0)
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 {
ADIS16480_SCAN_GYRO_X,
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);
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
return adis16480_get_filter_freq(indio_dev, chan, val);
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return adis16480_get_freq(indio_dev, val, val2);
default:
return -EINVAL;
}
@@ -586,6 +552,9 @@ static int adis16480_write_raw(struct iio_dev *indio_dev,
return adis16480_set_calibscale(indio_dev, chan, val);
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
return adis16480_set_filter_freq(indio_dev, chan, val);
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return adis16480_set_freq(indio_dev, val, val2);
+
default:
return -EINVAL;
}
@@ -600,6 +569,7 @@ static int adis16480_write_raw(struct iio_dev *indio_dev,
BIT(IIO_CHAN_INFO_CALIBBIAS) | \
_info_sep, \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.address = (_address), \
.scan_index = (_si), \
.scan_type = { \
@@ -638,6 +608,7 @@ static int adis16480_write_raw(struct iio_dev *indio_dev,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_CALIBBIAS) | \
BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.address = ADIS16480_REG_BAROM_OUT, \
.scan_index = ADIS16480_SCAN_BARO, \
.scan_type = { \
@@ -655,6 +626,7 @@ static int adis16480_write_raw(struct iio_dev *indio_dev,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_OFFSET), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.address = ADIS16480_REG_TEMP_OUT, \
.scan_index = ADIS16480_SCAN_TEMP, \
.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 = {
- .attrs = &adis16480_attribute_group,
.read_raw = &adis16480_read_raw,
.write_raw = &adis16480_write_raw,
.update_scan_mode = adis_update_scan_mode,
diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c
index 258a973a1fb8..35a5b0311dae 100644
--- a/drivers/iio/industrialio-event.c
+++ b/drivers/iio/industrialio-event.c
@@ -209,6 +209,7 @@ static const char * const iio_ev_info_text[] = {
[IIO_EV_INFO_ENABLE] = "en",
[IIO_EV_INFO_VALUE] = "value",
[IIO_EV_INFO_HYSTERESIS] = "hysteresis",
+ [IIO_EV_INFO_PERIOD] = "period",
};
static enum iio_event_direction iio_ev_attr_dir(struct iio_dev_attr *attr)
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index c89740d4748f..bf05ca5b0a57 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -62,6 +62,18 @@ config GP2AP020A00F
To compile this driver as a module, choose M here: the
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
depends on HID_SENSOR_HUB
select IIO_BUFFER
@@ -116,6 +128,18 @@ config LTR501
This driver can also be built as a module. If so, the module
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
tristate "TAOS TCS3472 color light-to-digital converter"
depends on I2C
diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
index 3eb36e5151fa..8b8c09f9c1f8 100644
--- a/drivers/iio/light/Makefile
+++ b/drivers/iio/light/Makefile
@@ -10,9 +10,11 @@ obj-$(CONFIG_CM36651) += cm36651.o
obj-$(CONFIG_GP2AP020A00F) += gp2ap020a00f.o
obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o
obj-$(CONFIG_HID_SENSOR_PROX) += hid-sensor-prox.o
+obj-$(CONFIG_ISL29125) += isl29125.o
obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o
obj-$(CONFIG_LTR501) += ltr501.o
obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o
+obj-$(CONFIG_TCS3414) += tcs3414.o
obj-$(CONFIG_TCS3472) += tcs3472.o
obj-$(CONFIG_TSL4531) += tsl4531.o
obj-$(CONFIG_VCNL4000) += vcnl4000.o
diff --git a/drivers/iio/light/isl29125.c b/drivers/iio/light/isl29125.c
new file mode 100644
index 000000000000..c82f4a6f8464
--- /dev/null
+++ b/drivers/iio/light/isl29125.c
@@ -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");
diff --git a/drivers/iio/light/tcs3414.c b/drivers/iio/light/tcs3414.c
new file mode 100644
index 000000000000..a9e449b0be0c
--- /dev/null
+++ b/drivers/iio/light/tcs3414.c
@@ -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");
diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c
index 240a21dd0c61..a4b64130ac2f 100644
--- a/drivers/iio/magnetometer/st_magn_core.c
+++ b/drivers/iio/magnetometer/st_magn_core.c
@@ -299,6 +299,9 @@ static int st_magn_read_raw(struct iio_dev *indio_dev,
else
*val2 = mdata->current_fullscale->gain;
return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = mdata->odr;
+ return IIO_VAL_INT;
default:
return -EINVAL;
}
@@ -316,6 +319,13 @@ static int st_magn_write_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE:
err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
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:
err = -EINVAL;
}
@@ -323,14 +333,12 @@ static int st_magn_write_raw(struct iio_dev *indio_dev,
return err;
}
-static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_magn_scale_available);
static struct attribute *st_magn_attributes[] = {
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_in_magn_scale_available.dev_attr.attr,
- &iio_dev_attr_sampling_frequency.dev_attr.attr,
NULL,
};
diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c
index 892e0feeb5c1..689250058442 100644
--- a/drivers/iio/magnetometer/st_magn_i2c.c
+++ b/drivers/iio/magnetometer/st_magn_i2c.c
@@ -18,6 +18,27 @@
#include <linux/iio/common/st_sensors_i2c.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,
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->dev = &client->dev;
+ st_sensors_of_i2c_probe(client, st_magn_of_match);
st_sensors_i2c_configure(indio_dev, client, mdata);
@@ -61,6 +83,7 @@ static struct i2c_driver st_magn_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "st-magn-i2c",
+ .of_match_table = of_match_ptr(st_magn_of_match),
},
.probe = st_magn_i2c_probe,
.remove = st_magn_i2c_remove,
diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c
index cd7e01f3a93b..473d914ef470 100644
--- a/drivers/iio/pressure/st_pressure_core.c
+++ b/drivers/iio/pressure/st_pressure_core.c
@@ -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,
struct iio_chan_spec const *ch, int *val,
int *val2, long mask)
@@ -349,6 +370,9 @@ static int st_press_read_raw(struct iio_dev *indio_dev,
}
return IIO_VAL_FRACTIONAL;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = pdata->odr;
+ return IIO_VAL_INT;
default:
return -EINVAL;
}
@@ -357,12 +381,10 @@ read_error:
return err;
}
-static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
static struct attribute *st_press_attributes[] = {
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
- &iio_dev_attr_sampling_frequency.dev_attr.attr,
NULL,
};
@@ -374,6 +396,7 @@ static const struct iio_info press_info = {
.driver_module = THIS_MODULE,
.attrs = &st_press_attribute_group,
.read_raw = &st_press_read_raw,
+ .write_raw = &st_press_write_raw,
};
#ifdef CONFIG_IIO_TRIGGER
diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c
index 3cd73e39b840..acaf165260bb 100644
--- a/drivers/iio/pressure/st_pressure_i2c.c
+++ b/drivers/iio/pressure/st_pressure_i2c.c
@@ -18,6 +18,27 @@
#include <linux/iio/common/st_sensors_i2c.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,
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->dev = &client->dev;
+ st_sensors_of_i2c_probe(client, st_press_of_match);
st_sensors_i2c_configure(indio_dev, client, pdata);
@@ -60,6 +82,7 @@ static struct i2c_driver st_press_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "st-press-i2c",
+ .of_match_table = of_match_ptr(st_press_of_match),
},
.probe = st_press_i2c_probe,
.remove = st_press_i2c_remove,
diff --git a/drivers/staging/iio/Documentation/iio_event_monitor.c b/drivers/staging/iio/Documentation/iio_event_monitor.c
index cb35a97f00c3..569d6f8face5 100644
--- a/drivers/staging/iio/Documentation/iio_event_monitor.c
+++ b/drivers/staging/iio/Documentation/iio_event_monitor.c
@@ -122,8 +122,6 @@ static bool event_is_known(struct iio_event_data *event)
case IIO_MOD_LIGHT_IR:
case IIO_MOD_ROOT_SUM_SQUARED_X_Y:
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_RED:
case IIO_MOD_LIGHT_GREEN:
diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c
index 2105576fa77c..50ba1fa7f98a 100644
--- a/drivers/staging/iio/accel/adis16201_core.c
+++ b/drivers/staging/iio/accel/adis16201_core.c
@@ -131,17 +131,17 @@ static int adis16201_write_raw(struct iio_dev *indio_dev,
}
static const struct iio_chan_spec adis16201_channels[] = {
- ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT, ADIS16201_SCAN_SUPPLY, 12),
- ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT, ADIS16201_SCAN_TEMP, 12),
+ ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT, ADIS16201_SCAN_SUPPLY, 0, 12),
+ ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT, ADIS16201_SCAN_TEMP, 0, 12),
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,
- BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
- ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC, ADIS16201_SCAN_AUX_ADC, 12),
+ BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
+ ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC, ADIS16201_SCAN_AUX_ADC, 0, 12),
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,
- BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
+ BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
IIO_CHAN_SOFT_TIMESTAMP(7)
};
diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c
index 409a28ed9043..f472137b0069 100644
--- a/drivers/staging/iio/accel/adis16203_core.c
+++ b/drivers/staging/iio/accel/adis16203_core.c
@@ -99,13 +99,14 @@ static int adis16203_read_raw(struct iio_dev *indio_dev,
}
static const struct iio_chan_spec adis16203_channels[] = {
- ADIS_SUPPLY_CHAN(ADIS16203_SUPPLY_OUT, ADIS16203_SCAN_SUPPLY, 12),
- ADIS_AUX_ADC_CHAN(ADIS16203_AUX_ADC, ADIS16203_SCAN_AUX_ADC, 12),
+ ADIS_SUPPLY_CHAN(ADIS16203_SUPPLY_OUT, ADIS16203_SCAN_SUPPLY, 0, 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,
- BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
+ BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
/* Fixme: Not what it appears to be - see data sheet */
- ADIS_INCLI_CHAN(Y, ADIS16203_YINCL_OUT, ADIS16203_SCAN_INCLI_Y, 0, 14),
- ADIS_TEMP_CHAN(ADIS16203_TEMP_OUT, ADIS16203_SCAN_TEMP, 12),
+ ADIS_INCLI_CHAN(Y, ADIS16203_YINCL_OUT, ADIS16203_SCAN_INCLI_Y,
+ 0, 0, 14),
+ ADIS_TEMP_CHAN(ADIS16203_TEMP_OUT, ADIS16203_SCAN_TEMP, 0, 12),
IIO_CHAN_SOFT_TIMESTAMP(5),
};
diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c
index b8ea76857cd6..19eaebc77d7a 100644
--- a/drivers/staging/iio/accel/adis16204_core.c
+++ b/drivers/staging/iio/accel/adis16204_core.c
@@ -136,15 +136,15 @@ static int adis16204_write_raw(struct iio_dev *indio_dev,
}
static const struct iio_chan_spec adis16204_channels[] = {
- ADIS_SUPPLY_CHAN(ADIS16204_SUPPLY_OUT, ADIS16204_SCAN_SUPPLY, 12),
- ADIS_AUX_ADC_CHAN(ADIS16204_AUX_ADC, ADIS16204_SCAN_AUX_ADC, 12),
- ADIS_TEMP_CHAN(ADIS16204_TEMP_OUT, ADIS16204_SCAN_TEMP, 12),
+ ADIS_SUPPLY_CHAN(ADIS16204_SUPPLY_OUT, ADIS16204_SCAN_SUPPLY, 0, 12),
+ ADIS_AUX_ADC_CHAN(ADIS16204_AUX_ADC, ADIS16204_SCAN_AUX_ADC, 0, 12),
+ ADIS_TEMP_CHAN(ADIS16204_TEMP_OUT, ADIS16204_SCAN_TEMP, 0, 12),
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,
- 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,
- 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),
};
diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c
index 4492e51d8886..374dc6edbcf5 100644
--- a/drivers/staging/iio/accel/adis16209_core.c
+++ b/drivers/staging/iio/accel/adis16209_core.c
@@ -130,16 +130,18 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
}
static const struct iio_chan_spec adis16209_channels[] = {
- ADIS_SUPPLY_CHAN(ADIS16209_SUPPLY_OUT, ADIS16209_SCAN_SUPPLY, 14),
- ADIS_TEMP_CHAN(ADIS16209_TEMP_OUT, ADIS16209_SCAN_TEMP, 12),
+ ADIS_SUPPLY_CHAN(ADIS16209_SUPPLY_OUT, ADIS16209_SCAN_SUPPLY, 0, 14),
+ ADIS_TEMP_CHAN(ADIS16209_TEMP_OUT, ADIS16209_SCAN_TEMP, 0, 12),
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,
- BIT(IIO_CHAN_INFO_CALIBBIAS), 14),
- ADIS_AUX_ADC_CHAN(ADIS16209_AUX_ADC, ADIS16209_SCAN_AUX_ADC, 12),
- ADIS_INCLI_CHAN(X, ADIS16209_XINCL_OUT, ADIS16209_SCAN_INCLI_X, 0, 14),
- ADIS_INCLI_CHAN(Y, ADIS16209_YINCL_OUT, ADIS16209_SCAN_INCLI_Y, 0, 14),
- ADIS_ROT_CHAN(X, ADIS16209_ROT_OUT, ADIS16209_SCAN_ROT, 0, 14),
+ BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
+ 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, 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)
};
diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c
index 3a303a03d028..74ace2a8769d 100644
--- a/drivers/staging/iio/accel/adis16240_core.c
+++ b/drivers/staging/iio/accel/adis16240_core.c
@@ -173,15 +173,15 @@ static int adis16240_write_raw(struct iio_dev *indio_dev,
}
static const struct iio_chan_spec adis16240_channels[] = {
- ADIS_SUPPLY_CHAN(ADIS16240_SUPPLY_OUT, ADIS16240_SCAN_SUPPLY, 10),
- ADIS_AUX_ADC_CHAN(ADIS16240_AUX_ADC, ADIS16240_SCAN_AUX_ADC, 10),
+ ADIS_SUPPLY_CHAN(ADIS16240_SUPPLY_OUT, ADIS16240_SCAN_SUPPLY, 0, 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,
- 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,
- 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,
- BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 10),
- ADIS_TEMP_CHAN(ADIS16240_TEMP_OUT, ADIS16240_SCAN_TEMP, 10),
+ BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 10),
+ ADIS_TEMP_CHAN(ADIS16240_TEMP_OUT, ADIS16240_SCAN_TEMP, 0, 10),
IIO_CHAN_SOFT_TIMESTAMP(6)
};
diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index b87e382ad768..d01c7076a342 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -3,13 +3,6 @@
#
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
tristate "Analog Devices AD7606 ADC driver"
depends on GPIOLIB
@@ -94,7 +87,7 @@ config LPC32XX_ADC
config MXS_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
select STMP_DEVICE
select IIO_BUFFER
diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile
index afdcd1ff08ff..1c4277dbd318 100644
--- a/drivers/staging/iio/adc/Makefile
+++ b/drivers/staging/iio/adc/Makefile
@@ -8,7 +8,6 @@ ad7606-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o
ad7606-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o
obj-$(CONFIG_AD7606) += ad7606.o
-obj-$(CONFIG_AD7291) += ad7291.o
obj-$(CONFIG_AD7780) += ad7780.o
obj-$(CONFIG_AD7816) += ad7816.o
obj-$(CONFIG_AD7192) += ad7192.o
diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c
index 8a48d18de788..7511839ba94e 100644
--- a/drivers/staging/iio/adc/ad7606_par.c
+++ b/drivers/staging/iio/adc/ad7606_par.c
@@ -53,7 +53,7 @@ static int ad7606_par_probe(struct platform_device *pdev)
struct iio_dev *indio_dev;
void __iomem *addr;
resource_size_t remap_size;
- int ret, irq;
+ int irq;
irq = platform_get_irq(pdev, 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);
- if (!res)
- return -ENODEV;
+ addr = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(addr))
+ return PTR_ERR(addr);
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,
platform_get_device_id(pdev)->driver_data,
remap_size > 1 ? &ad7606_par16_bops :
&ad7606_par8_bops);
- if (IS_ERR(indio_dev)) {
- ret = PTR_ERR(indio_dev);
- goto out2;
- }
+ if (IS_ERR(indio_dev))
+ return PTR_ERR(indio_dev);
platform_set_drvdata(pdev, indio_dev);
return 0;
-
-out2:
- iounmap(addr);
-out1:
- release_mem_region(res->start, remap_size);
-
- return ret;
}
static int ad7606_par_remove(struct platform_device *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));
- iounmap(st->base_address);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(res->start, resource_size(res));
-
return 0;
}
diff --git a/drivers/staging/iio/frequency/ad9832.c b/drivers/staging/iio/frequency/ad9832.c
index b7c8351ce2ff..cf68159a5848 100644
--- a/drivers/staging/iio/frequency/ad9832.c
+++ b/drivers/staging/iio/frequency/ad9832.c
@@ -120,7 +120,7 @@ static ssize_t ad9832_write(struct device *dev, struct device_attribute *attr,
ret = spi_sync(st->spi, &st->msg);
break;
case AD9832_PHASE_SYM:
- if (val < 0 || val > 3) {
+ if (val > 3) {
ret = -EINVAL;
break;
}
diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
index 16f1a06bcd89..a21b7c514776 100644
--- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
+++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
@@ -182,45 +182,40 @@ static int iio_bfin_tmr_trigger_probe(struct platform_device *pdev)
unsigned int config;
int ret;
- st = kzalloc(sizeof(*st), GFP_KERNEL);
- if (st == NULL) {
- ret = -ENOMEM;
- goto out;
- }
+ st = devm_kzalloc(&pdev->dev, sizeof(*st), GFP_KERNEL);
+ if (st == NULL)
+ return -ENOMEM;
st->irq = platform_get_irq(pdev, 0);
if (!st->irq) {
dev_err(&pdev->dev, "No IRQs specified");
- ret = -ENODEV;
- goto out1;
+ return -ENODEV;
}
ret = iio_bfin_tmr_get_number(st->irq);
if (ret < 0)
- goto out1;
+ return ret;
st->timer_num = ret;
st->t = &iio_bfin_timer_code[st->timer_num];
st->trig = iio_trigger_alloc("bfintmr%d", st->timer_num);
- if (!st->trig) {
- ret = -ENOMEM;
- goto out1;
- }
+ if (!st->trig)
+ return -ENOMEM;
st->trig->ops = &iio_bfin_tmr_trigger_ops;
st->trig->dev.groups = iio_bfin_tmr_trigger_attr_groups;
iio_trigger_set_drvdata(st->trig, st);
ret = iio_trigger_register(st->trig);
if (ret)
- goto out2;
+ goto out;
ret = request_irq(st->irq, iio_bfin_tmr_trigger_isr,
0, st->trig->name, st);
if (ret) {
dev_err(&pdev->dev,
"request IRQ-%d failed", st->irq);
- goto out4;
+ goto out1;
}
config = PWM_OUT | PERIOD_CNT | IRQ_ENA;
@@ -260,13 +255,10 @@ static int iio_bfin_tmr_trigger_probe(struct platform_device *pdev)
return 0;
out_free_irq:
free_irq(st->irq, st);
-out4:
- iio_trigger_unregister(st->trig);
-out2:
- iio_trigger_put(st->trig);
out1:
- kfree(st);
+ iio_trigger_unregister(st->trig);
out:
+ iio_trigger_put(st->trig);
return ret;
}
@@ -280,7 +272,6 @@ static int iio_bfin_tmr_trigger_remove(struct platform_device *pdev)
free_irq(st->irq, st);
iio_trigger_unregister(st->trig);
iio_trigger_put(st->trig);
- kfree(st);
return 0;
}
diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h
index 96f51f0e0096..d8257ab60bac 100644
--- a/include/linux/iio/common/st_sensors.h
+++ b/include/linux/iio/common/st_sensors.h
@@ -47,6 +47,7 @@
.type = device_type, \
.modified = mod, \
.info_mask_separate = mask, \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.scan_index = index, \
.channel2 = ch2, \
.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() \
IIO_DEV_ATTR_SAMP_FREQ_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 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,
struct device_attribute *attr, char *buf);
diff --git a/include/linux/iio/common/st_sensors_i2c.h b/include/linux/iio/common/st_sensors_i2c.h
index 67d845385ae2..1796af093368 100644
--- a/include/linux/iio/common/st_sensors_i2c.h
+++ b/include/linux/iio/common/st_sensors_i2c.h
@@ -13,8 +13,19 @@
#include <linux/i2c.h>
#include <linux/iio/common/st_sensors.h>
+#include <linux/of.h>
void st_sensors_i2c_configure(struct iio_dev *indio_dev,
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 */
diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h
index b665dc7f017b..fa2d01ef8f55 100644
--- a/include/linux/iio/imu/adis.h
+++ b/include/linux/iio/imu/adis.h
@@ -157,13 +157,14 @@ int adis_single_conversion(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, unsigned int error_mask,
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, \
.indexed = 1, \
.channel = (chan), \
.extend_name = name, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = info_all, \
.address = (addr), \
.scan_index = (si), \
.scan_type = { \
@@ -174,19 +175,20 @@ int adis_single_conversion(struct iio_dev *indio_dev,
}, \
}
-#define ADIS_SUPPLY_CHAN(addr, si, bits) \
- ADIS_VOLTAGE_CHAN(addr, si, 0, "supply", bits)
+#define ADIS_SUPPLY_CHAN(addr, si, info_all, bits) \
+ ADIS_VOLTAGE_CHAN(addr, si, 0, "supply", info_all, bits)
-#define ADIS_AUX_ADC_CHAN(addr, si, bits) \
- ADIS_VOLTAGE_CHAN(addr, si, 1, NULL, bits)
+#define ADIS_AUX_ADC_CHAN(addr, si, info_all, 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, \
.indexed = 1, \
.channel = 0, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_OFFSET), \
+ .info_mask_shared_by_all = info_all, \
.address = (addr), \
.scan_index = (si), \
.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), \
.modified = 1, \
.channel2 = IIO_MOD_ ## mod, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
info_sep, \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = info_all, \
.address = (addr), \
.scan_index = (si), \
.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) \
- ADIS_MOD_CHAN(IIO_ACCEL, 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, info_all, bits)
-#define ADIS_GYRO_CHAN(mod, addr, si, info_sep, bits) \
- ADIS_MOD_CHAN(IIO_ANGL_VEL, 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, info_all, bits)
-#define ADIS_INCLI_CHAN(mod, addr, si, info_sep, bits) \
- ADIS_MOD_CHAN(IIO_INCLI, 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, info_all, bits)
-#define ADIS_ROT_CHAN(mod, addr, si, info_sep, bits) \
- ADIS_MOD_CHAN(IIO_ROT, 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, info_all, bits)
#ifdef CONFIG_IIO_ADIS_LIB_BUFFER
diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h
index d480631eabc2..4a848d6be3bf 100644
--- a/include/linux/iio/types.h
+++ b/include/linux/iio/types.h
@@ -70,6 +70,7 @@ enum iio_event_info {
IIO_EV_INFO_ENABLE,
IIO_EV_INFO_VALUE,
IIO_EV_INFO_HYSTERESIS,
+ IIO_EV_INFO_PERIOD,
};
enum iio_event_direction {
diff --git a/drivers/staging/iio/adc/ad7291.h b/include/linux/platform_data/ad7291.h
index bbd89fa51188..bbd89fa51188 100644
--- a/drivers/staging/iio/adc/ad7291.h
+++ b/include/linux/platform_data/ad7291.h