diff options
| author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-12-26 20:05:25 -0500 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-12-26 20:05:25 -0500 |
| commit | 02c34ccc1d2d528d2de2897881b97933363432b5 (patch) | |
| tree | 8d1f53965b2c828a11066759cbe2797a4c54cf4d | |
| parent | 35ea984daccc60e6b9dd90074bb2f4f6b57e6309 (diff) | |
| parent | e8aab48b34d3bd069dfcf4ccb8f13ba8c98f7845 (diff) | |
Merge tag 'iio-for-4.5c' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next
Jonathan writes:
Third set of new stuff for IIO in the 4.5 cycle.
New driver features
- us5182
* Add interrupt support and rising / falling threshold events.
Cleanups / fixes to new stuff / minor additions
* Expose the IIO value formatting function for drivers to
make use of internally.
- ina2xx
* Fix wrong channel order
* Fix incorrect reporting of endianness
* Adding documentation of ABI unique to this device
- mma8452
* Drop an unused register description
* Use an enum for the channel index to aid readability
- sca3000
* Use standard NULL comparison style
- us5182
* fix an inconsistency in status of enable (a bug with no real effect until
above patches are applied)
* refactor the read_raw function to improve maintainability / readability.
| -rw-r--r-- | Documentation/ABI/testing/sysfs-bus-iio-ina2xx-adc | 24 | ||||
| -rw-r--r-- | drivers/iio/accel/mma8452.c | 40 | ||||
| -rw-r--r-- | drivers/iio/adc/ina2xx-adc.c | 6 | ||||
| -rw-r--r-- | drivers/iio/industrialio-core.c | 1 | ||||
| -rw-r--r-- | drivers/iio/light/us5182d.c | 442 | ||||
| -rw-r--r-- | drivers/staging/iio/accel/sca3000_ring.c | 2 | ||||
| -rw-r--r-- | include/linux/iio/iio.h | 2 |
7 files changed, 414 insertions, 103 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-ina2xx-adc b/Documentation/ABI/testing/sysfs-bus-iio-ina2xx-adc new file mode 100644 index 000000000000..8916f7ec6507 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-ina2xx-adc | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | What: /sys/bus/iio/devices/iio:deviceX/in_allow_async_readout | ||
| 2 | Date: December 2015 | ||
| 3 | KernelVersion: 4.4 | ||
| 4 | Contact: linux-iio@vger.kernel.org | ||
| 5 | Description: | ||
| 6 | By default (value '0'), the capture thread checks for the Conversion | ||
| 7 | Ready Flag to being set prior to committing a new value to the sample | ||
| 8 | buffer. This synchronizes the in-chip conversion rate with the | ||
| 9 | in-driver readout rate at the cost of an additional register read. | ||
| 10 | |||
| 11 | Writing '1' will remove the polling for the Conversion Ready Flags to | ||
| 12 | save the additional i2c transaction, which will improve the bandwidth | ||
| 13 | available for reading data. However, samples can be occasionally skipped | ||
| 14 | or repeated, depending on the beat between the capture and conversion | ||
| 15 | rates. | ||
| 16 | |||
| 17 | What: /sys/bus/iio/devices/iio:deviceX/in_shunt_resistor | ||
| 18 | Date: December 2015 | ||
| 19 | KernelVersion: 4.4 | ||
| 20 | Contact: linux-iio@vger.kernel.org | ||
| 21 | Description: | ||
| 22 | The value of the shunt resistor may be known only at runtime fom an | ||
| 23 | eeprom content read by a client application. This attribute allows to | ||
| 24 | set its value in ohms. | ||
diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 116a6e401a6a..ccc632a7cf01 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c | |||
| @@ -58,7 +58,6 @@ | |||
| 58 | #define MMA8452_FF_MT_COUNT 0x18 | 58 | #define MMA8452_FF_MT_COUNT 0x18 |
| 59 | #define MMA8452_TRANSIENT_CFG 0x1d | 59 | #define MMA8452_TRANSIENT_CFG 0x1d |
| 60 | #define MMA8452_TRANSIENT_CFG_HPF_BYP BIT(0) | 60 | #define MMA8452_TRANSIENT_CFG_HPF_BYP BIT(0) |
| 61 | #define MMA8452_TRANSIENT_CFG_CHAN(chan) BIT(chan + 1) | ||
| 62 | #define MMA8452_TRANSIENT_CFG_ELE BIT(4) | 61 | #define MMA8452_TRANSIENT_CFG_ELE BIT(4) |
| 63 | #define MMA8452_TRANSIENT_SRC 0x1e | 62 | #define MMA8452_TRANSIENT_SRC 0x1e |
| 64 | #define MMA8452_TRANSIENT_SRC_XTRANSE BIT(1) | 63 | #define MMA8452_TRANSIENT_SRC_XTRANSE BIT(1) |
| @@ -144,6 +143,13 @@ struct mma_chip_info { | |||
| 144 | u8 ev_count; | 143 | u8 ev_count; |
| 145 | }; | 144 | }; |
| 146 | 145 | ||
| 146 | enum { | ||
| 147 | idx_x, | ||
| 148 | idx_y, | ||
| 149 | idx_z, | ||
| 150 | idx_ts, | ||
| 151 | }; | ||
| 152 | |||
| 147 | static int mma8452_drdy(struct mma8452_data *data) | 153 | static int mma8452_drdy(struct mma8452_data *data) |
| 148 | { | 154 | { |
| 149 | int tries = 150; | 155 | int tries = 150; |
| @@ -817,31 +823,31 @@ static struct attribute_group mma8452_event_attribute_group = { | |||
| 817 | } | 823 | } |
| 818 | 824 | ||
| 819 | static const struct iio_chan_spec mma8452_channels[] = { | 825 | static const struct iio_chan_spec mma8452_channels[] = { |
| 820 | MMA8452_CHANNEL(X, 0, 12), | 826 | MMA8452_CHANNEL(X, idx_x, 12), |
| 821 | MMA8452_CHANNEL(Y, 1, 12), | 827 | MMA8452_CHANNEL(Y, idx_y, 12), |
| 822 | MMA8452_CHANNEL(Z, 2, 12), | 828 | MMA8452_CHANNEL(Z, idx_z, 12), |
| 823 | IIO_CHAN_SOFT_TIMESTAMP(3), | 829 | IIO_CHAN_SOFT_TIMESTAMP(idx_ts), |
| 824 | }; | 830 | }; |
| 825 | 831 | ||
| 826 | static const struct iio_chan_spec mma8453_channels[] = { | 832 | static const struct iio_chan_spec mma8453_channels[] = { |
| 827 | MMA8452_CHANNEL(X, 0, 10), | 833 | MMA8452_CHANNEL(X, idx_x, 10), |
| 828 | MMA8452_CHANNEL(Y, 1, 10), | 834 | MMA8452_CHANNEL(Y, idx_y, 10), |
| 829 | MMA8452_CHANNEL(Z, 2, 10), | 835 | MMA8452_CHANNEL(Z, idx_z, 10), |
| 830 | IIO_CHAN_SOFT_TIMESTAMP(3), | 836 | IIO_CHAN_SOFT_TIMESTAMP(idx_ts), |
| 831 | }; | 837 | }; |
| 832 | 838 | ||
| 833 | static const struct iio_chan_spec mma8652_channels[] = { | 839 | static const struct iio_chan_spec mma8652_channels[] = { |
| 834 | MMA8652_CHANNEL(X, 0, 12), | 840 | MMA8652_CHANNEL(X, idx_x, 12), |
| 835 | MMA8652_CHANNEL(Y, 1, 12), | 841 | MMA8652_CHANNEL(Y, idx_y, 12), |
| 836 | MMA8652_CHANNEL(Z, 2, 12), | 842 | MMA8652_CHANNEL(Z, idx_z, 12), |
| 837 | IIO_CHAN_SOFT_TIMESTAMP(3), | 843 | IIO_CHAN_SOFT_TIMESTAMP(idx_ts), |
| 838 | }; | 844 | }; |
| 839 | 845 | ||
| 840 | static const struct iio_chan_spec mma8653_channels[] = { | 846 | static const struct iio_chan_spec mma8653_channels[] = { |
| 841 | MMA8652_CHANNEL(X, 0, 10), | 847 | MMA8652_CHANNEL(X, idx_x, 10), |
| 842 | MMA8652_CHANNEL(Y, 1, 10), | 848 | MMA8652_CHANNEL(Y, idx_y, 10), |
| 843 | MMA8652_CHANNEL(Z, 2, 10), | 849 | MMA8652_CHANNEL(Z, idx_z, 10), |
| 844 | IIO_CHAN_SOFT_TIMESTAMP(3), | 850 | IIO_CHAN_SOFT_TIMESTAMP(idx_ts), |
| 845 | }; | 851 | }; |
| 846 | 852 | ||
| 847 | enum { | 853 | enum { |
diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index 4c18c4cc8939..d803e5018a42 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c | |||
| @@ -400,7 +400,7 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev, | |||
| 400 | .sign = 'u', \ | 400 | .sign = 'u', \ |
| 401 | .realbits = 16, \ | 401 | .realbits = 16, \ |
| 402 | .storagebits = 16, \ | 402 | .storagebits = 16, \ |
| 403 | .endianness = IIO_LE, \ | 403 | .endianness = IIO_CPU, \ |
| 404 | } \ | 404 | } \ |
| 405 | } | 405 | } |
| 406 | 406 | ||
| @@ -428,8 +428,8 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev, | |||
| 428 | static const struct iio_chan_spec ina2xx_channels[] = { | 428 | static const struct iio_chan_spec ina2xx_channels[] = { |
| 429 | INA2XX_CHAN_VOLTAGE(0, INA2XX_SHUNT_VOLTAGE), | 429 | INA2XX_CHAN_VOLTAGE(0, INA2XX_SHUNT_VOLTAGE), |
| 430 | INA2XX_CHAN_VOLTAGE(1, INA2XX_BUS_VOLTAGE), | 430 | INA2XX_CHAN_VOLTAGE(1, INA2XX_BUS_VOLTAGE), |
| 431 | INA2XX_CHAN(IIO_CURRENT, 2, INA2XX_CURRENT), | 431 | INA2XX_CHAN(IIO_POWER, 2, INA2XX_POWER), |
| 432 | INA2XX_CHAN(IIO_POWER, 3, INA2XX_POWER), | 432 | INA2XX_CHAN(IIO_CURRENT, 3, INA2XX_CURRENT), |
| 433 | IIO_CHAN_SOFT_TIMESTAMP(4), | 433 | IIO_CHAN_SOFT_TIMESTAMP(4), |
| 434 | }; | 434 | }; |
| 435 | 435 | ||
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 8966f85ca4cd..fd01f3493fc7 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c | |||
| @@ -470,6 +470,7 @@ ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals) | |||
| 470 | return 0; | 470 | return 0; |
| 471 | } | 471 | } |
| 472 | } | 472 | } |
| 473 | EXPORT_SYMBOL_GPL(iio_format_value); | ||
| 473 | 474 | ||
| 474 | static ssize_t iio_read_channel_info(struct device *dev, | 475 | static ssize_t iio_read_channel_info(struct device *dev, |
| 475 | struct device_attribute *attr, | 476 | struct device_attribute *attr, |
diff --git a/drivers/iio/light/us5182d.c b/drivers/iio/light/us5182d.c index 256c4bc12d21..45bc2f742f46 100644 --- a/drivers/iio/light/us5182d.c +++ b/drivers/iio/light/us5182d.c | |||
| @@ -20,7 +20,10 @@ | |||
| 20 | #include <linux/acpi.h> | 20 | #include <linux/acpi.h> |
| 21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
| 22 | #include <linux/i2c.h> | 22 | #include <linux/i2c.h> |
| 23 | #include <linux/iio/events.h> | ||
| 23 | #include <linux/iio/iio.h> | 24 | #include <linux/iio/iio.h> |
| 25 | #include <linux/interrupt.h> | ||
| 26 | #include <linux/irq.h> | ||
| 24 | #include <linux/iio/sysfs.h> | 27 | #include <linux/iio/sysfs.h> |
| 25 | #include <linux/mutex.h> | 28 | #include <linux/mutex.h> |
| 26 | #include <linux/pm.h> | 29 | #include <linux/pm.h> |
| @@ -30,6 +33,8 @@ | |||
| 30 | #define US5182D_CFG0_ONESHOT_EN BIT(6) | 33 | #define US5182D_CFG0_ONESHOT_EN BIT(6) |
| 31 | #define US5182D_CFG0_SHUTDOWN_EN BIT(7) | 34 | #define US5182D_CFG0_SHUTDOWN_EN BIT(7) |
| 32 | #define US5182D_CFG0_WORD_ENABLE BIT(0) | 35 | #define US5182D_CFG0_WORD_ENABLE BIT(0) |
| 36 | #define US5182D_CFG0_PROX BIT(3) | ||
| 37 | #define US5182D_CFG0_PX_IRQ BIT(2) | ||
| 33 | 38 | ||
| 34 | #define US5182D_REG_CFG1 0x01 | 39 | #define US5182D_REG_CFG1 0x01 |
| 35 | #define US5182D_CFG1_ALS_RES16 BIT(4) | 40 | #define US5182D_CFG1_ALS_RES16 BIT(4) |
| @@ -41,6 +46,7 @@ | |||
| 41 | 46 | ||
| 42 | #define US5182D_REG_CFG3 0x03 | 47 | #define US5182D_REG_CFG3 0x03 |
| 43 | #define US5182D_CFG3_LED_CURRENT100 (BIT(4) | BIT(5)) | 48 | #define US5182D_CFG3_LED_CURRENT100 (BIT(4) | BIT(5)) |
| 49 | #define US5182D_CFG3_INT_SOURCE_PX BIT(3) | ||
| 44 | 50 | ||
| 45 | #define US5182D_REG_CFG4 0x10 | 51 | #define US5182D_REG_CFG4 0x10 |
| 46 | 52 | ||
| @@ -55,6 +61,13 @@ | |||
| 55 | #define US5182D_REG_AUTO_LDARK_GAIN 0x29 | 61 | #define US5182D_REG_AUTO_LDARK_GAIN 0x29 |
| 56 | #define US5182D_REG_AUTO_HDARK_GAIN 0x2a | 62 | #define US5182D_REG_AUTO_HDARK_GAIN 0x2a |
| 57 | 63 | ||
| 64 | /* Thresholds for events: px low (0x08-l, 0x09-h), px high (0x0a-l 0x0b-h) */ | ||
| 65 | #define US5182D_REG_PXL_TH 0x08 | ||
| 66 | #define US5182D_REG_PXH_TH 0x0a | ||
| 67 | |||
| 68 | #define US5182D_REG_PXL_TH_DEFAULT 1000 | ||
| 69 | #define US5182D_REG_PXH_TH_DEFAULT 30000 | ||
| 70 | |||
| 58 | #define US5182D_OPMODE_ALS 0x01 | 71 | #define US5182D_OPMODE_ALS 0x01 |
| 59 | #define US5182D_OPMODE_PX 0x02 | 72 | #define US5182D_OPMODE_PX 0x02 |
| 60 | #define US5182D_OPMODE_SHIFT 4 | 73 | #define US5182D_OPMODE_SHIFT 4 |
| @@ -84,6 +97,8 @@ | |||
| 84 | #define US5182D_READ_WORD 2 | 97 | #define US5182D_READ_WORD 2 |
| 85 | #define US5182D_OPSTORE_SLEEP_TIME 20 /* ms */ | 98 | #define US5182D_OPSTORE_SLEEP_TIME 20 /* ms */ |
| 86 | #define US5182D_SLEEP_MS 3000 /* ms */ | 99 | #define US5182D_SLEEP_MS 3000 /* ms */ |
| 100 | #define US5182D_PXH_TH_DISABLE 0xffff | ||
| 101 | #define US5182D_PXL_TH_DISABLE 0x0000 | ||
| 87 | 102 | ||
| 88 | /* Available ranges: [12354, 7065, 3998, 2202, 1285, 498, 256, 138] lux */ | 103 | /* Available ranges: [12354, 7065, 3998, 2202, 1285, 498, 256, 138] lux */ |
| 89 | static const int us5182d_scales[] = {188500, 107800, 61000, 33600, 19600, 7600, | 104 | static const int us5182d_scales[] = {188500, 107800, 61000, 33600, 19600, 7600, |
| @@ -119,6 +134,12 @@ struct us5182d_data { | |||
| 119 | u8 upper_dark_gain; | 134 | u8 upper_dark_gain; |
| 120 | u16 *us5182d_dark_ths; | 135 | u16 *us5182d_dark_ths; |
| 121 | 136 | ||
| 137 | u16 px_low_th; | ||
| 138 | u16 px_high_th; | ||
| 139 | |||
| 140 | int rising_en; | ||
| 141 | int falling_en; | ||
| 142 | |||
| 122 | u8 opmode; | 143 | u8 opmode; |
| 123 | u8 power_mode; | 144 | u8 power_mode; |
| 124 | 145 | ||
| @@ -148,10 +169,26 @@ static const struct { | |||
| 148 | {US5182D_REG_CFG1, US5182D_CFG1_ALS_RES16}, | 169 | {US5182D_REG_CFG1, US5182D_CFG1_ALS_RES16}, |
| 149 | {US5182D_REG_CFG2, (US5182D_CFG2_PX_RES16 | | 170 | {US5182D_REG_CFG2, (US5182D_CFG2_PX_RES16 | |
| 150 | US5182D_CFG2_PXGAIN_DEFAULT)}, | 171 | US5182D_CFG2_PXGAIN_DEFAULT)}, |
| 151 | {US5182D_REG_CFG3, US5182D_CFG3_LED_CURRENT100}, | 172 | {US5182D_REG_CFG3, US5182D_CFG3_LED_CURRENT100 | |
| 173 | US5182D_CFG3_INT_SOURCE_PX}, | ||
| 152 | {US5182D_REG_CFG4, 0x00}, | 174 | {US5182D_REG_CFG4, 0x00}, |
| 153 | }; | 175 | }; |
| 154 | 176 | ||
| 177 | static const struct iio_event_spec us5182d_events[] = { | ||
| 178 | { | ||
| 179 | .type = IIO_EV_TYPE_THRESH, | ||
| 180 | .dir = IIO_EV_DIR_RISING, | ||
| 181 | .mask_separate = BIT(IIO_EV_INFO_VALUE) | | ||
| 182 | BIT(IIO_EV_INFO_ENABLE), | ||
| 183 | }, | ||
| 184 | { | ||
| 185 | .type = IIO_EV_TYPE_THRESH, | ||
| 186 | .dir = IIO_EV_DIR_FALLING, | ||
| 187 | .mask_separate = BIT(IIO_EV_INFO_VALUE) | | ||
| 188 | BIT(IIO_EV_INFO_ENABLE), | ||
| 189 | }, | ||
| 190 | }; | ||
| 191 | |||
| 155 | static const struct iio_chan_spec us5182d_channels[] = { | 192 | static const struct iio_chan_spec us5182d_channels[] = { |
| 156 | { | 193 | { |
| 157 | .type = IIO_LIGHT, | 194 | .type = IIO_LIGHT, |
| @@ -161,26 +198,11 @@ static const struct iio_chan_spec us5182d_channels[] = { | |||
| 161 | { | 198 | { |
| 162 | .type = IIO_PROXIMITY, | 199 | .type = IIO_PROXIMITY, |
| 163 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | 200 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), |
| 201 | .event_spec = us5182d_events, | ||
| 202 | .num_event_specs = ARRAY_SIZE(us5182d_events), | ||
| 164 | } | 203 | } |
| 165 | }; | 204 | }; |
| 166 | 205 | ||
| 167 | static int us5182d_get_als(struct us5182d_data *data) | ||
| 168 | { | ||
| 169 | int ret; | ||
| 170 | unsigned long result; | ||
| 171 | |||
| 172 | ret = i2c_smbus_read_word_data(data->client, | ||
| 173 | US5182D_REG_ADL); | ||
| 174 | if (ret < 0) | ||
| 175 | return ret; | ||
| 176 | |||
| 177 | result = ret * data->ga / US5182D_GA_RESOLUTION; | ||
| 178 | if (result > 0xffff) | ||
| 179 | result = 0xffff; | ||
| 180 | |||
| 181 | return result; | ||
| 182 | } | ||
| 183 | |||
| 184 | static int us5182d_oneshot_en(struct us5182d_data *data) | 206 | static int us5182d_oneshot_en(struct us5182d_data *data) |
| 185 | { | 207 | { |
| 186 | int ret; | 208 | int ret; |
| @@ -238,8 +260,12 @@ static int us5182d_als_enable(struct us5182d_data *data) | |||
| 238 | int ret; | 260 | int ret; |
| 239 | u8 mode; | 261 | u8 mode; |
| 240 | 262 | ||
| 241 | if (data->power_mode == US5182D_ONESHOT) | 263 | if (data->power_mode == US5182D_ONESHOT) { |
| 242 | return us5182d_set_opmode(data, US5182D_ALS_ONLY); | 264 | ret = us5182d_set_opmode(data, US5182D_ALS_ONLY); |
| 265 | if (ret < 0) | ||
| 266 | return ret; | ||
| 267 | data->px_enabled = false; | ||
| 268 | } | ||
| 243 | 269 | ||
| 244 | if (data->als_enabled) | 270 | if (data->als_enabled) |
| 245 | return 0; | 271 | return 0; |
| @@ -260,8 +286,12 @@ static int us5182d_px_enable(struct us5182d_data *data) | |||
| 260 | int ret; | 286 | int ret; |
| 261 | u8 mode; | 287 | u8 mode; |
| 262 | 288 | ||
| 263 | if (data->power_mode == US5182D_ONESHOT) | 289 | if (data->power_mode == US5182D_ONESHOT) { |
| 264 | return us5182d_set_opmode(data, US5182D_PX_ONLY); | 290 | ret = us5182d_set_opmode(data, US5182D_PX_ONLY); |
| 291 | if (ret < 0) | ||
| 292 | return ret; | ||
| 293 | data->als_enabled = false; | ||
| 294 | } | ||
| 265 | 295 | ||
| 266 | if (data->px_enabled) | 296 | if (data->px_enabled) |
| 267 | return 0; | 297 | return 0; |
| @@ -277,6 +307,39 @@ static int us5182d_px_enable(struct us5182d_data *data) | |||
| 277 | return 0; | 307 | return 0; |
| 278 | } | 308 | } |
| 279 | 309 | ||
| 310 | static int us5182d_get_als(struct us5182d_data *data) | ||
| 311 | { | ||
| 312 | int ret; | ||
| 313 | unsigned long result; | ||
| 314 | |||
| 315 | ret = us5182d_als_enable(data); | ||
| 316 | if (ret < 0) | ||
| 317 | return ret; | ||
| 318 | |||
| 319 | ret = i2c_smbus_read_word_data(data->client, | ||
| 320 | US5182D_REG_ADL); | ||
| 321 | if (ret < 0) | ||
| 322 | return ret; | ||
| 323 | |||
| 324 | result = ret * data->ga / US5182D_GA_RESOLUTION; | ||
| 325 | if (result > 0xffff) | ||
| 326 | result = 0xffff; | ||
| 327 | |||
| 328 | return result; | ||
| 329 | } | ||
| 330 | |||
| 331 | static int us5182d_get_px(struct us5182d_data *data) | ||
| 332 | { | ||
| 333 | int ret; | ||
| 334 | |||
| 335 | ret = us5182d_px_enable(data); | ||
| 336 | if (ret < 0) | ||
| 337 | return ret; | ||
| 338 | |||
| 339 | return i2c_smbus_read_word_data(data->client, | ||
| 340 | US5182D_REG_PDL); | ||
| 341 | } | ||
| 342 | |||
| 280 | static int us5182d_shutdown_en(struct us5182d_data *data, u8 state) | 343 | static int us5182d_shutdown_en(struct us5182d_data *data, u8 state) |
| 281 | { | 344 | { |
| 282 | int ret; | 345 | int ret; |
| @@ -323,6 +386,46 @@ static int us5182d_set_power_state(struct us5182d_data *data, bool on) | |||
| 323 | return ret; | 386 | return ret; |
| 324 | } | 387 | } |
| 325 | 388 | ||
| 389 | static int us5182d_read_value(struct us5182d_data *data, | ||
| 390 | struct iio_chan_spec const *chan) | ||
| 391 | { | ||
| 392 | int ret, value; | ||
| 393 | |||
| 394 | mutex_lock(&data->lock); | ||
| 395 | |||
| 396 | if (data->power_mode == US5182D_ONESHOT) { | ||
| 397 | ret = us5182d_oneshot_en(data); | ||
| 398 | if (ret < 0) | ||
| 399 | goto out_err; | ||
| 400 | } | ||
| 401 | |||
| 402 | ret = us5182d_set_power_state(data, true); | ||
| 403 | if (ret < 0) | ||
| 404 | goto out_err; | ||
| 405 | |||
| 406 | if (chan->type == IIO_LIGHT) | ||
| 407 | ret = us5182d_get_als(data); | ||
| 408 | else | ||
| 409 | ret = us5182d_get_px(data); | ||
| 410 | if (ret < 0) | ||
| 411 | goto out_poweroff; | ||
| 412 | |||
| 413 | value = ret; | ||
| 414 | |||
| 415 | ret = us5182d_set_power_state(data, false); | ||
| 416 | if (ret < 0) | ||
| 417 | goto out_err; | ||
| 418 | |||
| 419 | mutex_unlock(&data->lock); | ||
| 420 | return value; | ||
| 421 | |||
| 422 | out_poweroff: | ||
| 423 | us5182d_set_power_state(data, false); | ||
| 424 | out_err: | ||
| 425 | mutex_unlock(&data->lock); | ||
| 426 | return ret; | ||
| 427 | } | ||
| 428 | |||
| 326 | static int us5182d_read_raw(struct iio_dev *indio_dev, | 429 | static int us5182d_read_raw(struct iio_dev *indio_dev, |
| 327 | struct iio_chan_spec const *chan, int *val, | 430 | struct iio_chan_spec const *chan, int *val, |
| 328 | int *val2, long mask) | 431 | int *val2, long mask) |
| @@ -332,76 +435,21 @@ static int us5182d_read_raw(struct iio_dev *indio_dev, | |||
| 332 | 435 | ||
| 333 | switch (mask) { | 436 | switch (mask) { |
| 334 | case IIO_CHAN_INFO_RAW: | 437 | case IIO_CHAN_INFO_RAW: |
| 335 | switch (chan->type) { | 438 | ret = us5182d_read_value(data, chan); |
| 336 | case IIO_LIGHT: | 439 | if (ret < 0) |
| 337 | mutex_lock(&data->lock); | 440 | return ret; |
| 338 | if (data->power_mode == US5182D_ONESHOT) { | 441 | *val = ret; |
| 339 | ret = us5182d_oneshot_en(data); | 442 | return IIO_VAL_INT; |
| 340 | if (ret < 0) | ||
| 341 | goto out_err; | ||
| 342 | } | ||
| 343 | ret = us5182d_set_power_state(data, true); | ||
| 344 | if (ret < 0) | ||
| 345 | goto out_err; | ||
| 346 | ret = us5182d_als_enable(data); | ||
| 347 | if (ret < 0) | ||
| 348 | goto out_poweroff; | ||
| 349 | ret = us5182d_get_als(data); | ||
| 350 | if (ret < 0) | ||
| 351 | goto out_poweroff; | ||
| 352 | *val = ret; | ||
| 353 | ret = us5182d_set_power_state(data, false); | ||
| 354 | if (ret < 0) | ||
| 355 | goto out_err; | ||
| 356 | mutex_unlock(&data->lock); | ||
| 357 | return IIO_VAL_INT; | ||
| 358 | case IIO_PROXIMITY: | ||
| 359 | mutex_lock(&data->lock); | ||
| 360 | if (data->power_mode == US5182D_ONESHOT) { | ||
| 361 | ret = us5182d_oneshot_en(data); | ||
| 362 | if (ret < 0) | ||
| 363 | goto out_err; | ||
| 364 | } | ||
| 365 | ret = us5182d_set_power_state(data, true); | ||
| 366 | if (ret < 0) | ||
| 367 | goto out_err; | ||
| 368 | ret = us5182d_px_enable(data); | ||
| 369 | if (ret < 0) | ||
| 370 | goto out_poweroff; | ||
| 371 | ret = i2c_smbus_read_word_data(data->client, | ||
| 372 | US5182D_REG_PDL); | ||
| 373 | if (ret < 0) | ||
| 374 | goto out_poweroff; | ||
| 375 | *val = ret; | ||
| 376 | ret = us5182d_set_power_state(data, false); | ||
| 377 | if (ret < 0) | ||
| 378 | goto out_err; | ||
| 379 | mutex_unlock(&data->lock); | ||
| 380 | return IIO_VAL_INT; | ||
| 381 | default: | ||
| 382 | return -EINVAL; | ||
| 383 | } | ||
| 384 | |||
| 385 | case IIO_CHAN_INFO_SCALE: | 443 | case IIO_CHAN_INFO_SCALE: |
| 386 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1); | 444 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1); |
| 387 | if (ret < 0) | 445 | if (ret < 0) |
| 388 | return ret; | 446 | return ret; |
| 389 | |||
| 390 | *val = 0; | 447 | *val = 0; |
| 391 | *val2 = us5182d_scales[ret & US5182D_AGAIN_MASK]; | 448 | *val2 = us5182d_scales[ret & US5182D_AGAIN_MASK]; |
| 392 | |||
| 393 | return IIO_VAL_INT_PLUS_MICRO; | 449 | return IIO_VAL_INT_PLUS_MICRO; |
| 394 | default: | 450 | default: |
| 395 | return -EINVAL; | 451 | return -EINVAL; |
| 396 | } | 452 | } |
| 397 | |||
| 398 | return -EINVAL; | ||
| 399 | |||
| 400 | out_poweroff: | ||
| 401 | us5182d_set_power_state(data, false); | ||
| 402 | out_err: | ||
| 403 | mutex_unlock(&data->lock); | ||
| 404 | return ret; | ||
| 405 | } | 453 | } |
| 406 | 454 | ||
| 407 | /** | 455 | /** |
| @@ -479,11 +527,201 @@ static int us5182d_write_raw(struct iio_dev *indio_dev, | |||
| 479 | return -EINVAL; | 527 | return -EINVAL; |
| 480 | } | 528 | } |
| 481 | 529 | ||
| 530 | static int us5182d_setup_prox(struct iio_dev *indio_dev, | ||
| 531 | enum iio_event_direction dir, u16 val) | ||
| 532 | { | ||
| 533 | struct us5182d_data *data = iio_priv(indio_dev); | ||
| 534 | |||
| 535 | if (dir == IIO_EV_DIR_FALLING) | ||
| 536 | return i2c_smbus_write_word_data(data->client, | ||
| 537 | US5182D_REG_PXL_TH, val); | ||
| 538 | else if (dir == IIO_EV_DIR_RISING) | ||
| 539 | return i2c_smbus_write_word_data(data->client, | ||
| 540 | US5182D_REG_PXH_TH, val); | ||
| 541 | |||
| 542 | return 0; | ||
| 543 | } | ||
| 544 | |||
| 545 | static int us5182d_read_thresh(struct iio_dev *indio_dev, | ||
| 546 | const struct iio_chan_spec *chan, enum iio_event_type type, | ||
| 547 | enum iio_event_direction dir, enum iio_event_info info, int *val, | ||
| 548 | int *val2) | ||
| 549 | { | ||
| 550 | struct us5182d_data *data = iio_priv(indio_dev); | ||
| 551 | |||
| 552 | switch (dir) { | ||
| 553 | case IIO_EV_DIR_RISING: | ||
| 554 | mutex_lock(&data->lock); | ||
| 555 | *val = data->px_high_th; | ||
| 556 | mutex_unlock(&data->lock); | ||
| 557 | break; | ||
| 558 | case IIO_EV_DIR_FALLING: | ||
| 559 | mutex_lock(&data->lock); | ||
| 560 | *val = data->px_low_th; | ||
| 561 | mutex_unlock(&data->lock); | ||
| 562 | break; | ||
| 563 | default: | ||
| 564 | return -EINVAL; | ||
| 565 | } | ||
| 566 | |||
| 567 | return IIO_VAL_INT; | ||
| 568 | } | ||
| 569 | |||
| 570 | static int us5182d_write_thresh(struct iio_dev *indio_dev, | ||
| 571 | const struct iio_chan_spec *chan, enum iio_event_type type, | ||
| 572 | enum iio_event_direction dir, enum iio_event_info info, int val, | ||
| 573 | int val2) | ||
| 574 | { | ||
| 575 | struct us5182d_data *data = iio_priv(indio_dev); | ||
| 576 | int ret; | ||
| 577 | |||
| 578 | if (val < 0 || val > USHRT_MAX || val2 != 0) | ||
| 579 | return -EINVAL; | ||
| 580 | |||
| 581 | switch (dir) { | ||
| 582 | case IIO_EV_DIR_RISING: | ||
| 583 | mutex_lock(&data->lock); | ||
| 584 | if (data->rising_en) { | ||
| 585 | ret = us5182d_setup_prox(indio_dev, dir, val); | ||
| 586 | if (ret < 0) | ||
| 587 | goto err; | ||
| 588 | } | ||
| 589 | data->px_high_th = val; | ||
| 590 | mutex_unlock(&data->lock); | ||
| 591 | break; | ||
| 592 | case IIO_EV_DIR_FALLING: | ||
| 593 | mutex_lock(&data->lock); | ||
| 594 | if (data->falling_en) { | ||
| 595 | ret = us5182d_setup_prox(indio_dev, dir, val); | ||
| 596 | if (ret < 0) | ||
| 597 | goto err; | ||
| 598 | } | ||
| 599 | data->px_low_th = val; | ||
| 600 | mutex_unlock(&data->lock); | ||
| 601 | break; | ||
| 602 | default: | ||
| 603 | return -EINVAL; | ||
| 604 | } | ||
| 605 | |||
| 606 | return 0; | ||
| 607 | err: | ||
| 608 | mutex_unlock(&data->lock); | ||
| 609 | return ret; | ||
| 610 | } | ||
| 611 | |||
| 612 | static int us5182d_read_event_config(struct iio_dev *indio_dev, | ||
| 613 | const struct iio_chan_spec *chan, enum iio_event_type type, | ||
| 614 | enum iio_event_direction dir) | ||
| 615 | { | ||
| 616 | struct us5182d_data *data = iio_priv(indio_dev); | ||
| 617 | int ret; | ||
| 618 | |||
| 619 | switch (dir) { | ||
| 620 | case IIO_EV_DIR_RISING: | ||
| 621 | mutex_lock(&data->lock); | ||
| 622 | ret = data->rising_en; | ||
| 623 | mutex_unlock(&data->lock); | ||
| 624 | break; | ||
| 625 | case IIO_EV_DIR_FALLING: | ||
| 626 | mutex_lock(&data->lock); | ||
| 627 | ret = data->falling_en; | ||
| 628 | mutex_unlock(&data->lock); | ||
| 629 | break; | ||
| 630 | default: | ||
| 631 | ret = -EINVAL; | ||
| 632 | break; | ||
| 633 | } | ||
| 634 | |||
| 635 | return ret; | ||
| 636 | } | ||
| 637 | |||
| 638 | static int us5182d_write_event_config(struct iio_dev *indio_dev, | ||
| 639 | const struct iio_chan_spec *chan, enum iio_event_type type, | ||
| 640 | enum iio_event_direction dir, int state) | ||
| 641 | { | ||
| 642 | struct us5182d_data *data = iio_priv(indio_dev); | ||
| 643 | int ret; | ||
| 644 | u16 new_th; | ||
| 645 | |||
| 646 | mutex_lock(&data->lock); | ||
| 647 | |||
| 648 | switch (dir) { | ||
| 649 | case IIO_EV_DIR_RISING: | ||
| 650 | if (data->rising_en == state) { | ||
| 651 | mutex_unlock(&data->lock); | ||
| 652 | return 0; | ||
| 653 | } | ||
| 654 | new_th = US5182D_PXH_TH_DISABLE; | ||
| 655 | if (state) { | ||
| 656 | data->power_mode = US5182D_CONTINUOUS; | ||
| 657 | ret = us5182d_set_power_state(data, true); | ||
| 658 | if (ret < 0) | ||
| 659 | goto err; | ||
| 660 | ret = us5182d_px_enable(data); | ||
| 661 | if (ret < 0) | ||
| 662 | goto err_poweroff; | ||
| 663 | new_th = data->px_high_th; | ||
| 664 | } | ||
| 665 | ret = us5182d_setup_prox(indio_dev, dir, new_th); | ||
| 666 | if (ret < 0) | ||
| 667 | goto err_poweroff; | ||
| 668 | data->rising_en = state; | ||
| 669 | break; | ||
| 670 | case IIO_EV_DIR_FALLING: | ||
| 671 | if (data->falling_en == state) { | ||
| 672 | mutex_unlock(&data->lock); | ||
| 673 | return 0; | ||
| 674 | } | ||
| 675 | new_th = US5182D_PXL_TH_DISABLE; | ||
| 676 | if (state) { | ||
| 677 | data->power_mode = US5182D_CONTINUOUS; | ||
| 678 | ret = us5182d_set_power_state(data, true); | ||
| 679 | if (ret < 0) | ||
| 680 | goto err; | ||
| 681 | ret = us5182d_px_enable(data); | ||
| 682 | if (ret < 0) | ||
| 683 | goto err_poweroff; | ||
| 684 | new_th = data->px_low_th; | ||
| 685 | } | ||
| 686 | ret = us5182d_setup_prox(indio_dev, dir, new_th); | ||
| 687 | if (ret < 0) | ||
| 688 | goto err_poweroff; | ||
| 689 | data->falling_en = state; | ||
| 690 | break; | ||
| 691 | default: | ||
| 692 | ret = -EINVAL; | ||
| 693 | goto err; | ||
| 694 | } | ||
| 695 | |||
| 696 | if (!state) { | ||
| 697 | ret = us5182d_set_power_state(data, false); | ||
| 698 | if (ret < 0) | ||
| 699 | goto err; | ||
| 700 | } | ||
| 701 | |||
| 702 | if (!data->falling_en && !data->rising_en && !data->default_continuous) | ||
| 703 | data->power_mode = US5182D_ONESHOT; | ||
| 704 | |||
| 705 | mutex_unlock(&data->lock); | ||
| 706 | return 0; | ||
| 707 | |||
| 708 | err_poweroff: | ||
| 709 | if (state) | ||
| 710 | us5182d_set_power_state(data, false); | ||
| 711 | err: | ||
| 712 | mutex_unlock(&data->lock); | ||
| 713 | return ret; | ||
| 714 | } | ||
| 715 | |||
| 482 | static const struct iio_info us5182d_info = { | 716 | static const struct iio_info us5182d_info = { |
| 483 | .driver_module = THIS_MODULE, | 717 | .driver_module = THIS_MODULE, |
| 484 | .read_raw = us5182d_read_raw, | 718 | .read_raw = us5182d_read_raw, |
| 485 | .write_raw = us5182d_write_raw, | 719 | .write_raw = us5182d_write_raw, |
| 486 | .attrs = &us5182d_attr_group, | 720 | .attrs = &us5182d_attr_group, |
| 721 | .read_event_value = &us5182d_read_thresh, | ||
| 722 | .write_event_value = &us5182d_write_thresh, | ||
| 723 | .read_event_config = &us5182d_read_event_config, | ||
| 724 | .write_event_config = &us5182d_write_event_config, | ||
| 487 | }; | 725 | }; |
| 488 | 726 | ||
| 489 | static int us5182d_reset(struct iio_dev *indio_dev) | 727 | static int us5182d_reset(struct iio_dev *indio_dev) |
| @@ -505,6 +743,9 @@ static int us5182d_init(struct iio_dev *indio_dev) | |||
| 505 | 743 | ||
| 506 | data->opmode = 0; | 744 | data->opmode = 0; |
| 507 | data->power_mode = US5182D_CONTINUOUS; | 745 | data->power_mode = US5182D_CONTINUOUS; |
| 746 | data->px_low_th = US5182D_REG_PXL_TH_DEFAULT; | ||
| 747 | data->px_high_th = US5182D_REG_PXH_TH_DEFAULT; | ||
| 748 | |||
| 508 | for (i = 0; i < ARRAY_SIZE(us5182d_regvals); i++) { | 749 | for (i = 0; i < ARRAY_SIZE(us5182d_regvals); i++) { |
| 509 | ret = i2c_smbus_write_byte_data(data->client, | 750 | ret = i2c_smbus_write_byte_data(data->client, |
| 510 | us5182d_regvals[i].reg, | 751 | us5182d_regvals[i].reg, |
| @@ -575,6 +816,33 @@ static int us5182d_dark_gain_config(struct iio_dev *indio_dev) | |||
| 575 | US5182D_REG_DARK_AUTO_EN_DEFAULT); | 816 | US5182D_REG_DARK_AUTO_EN_DEFAULT); |
| 576 | } | 817 | } |
| 577 | 818 | ||
| 819 | static irqreturn_t us5182d_irq_thread_handler(int irq, void *private) | ||
| 820 | { | ||
| 821 | struct iio_dev *indio_dev = private; | ||
| 822 | struct us5182d_data *data = iio_priv(indio_dev); | ||
| 823 | enum iio_event_direction dir; | ||
| 824 | int ret; | ||
| 825 | u64 ev; | ||
| 826 | |||
| 827 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0); | ||
| 828 | if (ret < 0) { | ||
| 829 | dev_err(&data->client->dev, "i2c transfer error in irq\n"); | ||
| 830 | return IRQ_HANDLED; | ||
| 831 | } | ||
| 832 | |||
| 833 | dir = ret & US5182D_CFG0_PROX ? IIO_EV_DIR_RISING : IIO_EV_DIR_FALLING; | ||
| 834 | ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 1, IIO_EV_TYPE_THRESH, dir); | ||
| 835 | |||
| 836 | iio_push_event(indio_dev, ev, iio_get_time_ns()); | ||
| 837 | |||
| 838 | ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, | ||
| 839 | ret & ~US5182D_CFG0_PX_IRQ); | ||
| 840 | if (ret < 0) | ||
| 841 | dev_err(&data->client->dev, "i2c transfer error in irq\n"); | ||
| 842 | |||
| 843 | return IRQ_HANDLED; | ||
| 844 | } | ||
| 845 | |||
| 578 | static int us5182d_probe(struct i2c_client *client, | 846 | static int us5182d_probe(struct i2c_client *client, |
| 579 | const struct i2c_device_id *id) | 847 | const struct i2c_device_id *id) |
| 580 | { | 848 | { |
| @@ -606,6 +874,16 @@ static int us5182d_probe(struct i2c_client *client, | |||
| 606 | return (ret < 0) ? ret : -ENODEV; | 874 | return (ret < 0) ? ret : -ENODEV; |
| 607 | } | 875 | } |
| 608 | 876 | ||
| 877 | if (client->irq > 0) { | ||
| 878 | ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, | ||
| 879 | us5182d_irq_thread_handler, | ||
| 880 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
| 881 | "us5182d-irq", indio_dev); | ||
| 882 | if (ret < 0) | ||
| 883 | return ret; | ||
| 884 | } else | ||
| 885 | dev_warn(&client->dev, "no valid irq found\n"); | ||
| 886 | |||
| 609 | us5182d_get_platform_data(indio_dev); | 887 | us5182d_get_platform_data(indio_dev); |
| 610 | ret = us5182d_init(indio_dev); | 888 | ret = us5182d_init(indio_dev); |
| 611 | if (ret < 0) | 889 | if (ret < 0) |
diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c index 20b878d35ea2..1920dc60cf3d 100644 --- a/drivers/staging/iio/accel/sca3000_ring.c +++ b/drivers/staging/iio/accel/sca3000_ring.c | |||
| @@ -48,7 +48,7 @@ static int sca3000_read_data(struct sca3000_state *st, | |||
| 48 | } | 48 | } |
| 49 | }; | 49 | }; |
| 50 | *rx_p = kmalloc(len, GFP_KERNEL); | 50 | *rx_p = kmalloc(len, GFP_KERNEL); |
| 51 | if (*rx_p == NULL) { | 51 | if (!*rx_p) { |
| 52 | ret = -ENOMEM; | 52 | ret = -ENOMEM; |
| 53 | goto error_ret; | 53 | goto error_ret; |
| 54 | } | 54 | } |
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 19c94c9acc81..b5894118755f 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h | |||
| @@ -636,6 +636,8 @@ static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev) | |||
| 636 | } | 636 | } |
| 637 | #endif | 637 | #endif |
| 638 | 638 | ||
| 639 | ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals); | ||
| 640 | |||
| 639 | int iio_str_to_fixpoint(const char *str, int fract_mult, int *integer, | 641 | int iio_str_to_fixpoint(const char *str, int fract_mult, int *integer, |
| 640 | int *fract); | 642 | int *fract); |
| 641 | 643 | ||
