diff options
62 files changed, 2010 insertions, 425 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 8c24d0892f61..2db2cdf42d54 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1425,6 +1425,17 @@ Description: guarantees that the hardware fifo is flushed to the device buffer. +What: /sys/bus/iio/devices/iio:device*/buffer/hwfifo_timeout +KernelVersion: 4.12 +Contact: linux-iio@vger.kernel.org +Description: + A read/write property to provide capability to delay reporting of + samples till a timeout is reached. This allows host processors to + sleep, while the sensor is storing samples in its internal fifo. + The maximum timeout in seconds can be specified by setting + hwfifo_timeout.The current delay can be read by reading + hwfifo_timeout. A value of 0 means that there is no timeout. + What: /sys/bus/iio/devices/iio:deviceX/buffer/hwfifo_watermark KernelVersion: 4.2 Contact: linux-iio@vger.kernel.org diff --git a/Documentation/ABI/testing/sysfs-bus-iio-meas-spec b/Documentation/ABI/testing/sysfs-bus-iio-meas-spec index 1a6265e92e2f..6d47e548eee5 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio-meas-spec +++ b/Documentation/ABI/testing/sysfs-bus-iio-meas-spec @@ -5,4 +5,3 @@ Description: Reading returns either '1' or '0'. '1' means that the battery level supplied to sensor is below 2.25V. This ABI is available for tsys02d, htu21, ms8607 - This ABI is available for htu21, ms8607 diff --git a/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 b/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 index 230020e06677..deb015935683 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 +++ b/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32 @@ -16,6 +16,54 @@ Description: - "OC2REF" : OC2REF signal is used as trigger output. - "OC3REF" : OC3REF signal is used as trigger output. - "OC4REF" : OC4REF signal is used as trigger output. + Additional modes (on TRGO2 only): + - "OC5REF" : OC5REF signal is used as trigger output. + - "OC6REF" : OC6REF signal is used as trigger output. + - "compare_pulse_OC4REF": + OC4REF rising or falling edges generate pulses. + - "compare_pulse_OC6REF": + OC6REF rising or falling edges generate pulses. + - "compare_pulse_OC4REF_r_or_OC6REF_r": + OC4REF or OC6REF rising edges generate pulses. + - "compare_pulse_OC4REF_r_or_OC6REF_f": + OC4REF rising or OC6REF falling edges generate pulses. + - "compare_pulse_OC5REF_r_or_OC6REF_r": + OC5REF or OC6REF rising edges generate pulses. + - "compare_pulse_OC5REF_r_or_OC6REF_f": + OC5REF rising or OC6REF falling edges generate pulses. + + +-----------+ +-------------+ +---------+ + | Prescaler +-> | Counter | +-> | Master | TRGO(2) + +-----------+ +--+--------+-+ |-> | Control +--> + | | || +---------+ + +--v--------+-+ OCxREF || +---------+ + | Chx compare +----------> | Output | ChX + +-----------+-+ | | Control +--> + . | | +---------+ + . | | . + +-----------v-+ OC6REF | . + | Ch6 compare +---------+> + +-------------+ + + Example with: "compare_pulse_OC4REF_r_or_OC6REF_r": + + X + X X + X . . X + X . . X + X . . X + count X . . . . X + . . . . + . . . . + +---------------+ + OC4REF | . . | + +-+ . . +-+ + . +---+ . + OC6REF . | | . + +-------+ +-------+ + +-+ +-+ + TRGO2 | | | | + +-+ +---+ +---------+ What: /sys/bus/iio/devices/triggerX/master_mode KernelVersion: 4.11 diff --git a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt index 047189192aec..f413e82c8b83 100644 --- a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt +++ b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt @@ -2,6 +2,8 @@ Required properties: - compatible: depending on the SoC this should be one of: + - "amlogic,meson8-saradc" for Meson8 + - "amlogic,meson8b-saradc" for Meson8b - "amlogic,meson-gxbb-saradc" for GXBB - "amlogic,meson-gxl-saradc" for GXL - "amlogic,meson-gxm-saradc" for GXM diff --git a/Documentation/devicetree/bindings/iio/adc/renesas,gyroadc.txt b/Documentation/devicetree/bindings/iio/adc/renesas,gyroadc.txt index f5b0adae6010..2a62908a774a 100644 --- a/Documentation/devicetree/bindings/iio/adc/renesas,gyroadc.txt +++ b/Documentation/devicetree/bindings/iio/adc/renesas,gyroadc.txt @@ -16,8 +16,7 @@ Required properties: - clocks: References to all the clocks specified in the clock-names property as specified in Documentation/devicetree/bindings/clock/clock-bindings.txt. -- clock-names: Shall contain "fck" and "if". The "fck" is the GyroADC block - clock, the "if" is the interface clock. +- clock-names: Shall contain "fck". The "fck" is the GyroADC block clock. - power-domains: Must contain a reference to the PM domain, if available. - #address-cells: Should be <1> (setting for the subnodes) for all ADCs except for "fujitsu,mb88101a". Should be <0> (setting for @@ -75,8 +74,8 @@ Example: adc@e6e54000 { compatible = "renesas,r8a7791-gyroadc", "renesas,rcar-gyroadc"; reg = <0 0xe6e54000 0 64>; - clocks = <&mstp9_clks R8A7791_CLK_GYROADC>, <&clk_65m>; - clock-names = "fck", "if"; + clocks = <&mstp9_clks R8A7791_CLK_GYROADC>; + clock-names = "fck"; power-domains = <&sysc R8A7791_PD_ALWAYS_ON>; pinctrl-0 = <&adc_pins>; diff --git a/Documentation/devicetree/bindings/iio/adc/ti-adc084s021.txt b/Documentation/devicetree/bindings/iio/adc/ti-adc084s021.txt new file mode 100644 index 000000000000..4259e50620bc --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/ti-adc084s021.txt @@ -0,0 +1,19 @@ +* Texas Instruments' ADC084S021 + +Required properties: + - compatible : Must be "ti,adc084s021" + - reg : SPI chip select number for the device + - vref-supply : The regulator supply for ADC reference voltage + - spi-cpol : Per spi-bus bindings + - spi-cpha : Per spi-bus bindings + - spi-max-frequency : Per spi-bus bindings + +Example: +adc@0 { + compatible = "ti,adc084s021"; + reg = <0>; + vref-supply = <&adc_vref>; + spi-cpol; + spi-cpha; + spi-max-frequency = <16000000>; +}; diff --git a/Documentation/devicetree/bindings/iio/adc/ti-adc108s102.txt b/Documentation/devicetree/bindings/iio/adc/ti-adc108s102.txt new file mode 100644 index 000000000000..bbbbb4a9f58f --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/ti-adc108s102.txt @@ -0,0 +1,18 @@ +* Texas Instruments' ADC108S102 and ADC128S102 ADC chip + +Required properties: + - compatible: Should be "ti,adc108s102" + - reg: spi chip select number for the device + - vref-supply: The regulator supply for ADC reference voltage + +Recommended properties: + - spi-max-frequency: Definition as per + Documentation/devicetree/bindings/spi/spi-bus.txt + +Example: +adc@0 { + compatible = "ti,adc108s102"; + reg = <0>; + vref-supply = <&vdd_supply>; + spi-max-frequency = <1000000>; +}; diff --git a/Documentation/devicetree/bindings/trivial-devices.txt b/Documentation/devicetree/bindings/trivial-devices.txt index 3e0a34c88e07..35f406dd86b6 100644 --- a/Documentation/devicetree/bindings/trivial-devices.txt +++ b/Documentation/devicetree/bindings/trivial-devices.txt @@ -55,6 +55,7 @@ gmt,g751 G751: Digital Temperature Sensor and Thermal Watchdog with Two-Wire In infineon,slb9635tt Infineon SLB9635 (Soft-) I2C TPM (old protocol, max 100khz) infineon,slb9645tt Infineon SLB9645 I2C TPM (new protocol, max 400khz) isil,isl29028 Intersil ISL29028 Ambient Light and Proximity Sensor +isil,isl29030 Intersil ISL29030 Ambient Light and Proximity Sensor maxim,ds1050 5 Bit Programmable, Pulse-Width Modulator maxim,max1237 Low-Power, 4-/12-Channel, 2-Wire Serial, 12-Bit ADCs maxim,max6625 9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index efc67739c28f..17b7953f2502 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -14,6 +14,7 @@ * BMA250: 7-bit I2C slave address 0x18 or 0x19 */ +#include <linux/acpi.h> #include <linux/module.h> #include <linux/i2c.h> #include <linux/interrupt.h> @@ -36,6 +37,7 @@ enum chip_ids { BMA180, BMA250, + BMA250E, }; struct bma180_data; @@ -55,6 +57,7 @@ struct bma180_part_info { u8 power_reg, power_mask, lowpower_val; u8 int_enable_reg, int_enable_mask; u8 softreset_reg; + u8 chip_id; int (*chip_config)(struct bma180_data *data); void (*chip_disable)(struct bma180_data *data); @@ -112,6 +115,8 @@ struct bma180_part_info { #define BMA250_INT1_DATA_MASK BIT(0) #define BMA250_INT_RESET_MASK BIT(7) /* Reset pending interrupts */ +#define BMA250E_CHIP_ID 0xf9 + struct bma180_data { struct i2c_client *client; struct iio_trigger *trig; @@ -309,7 +314,7 @@ static int bma180_chip_init(struct bma180_data *data) if (ret < 0) return ret; - if (ret != BMA180_ID_REG_VAL) + if (ret != data->part_info->chip_id) return -ENODEV; ret = bma180_soft_reset(data); @@ -632,6 +637,7 @@ static const struct bma180_part_info bma180_part_info[] = { BMA180_TCO_Z, BMA180_MODE_CONFIG, BMA180_LOW_POWER, BMA180_CTRL_REG3, BMA180_NEW_DATA_INT, BMA180_RESET, + BMA180_CHIP_ID, bma180_chip_config, bma180_chip_disable, }, @@ -646,6 +652,22 @@ static const struct bma180_part_info bma180_part_info[] = { BMA250_POWER_REG, BMA250_LOWPOWER_MASK, 1, BMA250_INT_ENABLE_REG, BMA250_DATA_INTEN_MASK, BMA250_RESET_REG, + BMA180_CHIP_ID, + bma250_chip_config, + bma250_chip_disable, + }, + [BMA250E] = { + bma250_channels, ARRAY_SIZE(bma250_channels), + bma250_scale_table, ARRAY_SIZE(bma250_scale_table), + bma250_bw_table, ARRAY_SIZE(bma250_bw_table), + BMA250_INT_RESET_REG, BMA250_INT_RESET_MASK, + BMA250_POWER_REG, BMA250_SUSPEND_MASK, + BMA250_BW_REG, BMA250_BW_MASK, + BMA250_RANGE_REG, BMA250_RANGE_MASK, + BMA250_POWER_REG, BMA250_LOWPOWER_MASK, 1, + BMA250_INT_ENABLE_REG, BMA250_DATA_INTEN_MASK, + BMA250_RESET_REG, + BMA250E_CHIP_ID, bma250_chip_config, bma250_chip_disable, }, @@ -706,6 +728,8 @@ static const struct iio_trigger_ops bma180_trigger_ops = { static int bma180_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; + const struct acpi_device_id *acpi_id; struct bma180_data *data; struct iio_dev *indio_dev; enum chip_ids chip; @@ -718,10 +742,17 @@ static int bma180_probe(struct i2c_client *client, data = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); data->client = client; - if (client->dev.of_node) + if (dev->of_node) { chip = (enum chip_ids)of_device_get_match_data(&client->dev); - else + } else if (id) { chip = id->driver_data; + } else { + acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev); + if (!acpi_id) + return -ENODEV; + + chip = acpi_id->driver_data; + } data->part_info = &bma180_part_info[chip]; ret = data->part_info->chip_config(data); @@ -842,9 +873,16 @@ static SIMPLE_DEV_PM_OPS(bma180_pm_ops, bma180_suspend, bma180_resume); #define BMA180_PM_OPS NULL #endif +static const struct acpi_device_id bma180_acpi_match[] = { + { "BMA250E", BMA250E }, + { } +}; +MODULE_DEVICE_TABLE(acpi, bma180_acpi_match); + static struct i2c_device_id bma180_ids[] = { { "bma180", BMA180 }, { "bma250", BMA250 }, + { "bma250e", BMA250E }, { } }; @@ -866,6 +904,7 @@ MODULE_DEVICE_TABLE(of, bma180_of_match); static struct i2c_driver bma180_driver = { .driver = { .name = "bma180", + .acpi_match_table = ACPI_PTR(bma180_acpi_match), .pm = BMA180_PM_OPS, .of_match_table = bma180_of_match, }, diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c index 43a6cb078193..2238a26aba63 100644 --- a/drivers/iio/accel/hid-sensor-accel-3d.c +++ b/drivers/iio/accel/hid-sensor-accel-3d.c @@ -347,7 +347,7 @@ static int accel_3d_parse_report(struct platform_device *pdev, static int hid_accel_3d_probe(struct platform_device *pdev) { int ret = 0; - static const char *name; + const char *name; struct iio_dev *indio_dev; struct accel_3d_state *accel_state; const struct iio_chan_spec *channel_spec; diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index 784670e2736b..07d1489cd457 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -710,6 +710,8 @@ static const struct iio_trigger_ops st_accel_trigger_ops = { int st_accel_common_probe(struct iio_dev *indio_dev) { struct st_sensor_data *adata = iio_priv(indio_dev); + struct st_sensors_platform_data *pdata = + (struct st_sensors_platform_data *)adata->dev->platform_data; int irq = adata->get_irq_data_ready(indio_dev); int err; @@ -736,9 +738,8 @@ int st_accel_common_probe(struct iio_dev *indio_dev) &adata->sensor_settings->fs.fs_avl[0]; adata->odr = adata->sensor_settings->odr.odr_avl[0].hz; - if (!adata->dev->platform_data) - adata->dev->platform_data = - (struct st_sensors_platform_data *)&default_accel_pdata; + if (!pdata) + pdata = (struct st_sensors_platform_data *)&default_accel_pdata; err = st_sensors_init_sensor(indio_dev, adata->dev->platform_data); if (err < 0) diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 401f47b51d83..614fa41559b1 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -679,6 +679,18 @@ config TI_ADC0832 This driver can also be built as a module. If so, the module will be called ti-adc0832. +config TI_ADC084S021 + tristate "Texas Instruments ADC084S021" + depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + If you say yes here you get support for Texas Instruments ADC084S021 + chips. + + This driver can also be built as a module. If so, the module will be + called ti-adc084s021. + config TI_ADC12138 tristate "Texas Instruments ADC12130/ADC12132/ADC12138" depends on SPI @@ -691,6 +703,18 @@ config TI_ADC12138 This driver can also be built as a module. If so, the module will be called ti-adc12138. +config TI_ADC108S102 + tristate "Texas Instruments ADC108S102 and ADC128S102 driver" + depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes here to build support for Texas Instruments ADC108S102 and + ADC128S102 ADC. + + To compile this driver as a module, choose M here: the module will + be called ti-adc108s102. + config TI_ADC128S052 tristate "Texas Instruments ADC128S052/ADC122S021/ADC124S021" depends on SPI diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 9339bec4babe..b546736a5541 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -62,7 +62,9 @@ obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o obj-$(CONFIG_STM32_ADC) += stm32-adc.o obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o +obj-$(CONFIG_TI_ADC084S021) += ti-adc084s021.o obj-$(CONFIG_TI_ADC12138) += ti-adc12138.o +obj-$(CONFIG_TI_ADC108S102) += ti-adc108s102.o obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o obj-$(CONFIG_TI_ADC161S626) += ti-adc161s626.o obj-$(CONFIG_TI_ADS1015) += ti-ads1015.o diff --git a/drivers/iio/adc/hi8435.c b/drivers/iio/adc/hi8435.c index 678e8c7ea763..ab59969b7c49 100644 --- a/drivers/iio/adc/hi8435.c +++ b/drivers/iio/adc/hi8435.c @@ -105,6 +105,26 @@ static int hi8435_writew(struct hi8435_priv *priv, u8 reg, u16 val) return spi_write(priv->spi, priv->reg_buffer, 3); } +static int hi8435_read_raw(struct iio_dev *idev, + const struct iio_chan_spec *chan, + int *val, int *val2, long mask) +{ + struct hi8435_priv *priv = iio_priv(idev); + u32 tmp; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = hi8435_readl(priv, HI8435_SO31_0_REG, &tmp); + if (ret < 0) + return ret; + *val = !!(tmp & BIT(chan->channel)); + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + static int hi8435_read_event_config(struct iio_dev *idev, const struct iio_chan_spec *chan, enum iio_event_type type, @@ -121,10 +141,21 @@ static int hi8435_write_event_config(struct iio_dev *idev, enum iio_event_direction dir, int state) { struct hi8435_priv *priv = iio_priv(idev); + int ret; + u32 tmp; + + if (state) { + ret = hi8435_readl(priv, HI8435_SO31_0_REG, &tmp); + if (ret < 0) + return ret; + if (tmp & BIT(chan->channel)) + priv->event_prev_val |= BIT(chan->channel); + else + priv->event_prev_val &= ~BIT(chan->channel); - priv->event_scan_mask &= ~BIT(chan->channel); - if (state) priv->event_scan_mask |= BIT(chan->channel); + } else + priv->event_scan_mask &= ~BIT(chan->channel); return 0; } @@ -325,6 +356,7 @@ static const struct iio_enum hi8435_sensing_mode = { static const struct iio_chan_spec_ext_info hi8435_ext_info[] = { IIO_ENUM("sensing_mode", IIO_SEPARATE, &hi8435_sensing_mode), + IIO_ENUM_AVAILABLE("sensing_mode", &hi8435_sensing_mode), {}, }; @@ -333,6 +365,7 @@ static const struct iio_chan_spec_ext_info hi8435_ext_info[] = { .type = IIO_VOLTAGE, \ .indexed = 1, \ .channel = num, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .event_spec = hi8435_events, \ .num_event_specs = ARRAY_SIZE(hi8435_events), \ .ext_info = hi8435_ext_info, \ @@ -376,6 +409,7 @@ static const struct iio_chan_spec hi8435_channels[] = { static const struct iio_info hi8435_info = { .driver_module = THIS_MODULE, + .read_raw = hi8435_read_raw, .read_event_config = &hi8435_read_event_config, .write_event_config = hi8435_write_event_config, .read_event_value = &hi8435_read_event_value, @@ -442,13 +476,15 @@ static int hi8435_probe(struct spi_device *spi) priv->spi = spi; reset_gpio = devm_gpiod_get(&spi->dev, NULL, GPIOD_OUT_LOW); - if (IS_ERR(reset_gpio)) { - /* chip s/w reset if h/w reset failed */ + if (!IS_ERR(reset_gpio)) { + /* need >=100ns low pulse to reset chip */ + gpiod_set_raw_value_cansleep(reset_gpio, 0); + udelay(1); + gpiod_set_raw_value_cansleep(reset_gpio, 1); + } else { + /* s/w reset chip if h/w reset is not available */ hi8435_writeb(priv, HI8435_CTRL_REG, HI8435_CTRL_SRST); hi8435_writeb(priv, HI8435_CTRL_REG, 0); - } else { - udelay(5); - gpiod_set_value(reset_gpio, 1); } spi_set_drvdata(spi, idev); diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index db9838230257..6b588ac3130c 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -42,8 +42,8 @@ #define INA2XX_CURRENT 0x04 /* readonly */ #define INA2XX_CALIBRATION 0x05 -#define INA226_ALERT_MASK GENMASK(2, 1) -#define INA266_CVRF BIT(3) +#define INA226_MASK_ENABLE 0x06 +#define INA226_CVRF BIT(3) #define INA2XX_MAX_REGISTERS 8 @@ -417,8 +417,8 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev, .address = (_address), \ .indexed = 1, \ .channel = (_index), \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) \ - | BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ .scan_index = (_index), \ @@ -481,12 +481,12 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev) */ if (!chip->allow_async_readout) do { - ret = regmap_read(chip->regmap, INA226_ALERT_MASK, + ret = regmap_read(chip->regmap, INA226_MASK_ENABLE, &alert); if (ret < 0) return ret; - alert &= INA266_CVRF; + alert &= INA226_CVRF; } while (!alert); /* diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index dd4190b50df6..81cd39a57fe3 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -220,6 +220,7 @@ enum meson_sar_adc_chan7_mux_sel { }; struct meson_sar_adc_data { + bool has_bl30_integration; unsigned int resolution; const char *name; }; @@ -437,19 +438,24 @@ static int meson_sar_adc_lock(struct iio_dev *indio_dev) mutex_lock(&indio_dev->mlock); - /* prevent BL30 from using the SAR ADC while we are using it */ - regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, - MESON_SAR_ADC_DELAY_KERNEL_BUSY, - MESON_SAR_ADC_DELAY_KERNEL_BUSY); - - /* wait until BL30 releases it's lock (so we can use the SAR ADC) */ - do { - udelay(1); - regmap_read(priv->regmap, MESON_SAR_ADC_DELAY, &val); - } while (val & MESON_SAR_ADC_DELAY_BL30_BUSY && timeout--); - - if (timeout < 0) - return -ETIMEDOUT; + if (priv->data->has_bl30_integration) { + /* prevent BL30 from using the SAR ADC while we are using it */ + regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, + MESON_SAR_ADC_DELAY_KERNEL_BUSY, + MESON_SAR_ADC_DELAY_KERNEL_BUSY); + + /* + * wait until BL30 releases it's lock (so we can use the SAR + * ADC) + */ + do { + udelay(1); + regmap_read(priv->regmap, MESON_SAR_ADC_DELAY, &val); + } while (val & MESON_SAR_ADC_DELAY_BL30_BUSY && timeout--); + + if (timeout < 0) + return -ETIMEDOUT; + } return 0; } @@ -458,9 +464,10 @@ static void meson_sar_adc_unlock(struct iio_dev *indio_dev) { struct meson_sar_adc_priv *priv = iio_priv(indio_dev); - /* allow BL30 to use the SAR ADC again */ - regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, - MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0); + if (priv->data->has_bl30_integration) + /* allow BL30 to use the SAR ADC again */ + regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, + MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0); mutex_unlock(&indio_dev->mlock); } @@ -614,14 +621,16 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev) */ meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT); - /* - * leave sampling delay and the input clocks as configured by BL30 to - * make sure BL30 gets the values it expects when reading the - * temperature sensor. - */ - regmap_read(priv->regmap, MESON_SAR_ADC_REG3, ®val); - if (regval & MESON_SAR_ADC_REG3_BL30_INITIALIZED) - return 0; + if (priv->data->has_bl30_integration) { + /* + * leave sampling delay and the input clocks as configured by + * BL30 to make sure BL30 gets the values it expects when + * reading the temperature sensor. + */ + regmap_read(priv->regmap, MESON_SAR_ADC_REG3, ®val); + if (regval & MESON_SAR_ADC_REG3_BL30_INITIALIZED) + return 0; + } meson_sar_adc_stop_sample_engine(indio_dev); @@ -834,23 +843,46 @@ static const struct iio_info meson_sar_adc_iio_info = { .driver_module = THIS_MODULE, }; -struct meson_sar_adc_data meson_sar_adc_gxbb_data = { +static const struct meson_sar_adc_data meson_sar_adc_meson8_data = { + .has_bl30_integration = false, + .resolution = 10, + .name = "meson-meson8-saradc", +}; + +static const struct meson_sar_adc_data meson_sar_adc_meson8b_data = { + .has_bl30_integration = false, + .resolution = 10, + .name = "meson-meson8b-saradc", +}; + +static const struct meson_sar_adc_data meson_sar_adc_gxbb_data = { + .has_bl30_integration = true, .resolution = 10, .name = "meson-gxbb-saradc", }; -struct meson_sar_adc_data meson_sar_adc_gxl_data = { +static const struct meson_sar_adc_data meson_sar_adc_gxl_data = { + .has_bl30_integration = true, .resolution = 12, .name = "meson-gxl-saradc", }; -struct meson_sar_adc_data meson_sar_adc_gxm_data = { +static const struct meson_sar_adc_data meson_sar_adc_gxm_data = { + .has_bl30_integration = true, .resolution = 12, .name = "meson-gxm-saradc", }; static const struct of_device_id meson_sar_adc_of_match[] = { { + .compatible = "amlogic,meson8-saradc", + .data = &meson_sar_adc_meson8_data, + }, + { + .compatible = "amlogic,meson8b-saradc", + .data = &meson_sar_adc_meson8b_data, + }, + { .compatible = "amlogic,meson-gxbb-saradc", .data = &meson_sar_adc_gxbb_data, }, { diff --git a/drivers/iio/adc/rcar-gyroadc.c b/drivers/iio/adc/rcar-gyroadc.c index 018ed360e717..27a318164619 100644 --- a/drivers/iio/adc/rcar-gyroadc.c +++ b/drivers/iio/adc/rcar-gyroadc.c @@ -73,7 +73,7 @@ enum rcar_gyroadc_model { struct rcar_gyroadc { struct device *dev; void __iomem *regs; - struct clk *iclk; + struct clk *clk; struct regulator *vref[8]; unsigned int num_channels; enum rcar_gyroadc_model model; @@ -83,7 +83,7 @@ struct rcar_gyroadc { static void rcar_gyroadc_hw_init(struct rcar_gyroadc *priv) { - const unsigned long clk_mhz = clk_get_rate(priv->iclk) / 1000000; + const unsigned long clk_mhz = clk_get_rate(priv->clk) / 1000000; const unsigned long clk_mul = (priv->mode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) ? 10 : 5; unsigned long clk_len = clk_mhz * clk_mul; @@ -510,9 +510,9 @@ static int rcar_gyroadc_probe(struct platform_device *pdev) if (IS_ERR(priv->regs)) return PTR_ERR(priv->regs); - priv->iclk = devm_clk_get(dev, "if"); - if (IS_ERR(priv->iclk)) { - ret = PTR_ERR(priv->iclk); + priv->clk = devm_clk_get(dev, "fck"); + if (IS_ERR(priv->clk)) { + ret = PTR_ERR(priv->clk); if (ret != -EPROBE_DEFER) dev_err(dev, "Failed to get IF clock (ret=%i)\n", ret); return ret; @@ -536,7 +536,7 @@ static int rcar_gyroadc_probe(struct platform_device *pdev) indio_dev->info = &rcar_gyroadc_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; - ret = clk_prepare_enable(priv->iclk); + ret = clk_prepare_enable(priv->clk); if (ret) { dev_err(dev, "Could not prepare or enable the IF clock.\n"); goto err_clk_if_enable; @@ -565,7 +565,7 @@ err_iio_device_register: pm_runtime_put_sync(dev); pm_runtime_disable(dev); pm_runtime_set_suspended(dev); - clk_disable_unprepare(priv->iclk); + clk_disable_unprepare(priv->clk); err_clk_if_enable: rcar_gyroadc_deinit_supplies(indio_dev); @@ -584,7 +584,7 @@ static int rcar_gyroadc_remove(struct platform_device *pdev) pm_runtime_put_sync(dev); pm_runtime_disable(dev); pm_runtime_set_suspended(dev); - clk_disable_unprepare(priv->iclk); + clk_disable_unprepare(priv->clk); rcar_gyroadc_deinit_supplies(indio_dev); return 0; diff --git a/drivers/iio/adc/ti-adc084s021.c b/drivers/iio/adc/ti-adc084s021.c new file mode 100644 index 000000000000..a355121c11a4 --- /dev/null +++ b/drivers/iio/adc/ti-adc084s021.c @@ -0,0 +1,275 @@ +/** + * Copyright (C) 2017 Axis Communications AB + * + * Driver for Texas Instruments' ADC084S021 ADC chip. + * Datasheets can be found here: + * http://www.ti.com/lit/ds/symlink/adc084s021.pdf + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/err.h> +#include <linux/spi/spi.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/iio/iio.h> +#include <linux/iio/buffer.h> +#include <linux/iio/triggered_buffer.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/regulator/consumer.h> + +#define ADC084S021_DRIVER_NAME "adc084s021" + +struct adc084s021 { + struct spi_device *spi; + struct spi_message message; + struct spi_transfer spi_trans; + struct regulator *reg; + struct mutex lock; + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache line. + */ + u16 tx_buf[4] ____cacheline_aligned; + __be16 rx_buf[5]; /* First 16-bits are trash */ +}; + +#define ADC084S021_VOLTAGE_CHANNEL(num) \ + { \ + .type = IIO_VOLTAGE, \ + .channel = (num), \ + .indexed = 1, \ + .scan_index = (num), \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 8, \ + .storagebits = 16, \ + .shift = 4, \ + .endianness = IIO_BE, \ + }, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ + } + +static const struct iio_chan_spec adc084s021_channels[] = { + ADC084S021_VOLTAGE_CHANNEL(0), + ADC084S021_VOLTAGE_CHANNEL(1), + ADC084S021_VOLTAGE_CHANNEL(2), + ADC084S021_VOLTAGE_CHANNEL(3), + IIO_CHAN_SOFT_TIMESTAMP(4), +}; + +/** + * Read an ADC channel and return its value. + * + * @adc: The ADC SPI data. + * @data: Buffer for converted data. + */ +static int adc084s021_adc_conversion(struct adc084s021 *adc, void *data) +{ + int n_words = (adc->spi_trans.len >> 1) - 1; /* Discard first word */ + int ret, i = 0; + u16 *p = data; + + /* Do the transfer */ + ret = spi_sync(adc->spi, &adc->message); + if (ret < 0) + return ret; + + for (; i < n_words; i++) + *(p + i) = adc->rx_buf[i + 1]; + + return ret; +} + +static int adc084s021_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *channel, int *val, + int *val2, long mask) +{ + struct adc084s021 *adc = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret < 0) + return ret; + + ret = regulator_enable(adc->reg); + if (ret) { + iio_device_release_direct_mode(indio_dev); + return ret; + } + + adc->tx_buf[0] = channel->channel << 3; + ret = adc084s021_adc_conversion(adc, val); + iio_device_release_direct_mode(indio_dev); + regulator_disable(adc->reg); + if (ret < 0) + return ret; + + *val = be16_to_cpu(*val); + *val = (*val >> channel->scan_type.shift) & 0xff; + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + ret = regulator_enable(adc->reg); + if (ret) + return ret; + + ret = regulator_get_voltage(adc->reg); + regulator_disable(adc->reg); + if (ret < 0) + return ret; + + *val = ret / 1000; + + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +/** + * Read enabled ADC channels and push data to the buffer. + * + * @irq: The interrupt number (not used). + * @pollfunc: Pointer to the poll func. + */ +static irqreturn_t adc084s021_buffer_trigger_handler(int irq, void *pollfunc) +{ + struct iio_poll_func *pf = pollfunc; + struct iio_dev *indio_dev = pf->indio_dev; + struct adc084s021 *adc = iio_priv(indio_dev); + __be16 data[8] = {0}; /* 4 * 16-bit words of data + 8 bytes timestamp */ + + mutex_lock(&adc->lock); + + if (adc084s021_adc_conversion(adc, &data) < 0) + dev_err(&adc->spi->dev, "Failed to read data\n"); + + iio_push_to_buffers_with_timestamp(indio_dev, data, + iio_get_time_ns(indio_dev)); + mutex_unlock(&adc->lock); + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int adc084s021_buffer_preenable(struct iio_dev *indio_dev) +{ + struct adc084s021 *adc = iio_priv(indio_dev); + int scan_index; + int i = 0; + + for_each_set_bit(scan_index, indio_dev->active_scan_mask, + indio_dev->masklength) { + const struct iio_chan_spec *channel = + &indio_dev->channels[scan_index]; + adc->tx_buf[i++] = channel->channel << 3; + } + adc->spi_trans.len = 2 + (i * sizeof(__be16)); /* Trash + channels */ + + return regulator_enable(adc->reg); +} + +static int adc084s021_buffer_postdisable(struct iio_dev *indio_dev) +{ + struct adc084s021 *adc = iio_priv(indio_dev); + + adc->spi_trans.len = 4; /* Trash + single channel */ + + return regulator_disable(adc->reg); +} + +static const struct iio_info adc084s021_info = { + .read_raw = adc084s021_read_raw, + .driver_module = THIS_MODULE, +}; + +static const struct iio_buffer_setup_ops adc084s021_buffer_setup_ops = { + .preenable = adc084s021_buffer_preenable, + .postenable = iio_triggered_buffer_postenable, + .predisable = iio_triggered_buffer_predisable, + .postdisable = adc084s021_buffer_postdisable, +}; + +static int adc084s021_probe(struct spi_device *spi) +{ + struct iio_dev *indio_dev; + struct adc084s021 *adc; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc)); + if (!indio_dev) { + dev_err(&spi->dev, "Failed to allocate IIO device\n"); + return -ENOMEM; + } + + adc = iio_priv(indio_dev); + adc->spi = spi; + + /* Connect the SPI device and the iio dev */ + spi_set_drvdata(spi, indio_dev); + + /* Initiate the Industrial I/O device */ + indio_dev->dev.parent = &spi->dev; + indio_dev->dev.of_node = spi->dev.of_node; + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &adc084s021_info; + indio_dev->channels = adc084s021_channels; + indio_dev->num_channels = ARRAY_SIZE(adc084s021_channels); + + /* Create SPI transfer for channel reads */ + adc->spi_trans.tx_buf = adc->tx_buf; + adc->spi_trans.rx_buf = adc->rx_buf; + adc->spi_trans.len = 4; /* Trash + single channel */ + spi_message_init_with_transfers(&adc->message, &adc->spi_trans, 1); + + adc->reg = devm_regulator_get(&spi->dev, "vref"); + if (IS_ERR(adc->reg)) + return PTR_ERR(adc->reg); + + mutex_init(&adc->lock); + + /* Setup triggered buffer with pollfunction */ + ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, NULL, + adc084s021_buffer_trigger_handler, + &adc084s021_buffer_setup_ops); + if (ret) { + dev_err(&spi->dev, "Failed to setup triggered buffer\n"); + return ret; + } + + return devm_iio_device_register(&spi->dev, indio_dev); +} + +static const struct of_device_id adc084s021_of_match[] = { + { .compatible = "ti,adc084s021", }, + {}, +}; +MODULE_DEVICE_TABLE(of, adc084s021_of_match); + +static const struct spi_device_id adc084s021_id[] = { + { ADC084S021_DRIVER_NAME, 0}, + {} +}; +MODULE_DEVICE_TABLE(spi, adc084s021_id); + +static struct spi_driver adc084s021_driver = { + .driver = { + .name = ADC084S021_DRIVER_NAME, + .of_match_table = of_match_ptr(adc084s021_of_match), + }, + .probe = adc084s021_probe, + .id_table = adc084s021_id, +}; +module_spi_driver(adc084s021_driver); + +MODULE_AUTHOR("Mårten Lindahl <martenli@axis.com>"); +MODULE_DESCRIPTION("Texas Instruments ADC084S021"); +MODULE_LICENSE("GPL v2"); +MODULE_VERSION("1.0"); diff --git a/drivers/iio/adc/ti-adc108s102.c b/drivers/iio/adc/ti-adc108s102.c new file mode 100644 index 000000000000..de4e5ac98c6e --- /dev/null +++ b/drivers/iio/adc/ti-adc108s102.c @@ -0,0 +1,348 @@ +/* + * TI ADC108S102 SPI ADC driver + * + * Copyright (c) 2013-2015 Intel Corporation. + * Copyright (c) 2017 Siemens AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * This IIO device driver is designed to work with the following + * analog to digital converters from Texas Instruments: + * ADC108S102 + * ADC128S102 + * The communication with ADC chip is via the SPI bus (mode 3). + */ + +#include <linux/acpi.h> +#include <linux/iio/iio.h> +#include <linux/iio/buffer.h> +#include <linux/iio/types.h> +#include <linux/iio/triggered_buffer.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/property.h> +#include <linux/regulator/consumer.h> +#include <linux/spi/spi.h> + +/* + * In case of ACPI, we use the hard-wired 5000 mV of the Galileo and IOT2000 + * boards as default for the reference pin VA. Device tree users encode that + * via the vref-supply regulator. + */ +#define ADC108S102_VA_MV_ACPI_DEFAULT 5000 + +/* + * Defining the ADC resolution being 12 bits, we can use the same driver for + * both ADC108S102 (10 bits resolution) and ADC128S102 (12 bits resolution) + * chips. The ADC108S102 effectively returns a 12-bit result with the 2 + * least-significant bits unset. + */ +#define ADC108S102_BITS 12 +#define ADC108S102_MAX_CHANNELS 8 + +/* + * 16-bit SPI command format: + * [15:14] Ignored + * [13:11] 3-bit channel address + * [10:0] Ignored + */ +#define ADC108S102_CMD(ch) ((u16)(ch) << 11) + +/* + * 16-bit SPI response format: + * [15:12] Zeros + * [11:0] 12-bit ADC sample (for ADC108S102, [1:0] will always be 0). + */ +#define ADC108S102_RES_DATA(res) ((u16)res & GENMASK(11, 0)) + +struct adc108s102_state { + struct spi_device *spi; + struct regulator *reg; + u32 va_millivolt; + /* SPI transfer used by triggered buffer handler*/ + struct spi_transfer ring_xfer; + /* SPI transfer used by direct scan */ + struct spi_transfer scan_single_xfer; + /* SPI message used by ring_xfer SPI transfer */ + struct spi_message ring_msg; + /* SPI message used by scan_single_xfer SPI transfer */ + struct spi_message scan_single_msg; + + /* + * SPI message buffers: + * tx_buf: |C0|C1|C2|C3|C4|C5|C6|C7|XX| + * rx_buf: |XX|R0|R1|R2|R3|R4|R5|R6|R7|tt|tt|tt|tt| + * + * tx_buf: 8 channel read commands, plus 1 dummy command + * rx_buf: 1 dummy response, 8 channel responses, plus 64-bit timestamp + */ + __be16 rx_buf[13] ____cacheline_aligned; + __be16 tx_buf[9] ____cacheline_aligned; +}; + +#define ADC108S102_V_CHAN(index) \ + { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = index, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .address = index, \ + .scan_index = index, \ + .scan_type = { \ + .sign = 'u', \ + .realbits = ADC108S102_BITS, \ + .storagebits = 16, \ + .endianness = IIO_BE, \ + }, \ + } + +static const struct iio_chan_spec adc108s102_channels[] = { + ADC108S102_V_CHAN(0), + ADC108S102_V_CHAN(1), + ADC108S102_V_CHAN(2), + ADC108S102_V_CHAN(3), + ADC108S102_V_CHAN(4), + ADC108S102_V_CHAN(5), + ADC108S102_V_CHAN(6), + ADC108S102_V_CHAN(7), + IIO_CHAN_SOFT_TIMESTAMP(8), +}; + +static int adc108s102_update_scan_mode(struct iio_dev *indio_dev, + unsigned long const *active_scan_mask) +{ + struct adc108s102_state *st = iio_priv(indio_dev); + unsigned int bit, cmds; + + /* + * Fill in the first x shorts of tx_buf with the number of channels + * enabled for sampling by the triggered buffer. + */ + cmds = 0; + for_each_set_bit(bit, active_scan_mask, ADC108S102_MAX_CHANNELS) + st->tx_buf[cmds++] = cpu_to_be16(ADC108S102_CMD(bit)); + + /* One dummy command added, to clock in the last response */ + st->tx_buf[cmds++] = 0x00; + + /* build SPI ring message */ + st->ring_xfer.tx_buf = &st->tx_buf[0]; + st->ring_xfer.rx_buf = &st->rx_buf[0]; + st->ring_xfer.len = cmds * sizeof(st->tx_buf[0]); + + spi_message_init_with_transfers(&st->ring_msg, &st->ring_xfer, 1); + + return 0; +} + +static irqreturn_t adc108s102_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct adc108s102_state *st = iio_priv(indio_dev); + int ret; + + ret = spi_sync(st->spi, &st->ring_msg); + if (ret < 0) + goto out_notify; + + /* Skip the dummy response in the first slot */ + iio_push_to_buffers_with_timestamp(indio_dev, + (u8 *)&st->rx_buf[1], + iio_get_time_ns(indio_dev)); + +out_notify: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int adc108s102_scan_direct(struct adc108s102_state *st, unsigned int ch) +{ + int ret; + + st->tx_buf[0] = cpu_to_be16(ADC108S102_CMD(ch)); + ret = spi_sync(st->spi, &st->scan_single_msg); + if (ret) + return ret; + + /* Skip the dummy response in the first slot */ + return be16_to_cpu(st->rx_buf[1]); +} + +static int adc108s102_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long m) +{ + struct adc108s102_state *st = iio_priv(indio_dev); + int ret; + + switch (m) { + case IIO_CHAN_INFO_RAW: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + ret = adc108s102_scan_direct(st, chan->address); + + iio_device_release_direct_mode(indio_dev); + + if (ret < 0) + return ret; + + *val = ADC108S102_RES_DATA(ret); + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + if (chan->type != IIO_VOLTAGE) + break; + + *val = st->va_millivolt; + *val2 = chan->scan_type.realbits; + + return IIO_VAL_FRACTIONAL_LOG2; + default: + break; + } + + return -EINVAL; +} + +static const struct iio_info adc108s102_info = { + .read_raw = &adc108s102_read_raw, + .update_scan_mode = &adc108s102_update_scan_mode, + .driver_module = THIS_MODULE, +}; + +static int adc108s102_probe(struct spi_device *spi) +{ + struct adc108s102_state *st; + struct iio_dev *indio_dev; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st = iio_priv(indio_dev); + + if (ACPI_COMPANION(&spi->dev)) { + st->va_millivolt = ADC108S102_VA_MV_ACPI_DEFAULT; + } else { + st->reg = devm_regulator_get(&spi->dev, "vref"); + if (IS_ERR(st->reg)) + return PTR_ERR(st->reg); + + ret = regulator_enable(st->reg); + if (ret < 0) { + dev_err(&spi->dev, "Cannot enable vref regulator\n"); + return ret; + } + + ret = regulator_get_voltage(st->reg); + if (ret < 0) { + dev_err(&spi->dev, "vref get voltage failed\n"); + return ret; + } + + st->va_millivolt = ret / 1000; + } + + spi_set_drvdata(spi, indio_dev); + st->spi = spi; + + indio_dev->name = spi->modalias; + indio_dev->dev.parent = &spi->dev; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = adc108s102_channels; + indio_dev->num_channels = ARRAY_SIZE(adc108s102_channels); + indio_dev->info = &adc108s102_info; + + /* Setup default message */ + st->scan_single_xfer.tx_buf = st->tx_buf; + st->scan_single_xfer.rx_buf = st->rx_buf; + st->scan_single_xfer.len = 2 * sizeof(st->tx_buf[0]); + + spi_message_init_with_transfers(&st->scan_single_msg, + &st->scan_single_xfer, 1); + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + &adc108s102_trigger_handler, NULL); + if (ret) + goto error_disable_reg; + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&spi->dev, "Failed to register IIO device\n"); + goto error_cleanup_triggered_buffer; + } + return 0; + +error_cleanup_triggered_buffer: + iio_triggered_buffer_cleanup(indio_dev); + +error_disable_reg: + regulator_disable(st->reg); + + return ret; +} + +static int adc108s102_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct adc108s102_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + + regulator_disable(st->reg); + + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id adc108s102_of_match[] = { + { .compatible = "ti,adc108s102" }, + { } +}; +MODULE_DEVICE_TABLE(of, adc108s102_of_match); +#endif + +#ifdef CONFIG_ACPI +static const struct acpi_device_id adc108s102_acpi_ids[] = { + { "INT3495", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, adc108s102_acpi_ids); +#endif + +static const struct spi_device_id adc108s102_id[] = { + { "adc108s102", 0 }, + { } +}; +MODULE_DEVICE_TABLE(spi, adc108s102_id); + +static struct spi_driver adc108s102_driver = { + .driver = { + .name = "adc108s102", + .of_match_table = of_match_ptr(adc108s102_of_match), + .acpi_match_table = ACPI_PTR(adc108s102_acpi_ids), + }, + .probe = adc108s102_probe, + .remove = adc108s102_remove, + .id_table = adc108s102_id, +}; +module_spi_driver(adc108s102_driver); + +MODULE_AUTHOR("Bogdan Pricop <bogdan.pricop@emutex.com>"); +MODULE_DESCRIPTION("Texas Instruments ADC108S102 and ADC128S102 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c index 1c0874cdf665..f5d4d786e193 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c @@ -69,6 +69,12 @@ static struct { {HID_USAGE_SENSOR_TIME_TIMESTAMP, HID_USAGE_SENSOR_UNITS_MILLISECOND, 1000000, 0}, + {HID_USAGE_SENSOR_DEVICE_ORIENTATION, 0, 1, 0}, + + {HID_USAGE_SENSOR_RELATIVE_ORIENTATION, 0, 1, 0}, + + {HID_USAGE_SENSOR_GEOMAGNETIC_ORIENTATION, 0, 1, 0}, + {HID_USAGE_SENSOR_TEMPERATURE, 0, 1000, 0}, {HID_USAGE_SENSOR_TEMPERATURE, HID_USAGE_SENSOR_UNITS_DEGREES, 1000, 0}, @@ -230,7 +236,7 @@ int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st, ret = sensor_hub_set_feature(st->hsdev, st->poll.report_id, st->poll.index, sizeof(value), &value); if (ret < 0 || value < 0) - ret = -EINVAL; + return -EINVAL; ret = sensor_hub_get_feature(st->hsdev, st->poll.report_id, @@ -283,7 +289,7 @@ int hid_sensor_write_raw_hyst_value(struct hid_sensor_common *st, st->sensitivity.index, sizeof(value), &value); if (ret < 0 || value < 0) - ret = -EINVAL; + return -EINVAL; ret = sensor_hub_get_feature(st->hsdev, st->sensitivity.report_id, @@ -404,6 +410,48 @@ int hid_sensor_get_reporting_interval(struct hid_sensor_hub_device *hsdev, } +static void hid_sensor_get_report_latency_info(struct hid_sensor_hub_device *hsdev, + u32 usage_id, + struct hid_sensor_common *st) +{ + sensor_hub_input_get_attribute_info(hsdev, HID_FEATURE_REPORT, + usage_id, + HID_USAGE_SENSOR_PROP_REPORT_LATENCY, + &st->report_latency); + + hid_dbg(hsdev->hdev, "Report latency attributes: %x:%x\n", + st->report_latency.index, st->report_latency.report_id); +} + +int hid_sensor_get_report_latency(struct hid_sensor_common *st) +{ + int ret; + int value; + + ret = sensor_hub_get_feature(st->hsdev, st->report_latency.report_id, + st->report_latency.index, sizeof(value), + &value); + if (ret < 0) + return ret; + + return value; +} +EXPORT_SYMBOL(hid_sensor_get_report_latency); + +int hid_sensor_set_report_latency(struct hid_sensor_common *st, int latency_ms) +{ + return sensor_hub_set_feature(st->hsdev, st->report_latency.report_id, + st->report_latency.index, + sizeof(latency_ms), &latency_ms); +} +EXPORT_SYMBOL(hid_sensor_set_report_latency); + +bool hid_sensor_batch_mode_supported(struct hid_sensor_common *st) +{ + return st->report_latency.index > 0 && st->report_latency.report_id > 0; +} +EXPORT_SYMBOL(hid_sensor_batch_mode_supported); + int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev, u32 usage_id, struct hid_sensor_common *st) @@ -445,6 +493,8 @@ int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev, } else st->timestamp_ns_scale = 1000000000; + hid_sensor_get_report_latency_info(hsdev, usage_id, st); + hid_dbg(hsdev->hdev, "common attributes: %x:%x, %x:%x, %x:%x %x:%x %x:%x\n", st->poll.index, st->poll.report_id, st->report_state.index, st->report_state.report_id, diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c index 0b5dea050239..16ade0a0327b 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c @@ -26,9 +26,84 @@ #include <linux/hid-sensor-hub.h> #include <linux/iio/iio.h> #include <linux/iio/trigger.h> +#include <linux/iio/buffer.h> #include <linux/iio/sysfs.h> #include "hid-sensor-trigger.h" +static ssize_t _hid_sensor_set_report_latency(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev); + int integer, fract, ret; + int latency; + + ret = iio_str_to_fixpoint(buf, 100000, &integer, &fract); + if (ret) + return ret; + + latency = integer * 1000 + fract / 1000; + ret = hid_sensor_set_report_latency(attrb, latency); + if (ret < 0) + return len; + + attrb->latency_ms = hid_sensor_get_report_latency(attrb); + + return len; +} + +static ssize_t _hid_sensor_get_report_latency(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev); + int latency; + + latency = hid_sensor_get_report_latency(attrb); + if (latency < 0) + return latency; + + return sprintf(buf, "%d.%06u\n", latency / 1000, (latency % 1000) * 1000); +} + +static ssize_t _hid_sensor_get_fifo_state(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev); + int latency; + + latency = hid_sensor_get_report_latency(attrb); + if (latency < 0) + return latency; + + return sprintf(buf, "%d\n", !!latency); +} + +static IIO_DEVICE_ATTR(hwfifo_timeout, 0644, + _hid_sensor_get_report_latency, + _hid_sensor_set_report_latency, 0); +static IIO_DEVICE_ATTR(hwfifo_enabled, 0444, + _hid_sensor_get_fifo_state, NULL, 0); + +static const struct attribute *hid_sensor_fifo_attributes[] = { + &iio_dev_attr_hwfifo_timeout.dev_attr.attr, + &iio_dev_attr_hwfifo_enabled.dev_attr.attr, + NULL, +}; + +static void hid_sensor_setup_batch_mode(struct iio_dev *indio_dev, + struct hid_sensor_common *st) +{ + if (!hid_sensor_batch_mode_supported(st)) + return; + + iio_buffer_set_attrs(indio_dev->buffer, hid_sensor_fifo_attributes); +} + static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state) { int state_val; @@ -141,6 +216,9 @@ static void hid_sensor_set_power_work(struct work_struct *work) sizeof(attrb->raw_hystersis), &attrb->raw_hystersis); + if (attrb->latency_ms > 0) + hid_sensor_set_report_latency(attrb, attrb->latency_ms); + _hid_sensor_power_state(attrb, true); } @@ -192,6 +270,8 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, attrb->trigger = trig; indio_dev->trig = iio_trigger_get(trig); + hid_sensor_setup_batch_mode(indio_dev, attrb); + ret = pm_runtime_set_active(&indio_dev->dev); if (ret) goto error_unreg_trigger; diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index df5abc46cd3f..25bed2d7d2b9 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -13,7 +13,8 @@ config AD5064 AD5045, AD5064, AD5064-1, AD5065, AD5625, AD5625R, AD5627, AD5627R, AD5628, AD5629R, AD5645R, AD5647R, AD5648, AD5665, AD5665R, AD5666, AD5667, AD5667R, AD5668, AD5669R, LTC2606, LTC2607, LTC2609, LTC2616, - LTC2617, LTC2619, LTC2626, LTC2627, LTC2629 Digital to Analog Converter. + LTC2617, LTC2619, LTC2626, LTC2627, LTC2629, LTC2631, LTC2633, LTC2635 + Digital to Analog Converter. To compile this driver as a module, choose M here: the module will be called ad5064. diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c index 6803e4a137cd..3f9399c27869 100644 --- a/drivers/iio/dac/ad5064.c +++ b/drivers/iio/dac/ad5064.c @@ -2,8 +2,8 @@ * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1, AD5065, AD5625, AD5625R, * AD5627, AD5627R, AD5628, AD5629R, AD5645R, AD5647R, AD5648, AD5665, AD5665R, * AD5666, AD5667, AD5667R, AD5668, AD5669R, LTC2606, LTC2607, LTC2609, LTC2616, - * LTC2617, LTC2619, LTC2626, LTC2627, LTC2629 Digital to analog converters - * driver + * LTC2617, LTC2619, LTC2626, LTC2627, LTC2629, LTC2631, LTC2633, LTC2635 + * Digital to analog converters driver * * Copyright 2011 Analog Devices Inc. * @@ -168,6 +168,24 @@ enum ad5064_type { ID_LTC2626, ID_LTC2627, ID_LTC2629, + ID_LTC2631_L12, + ID_LTC2631_H12, + ID_LTC2631_L10, + ID_LTC2631_H10, + ID_LTC2631_L8, + ID_LTC2631_H8, + ID_LTC2633_L12, + ID_LTC2633_H12, + ID_LTC2633_L10, + ID_LTC2633_H10, + ID_LTC2633_L8, + ID_LTC2633_H8, + ID_LTC2635_L12, + ID_LTC2635_H12, + ID_LTC2635_L10, + ID_LTC2635_H10, + ID_LTC2635_L8, + ID_LTC2635_H8, }; static int ad5064_write(struct ad5064_state *st, unsigned int cmd, @@ -425,6 +443,19 @@ static DECLARE_AD5064_CHANNELS(ad5669_channels, 16, 0, ad5064_ext_info); static DECLARE_AD5064_CHANNELS(ltc2607_channels, 16, 0, ltc2617_ext_info); static DECLARE_AD5064_CHANNELS(ltc2617_channels, 14, 2, ltc2617_ext_info); static DECLARE_AD5064_CHANNELS(ltc2627_channels, 12, 4, ltc2617_ext_info); +#define ltc2631_12_channels ltc2627_channels +static DECLARE_AD5064_CHANNELS(ltc2631_10_channels, 10, 6, ltc2617_ext_info); +static DECLARE_AD5064_CHANNELS(ltc2631_8_channels, 8, 8, ltc2617_ext_info); + +#define LTC2631_INFO(vref, pchannels, nchannels) \ + { \ + .shared_vref = true, \ + .internal_vref = vref, \ + .channels = pchannels, \ + .num_channels = nchannels, \ + .regmap_type = AD5064_REGMAP_LTC, \ + } + static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { [ID_AD5024] = { @@ -724,6 +755,24 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { .num_channels = 4, .regmap_type = AD5064_REGMAP_LTC, }, + [ID_LTC2631_L12] = LTC2631_INFO(2500000, ltc2631_12_channels, 1), + [ID_LTC2631_H12] = LTC2631_INFO(4096000, ltc2631_12_channels, 1), + [ID_LTC2631_L10] = LTC2631_INFO(2500000, ltc2631_10_channels, 1), + [ID_LTC2631_H10] = LTC2631_INFO(4096000, ltc2631_10_channels, 1), + [ID_LTC2631_L8] = LTC2631_INFO(2500000, ltc2631_8_channels, 1), + [ID_LTC2631_H8] = LTC2631_INFO(4096000, ltc2631_8_channels, 1), + [ID_LTC2633_L12] = LTC2631_INFO(2500000, ltc2631_12_channels, 2), + [ID_LTC2633_H12] = LTC2631_INFO(4096000, ltc2631_12_channels, 2), + [ID_LTC2633_L10] = LTC2631_INFO(2500000, ltc2631_10_channels, 2), + [ID_LTC2633_H10] = LTC2631_INFO(4096000, ltc2631_10_channels, 2), + [ID_LTC2633_L8] = LTC2631_INFO(2500000, ltc2631_8_channels, 2), + [ID_LTC2633_H8] = LTC2631_INFO(4096000, ltc2631_8_channels, 2), + [ID_LTC2635_L12] = LTC2631_INFO(2500000, ltc2631_12_channels, 4), + [ID_LTC2635_H12] = LTC2631_INFO(4096000, ltc2631_12_channels, 4), + [ID_LTC2635_L10] = LTC2631_INFO(2500000, ltc2631_10_channels, 4), + [ID_LTC2635_H10] = LTC2631_INFO(4096000, ltc2631_10_channels, 4), + [ID_LTC2635_L8] = LTC2631_INFO(2500000, ltc2631_8_channels, 4), + [ID_LTC2635_H8] = LTC2631_INFO(4096000, ltc2631_8_channels, 4), }; static inline unsigned int ad5064_num_vref(struct ad5064_state *st) @@ -982,6 +1031,24 @@ static const struct i2c_device_id ad5064_i2c_ids[] = { {"ltc2626", ID_LTC2626}, {"ltc2627", ID_LTC2627}, {"ltc2629", ID_LTC2629}, + {"ltc2631-l12", ID_LTC2631_L12}, + {"ltc2631-h12", ID_LTC2631_H12}, + {"ltc2631-l10", ID_LTC2631_L10}, + {"ltc2631-h10", ID_LTC2631_H10}, + {"ltc2631-l8", ID_LTC2631_L8}, + {"ltc2631-h8", ID_LTC2631_H8}, + {"ltc2633-l12", ID_LTC2633_L12}, + {"ltc2633-h12", ID_LTC2633_H12}, + {"ltc2633-l10", ID_LTC2633_L10}, + {"ltc2633-h10", ID_LTC2633_H10}, + {"ltc2633-l8", ID_LTC2633_L8}, + {"ltc2633-h8", ID_LTC2633_H8}, + {"ltc2635-l12", ID_LTC2635_L12}, + {"ltc2635-h12", ID_LTC2635_H12}, + {"ltc2635-l10", ID_LTC2635_L10}, + {"ltc2635-h10", ID_LTC2635_H10}, + {"ltc2635-l8", ID_LTC2635_L8}, + {"ltc2635-h8", ID_LTC2635_H8}, {} }; MODULE_DEVICE_TABLE(i2c, ad5064_i2c_ids); diff --git a/drivers/iio/humidity/hts221.h b/drivers/iio/humidity/hts221.h index c7154665512e..94510266e0a5 100644 --- a/drivers/iio/humidity/hts221.h +++ b/drivers/iio/humidity/hts221.h @@ -57,12 +57,15 @@ struct hts221_hw { struct hts221_sensor sensors[HTS221_SENSOR_MAX]; + bool enabled; u8 odr; const struct hts221_transfer_function *tf; struct hts221_transfer_buffer tb; }; +extern const struct dev_pm_ops hts221_pm_ops; + int hts221_config_drdy(struct hts221_hw *hw, bool enable); int hts221_probe(struct iio_dev *iio_dev); int hts221_power_on(struct hts221_hw *hw); diff --git a/drivers/iio/humidity/hts221_core.c b/drivers/iio/humidity/hts221_core.c index 3f3ef4a1a474..a56da3999e00 100644 --- a/drivers/iio/humidity/hts221_core.c +++ b/drivers/iio/humidity/hts221_core.c @@ -13,6 +13,7 @@ #include <linux/device.h> #include <linux/iio/sysfs.h> #include <linux/delay.h> +#include <linux/pm.h> #include <asm/unaligned.h> #include "hts221.h" @@ -307,15 +308,30 @@ hts221_sysfs_temp_oversampling_avail(struct device *dev, int hts221_power_on(struct hts221_hw *hw) { - return hts221_update_odr(hw, hw->odr); + int err; + + err = hts221_update_odr(hw, hw->odr); + if (err < 0) + return err; + + hw->enabled = true; + + return 0; } int hts221_power_off(struct hts221_hw *hw) { - u8 data[] = {0x00, 0x00}; + __le16 data = 0; + int err; - return hw->tf->write(hw->dev, HTS221_REG_CNTRL1_ADDR, sizeof(data), - data); + err = hw->tf->write(hw->dev, HTS221_REG_CNTRL1_ADDR, sizeof(data), + (u8 *)&data); + if (err < 0) + return err; + + hw->enabled = false; + + return 0; } static int hts221_parse_temp_caldata(struct hts221_hw *hw) @@ -682,6 +698,36 @@ int hts221_probe(struct iio_dev *iio_dev) } EXPORT_SYMBOL(hts221_probe); +static int __maybe_unused hts221_suspend(struct device *dev) +{ + struct iio_dev *iio_dev = dev_get_drvdata(dev); + struct hts221_hw *hw = iio_priv(iio_dev); + __le16 data = 0; + int err; + + err = hw->tf->write(hw->dev, HTS221_REG_CNTRL1_ADDR, sizeof(data), + (u8 *)&data); + + return err < 0 ? err : 0; +} + +static int __maybe_unused hts221_resume(struct device *dev) +{ + struct iio_dev *iio_dev = dev_get_drvdata(dev); + struct hts221_hw *hw = iio_priv(iio_dev); + int err = 0; + + if (hw->enabled) + err = hts221_update_odr(hw, hw->odr); + + return err; +} + +const struct dev_pm_ops hts221_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(hts221_suspend, hts221_resume) +}; +EXPORT_SYMBOL(hts221_pm_ops); + MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>"); MODULE_DESCRIPTION("STMicroelectronics hts221 sensor driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/humidity/hts221_i2c.c b/drivers/iio/humidity/hts221_i2c.c index 8333c0296c0e..f38e4b7e0160 100644 --- a/drivers/iio/humidity/hts221_i2c.c +++ b/drivers/iio/humidity/hts221_i2c.c @@ -105,6 +105,7 @@ MODULE_DEVICE_TABLE(i2c, hts221_i2c_id_table); static struct i2c_driver hts221_driver = { .driver = { .name = "hts221_i2c", + .pm = &hts221_pm_ops, .of_match_table = of_match_ptr(hts221_i2c_of_match), .acpi_match_table = ACPI_PTR(hts221_acpi_match), }, diff --git a/drivers/iio/humidity/hts221_spi.c b/drivers/iio/humidity/hts221_spi.c index 70df5e7150c1..57cbc256771b 100644 --- a/drivers/iio/humidity/hts221_spi.c +++ b/drivers/iio/humidity/hts221_spi.c @@ -113,6 +113,7 @@ MODULE_DEVICE_TABLE(spi, hts221_spi_id_table); static struct spi_driver hts221_driver = { .driver = { .name = "hts221_spi", + .pm = &hts221_pm_ops, .of_match_table = of_match_ptr(hts221_spi_of_match), }, .probe = hts221_spi_probe, diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index 4839db7b9690..46352c7bff43 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -135,6 +135,8 @@ struct st_lsm6dsx_hw { #endif /* CONFIG_SPI_MASTER */ }; +extern const struct dev_pm_ops st_lsm6dsx_pm_ops; + int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, const char *name, const struct st_lsm6dsx_transfer_function *tf_ops); int st_lsm6dsx_sensor_enable(struct st_lsm6dsx_sensor *sensor); @@ -144,5 +146,8 @@ int st_lsm6dsx_write_with_mask(struct st_lsm6dsx_hw *hw, u8 addr, u8 mask, u8 val); int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor, u16 watermark); +int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw); +int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw, + enum st_lsm6dsx_fifo_mode fifo_mode); #endif /* ST_LSM6DSX_H */ diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c index c8e5cfd0ef0b..b19a62d8c884 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -130,8 +130,8 @@ static int st_lsm6dsx_update_decimators(struct st_lsm6dsx_hw *hw) return 0; } -static int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw, - enum st_lsm6dsx_fifo_mode fifo_mode) +int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw, + enum st_lsm6dsx_fifo_mode fifo_mode) { u8 data; int err; @@ -303,7 +303,7 @@ static int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) return read_len; } -static int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw) +int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw) { int err; diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index 462a27b70453..b485540da89e 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -36,6 +36,7 @@ #include <linux/delay.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> +#include <linux/pm.h> #include <linux/platform_data/st_sensors_pdata.h> @@ -731,6 +732,57 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, const char *name, } EXPORT_SYMBOL(st_lsm6dsx_probe); +static int __maybe_unused st_lsm6dsx_suspend(struct device *dev) +{ + struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev); + struct st_lsm6dsx_sensor *sensor; + int i, err = 0; + + for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { + sensor = iio_priv(hw->iio_devs[i]); + if (!(hw->enable_mask & BIT(sensor->id))) + continue; + + err = st_lsm6dsx_write_with_mask(hw, + st_lsm6dsx_odr_table[sensor->id].reg.addr, + st_lsm6dsx_odr_table[sensor->id].reg.mask, 0); + if (err < 0) + return err; + } + + if (hw->fifo_mode != ST_LSM6DSX_FIFO_BYPASS) + err = st_lsm6dsx_flush_fifo(hw); + + return err; +} + +static int __maybe_unused st_lsm6dsx_resume(struct device *dev) +{ + struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev); + struct st_lsm6dsx_sensor *sensor; + int i, err = 0; + + for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { + sensor = iio_priv(hw->iio_devs[i]); + if (!(hw->enable_mask & BIT(sensor->id))) + continue; + + err = st_lsm6dsx_set_odr(sensor, sensor->odr); + if (err < 0) + return err; + } + + if (hw->enable_mask) + err = st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_CONT); + + return err; +} + +const struct dev_pm_ops st_lsm6dsx_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(st_lsm6dsx_suspend, st_lsm6dsx_resume) +}; +EXPORT_SYMBOL(st_lsm6dsx_pm_ops); + MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>"); MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>"); MODULE_DESCRIPTION("STMicroelectronics st_lsm6dsx driver"); diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c index 09a51cfb9b5e..305fec712ab0 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c @@ -98,6 +98,7 @@ MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table); static struct i2c_driver st_lsm6dsx_driver = { .driver = { .name = "st_lsm6dsx_i2c", + .pm = &st_lsm6dsx_pm_ops, .of_match_table = of_match_ptr(st_lsm6dsx_i2c_of_match), }, .probe = st_lsm6dsx_i2c_probe, diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c index f765a5058488..95472f153ad2 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c @@ -115,6 +115,7 @@ MODULE_DEVICE_TABLE(spi, st_lsm6dsx_spi_id_table); static struct spi_driver st_lsm6dsx_driver = { .driver = { .name = "st_lsm6dsx_spi", + .pm = &st_lsm6dsx_pm_ops, .of_match_table = of_match_ptr(st_lsm6dsx_spi_of_match), }, .probe = st_lsm6dsx_spi_probe, diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 57c14da5708f..4a1de59d153a 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -1089,7 +1089,7 @@ static int iio_device_add_info_mask_type(struct iio_dev *indio_dev, { int i, ret, attrcount = 0; - for_each_set_bit(i, infomask, sizeof(infomask)*8) { + for_each_set_bit(i, infomask, sizeof(*infomask)*8) { if (i >= ARRAY_SIZE(iio_chan_info_postfix)) return -EINVAL; ret = __iio_add_chan_devattr(iio_chan_info_postfix[i], @@ -1118,7 +1118,7 @@ static int iio_device_add_info_mask_type_avail(struct iio_dev *indio_dev, int i, ret, attrcount = 0; char *avail_postfix; - for_each_set_bit(i, infomask, sizeof(infomask) * 8) { + for_each_set_bit(i, infomask, sizeof(*infomask) * 8) { avail_postfix = kasprintf(GFP_KERNEL, "%s_available", iio_chan_info_postfix[i]); diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 7a13535dc3e9..a3941bade6a7 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -750,11 +750,9 @@ int iio_read_avail_channel_raw(struct iio_channel *chan, err_unlock: mutex_unlock(&chan->indio_dev->info_exist_lock); - if (ret >= 0 && type != IIO_VAL_INT) { + if (ret >= 0 && type != IIO_VAL_INT) /* raw values are assumed to be IIO_VAL_INT */ ret = -EINVAL; - goto err_unlock; - } return ret; } diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 33e755d8d825..2356ed9285df 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -172,6 +172,16 @@ config SENSORS_ISL29018 in lux, proximity infrared sensing and normal infrared sensing. Data from sensor is accessible via sysfs. +config SENSORS_ISL29028 + tristate "Intersil ISL29028 Concurrent Light and Proximity Sensor" + depends on I2C + select REGMAP_I2C + help + Provides driver for the Intersil's ISL29028 device. + This driver supports the sysfs interface to get the ALS, IR intensity, + Proximity value via iio. The ISL29028 provides the concurrent sensing + of ambient light and proximity. + config ISL29125 tristate "Intersil ISL29125 digital color light sensor" depends on I2C diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index 681363c2b298..fa32fa459e2e 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -20,6 +20,7 @@ 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_SENSORS_ISL29018) += isl29018.o +obj-$(CONFIG_SENSORS_ISL29028) += isl29028.o obj-$(CONFIG_ISL29125) += isl29125.o obj-$(CONFIG_JSA1212) += jsa1212.o obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o diff --git a/drivers/iio/light/isl29018.c b/drivers/iio/light/isl29018.c index 917dd8b43e72..61f5924b472d 100644 --- a/drivers/iio/light/isl29018.c +++ b/drivers/iio/light/isl29018.c @@ -807,6 +807,7 @@ static SIMPLE_DEV_PM_OPS(isl29018_pm_ops, isl29018_suspend, isl29018_resume); #define ISL29018_PM_OPS NULL #endif +#ifdef CONFIG_ACPI static const struct acpi_device_id isl29018_acpi_match[] = { {"ISL29018", isl29018}, {"ISL29023", isl29023}, @@ -814,6 +815,7 @@ static const struct acpi_device_id isl29018_acpi_match[] = { {}, }; MODULE_DEVICE_TABLE(acpi, isl29018_acpi_match); +#endif static const struct i2c_device_id isl29018_id[] = { {"isl29018", isl29018}, diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/iio/light/isl29028.c index 5375e7a81205..3d09c1fc4dad 100644 --- a/drivers/staging/iio/light/isl29028.c +++ b/drivers/iio/light/isl29028.c @@ -16,6 +16,10 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Datasheets: + * - http://www.intersil.com/content/dam/Intersil/documents/isl2/isl29028.pdf + * - http://www.intersil.com/content/dam/Intersil/documents/isl2/isl29030.pdf */ #include <linux/module.h> @@ -64,8 +68,25 @@ #define ISL29028_POWER_OFF_DELAY_MS 2000 -static const unsigned int isl29028_prox_sleep_time[] = {800, 400, 200, 100, 75, - 50, 12, 0}; +struct isl29028_prox_data { + int sampling_int; + int sampling_fract; + int sleep_time; +}; + +static const struct isl29028_prox_data isl29028_prox_data[] = { + { 1, 250000, 800 }, + { 2, 500000, 400 }, + { 5, 0, 200 }, + { 10, 0, 100 }, + { 13, 300000, 75 }, + { 20, 0, 50 }, + { 80, 0, 13 }, /* + * Note: Data sheet lists 12.5 ms sleep time. + * Round up a half millisecond for msleep(). + */ + { 100, 0, 0 } +}; enum isl29028_als_ir_mode { ISL29028_MODE_NONE = 0, @@ -76,32 +97,37 @@ enum isl29028_als_ir_mode { struct isl29028_chip { struct mutex lock; struct regmap *regmap; - unsigned int prox_sampling; + int prox_sampling_int; + int prox_sampling_frac; bool enable_prox; int lux_scale; enum isl29028_als_ir_mode als_ir_mode; }; -static int isl29028_find_prox_sleep_time_index(int sampling) +static int isl29028_find_prox_sleep_index(int sampling_int, int sampling_fract) { - unsigned int period = DIV_ROUND_UP(1000, sampling); int i; - for (i = 0; i < ARRAY_SIZE(isl29028_prox_sleep_time); ++i) { - if (period >= isl29028_prox_sleep_time[i]) - break; + for (i = 0; i < ARRAY_SIZE(isl29028_prox_data); ++i) { + if (isl29028_prox_data[i].sampling_int == sampling_int && + isl29028_prox_data[i].sampling_fract == sampling_fract) + return i; } - return i; + return -EINVAL; } static int isl29028_set_proxim_sampling(struct isl29028_chip *chip, - unsigned int sampling) + int sampling_int, int sampling_fract) { struct device *dev = regmap_get_device(chip->regmap); int sleep_index, ret; - sleep_index = isl29028_find_prox_sleep_time_index(sampling); + sleep_index = isl29028_find_prox_sleep_index(sampling_int, + sampling_fract); + if (sleep_index < 0) + return sleep_index; + ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE, ISL29028_CONF_PROX_SLP_MASK, sleep_index << ISL29028_CONF_PROX_SLP_SH); @@ -112,16 +138,18 @@ static int isl29028_set_proxim_sampling(struct isl29028_chip *chip, return ret; } - chip->prox_sampling = sampling; + chip->prox_sampling_int = sampling_int; + chip->prox_sampling_frac = sampling_fract; return ret; } static int isl29028_enable_proximity(struct isl29028_chip *chip) { - int sleep_index, ret; + int prox_index, ret; - ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling); + ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling_int, + chip->prox_sampling_frac); if (ret < 0) return ret; @@ -132,8 +160,12 @@ static int isl29028_enable_proximity(struct isl29028_chip *chip) return ret; /* Wait for conversion to be complete for first sample */ - sleep_index = isl29028_find_prox_sleep_time_index(chip->prox_sampling); - msleep(isl29028_prox_sleep_time[sleep_index]); + prox_index = isl29028_find_prox_sleep_index(chip->prox_sampling_int, + chip->prox_sampling_frac); + if (prox_index < 0) + return prox_index; + + msleep(isl29028_prox_data[prox_index].sleep_time); return 0; } @@ -361,7 +393,7 @@ static int isl29028_write_raw(struct iio_dev *indio_dev, break; } - ret = isl29028_set_proxim_sampling(chip, val); + ret = isl29028_set_proxim_sampling(chip, val, val2); break; case IIO_LIGHT: if (mask != IIO_CHAN_INFO_SCALE) { @@ -439,7 +471,8 @@ static int isl29028_read_raw(struct iio_dev *indio_dev, if (chan->type != IIO_PROXIMITY) break; - *val = chip->prox_sampling; + *val = chip->prox_sampling_int; + *val2 = chip->prox_sampling_frac; ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_SCALE: @@ -472,7 +505,7 @@ static int isl29028_read_raw(struct iio_dev *indio_dev, } static IIO_CONST_ATTR(in_proximity_sampling_frequency_available, - "1 3 5 10 13 20 83 100"); + "1.25 2.5 5 10 13.3 20 80 100"); static IIO_CONST_ATTR(in_illuminance_scale_available, "125 2000"); #define ISL29028_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr) @@ -571,7 +604,8 @@ static int isl29028_probe(struct i2c_client *client, } chip->enable_prox = false; - chip->prox_sampling = 20; + chip->prox_sampling_int = 20; + chip->prox_sampling_frac = 0; chip->lux_scale = 2000; ret = regmap_write(chip->regmap, ISL29028_REG_TEST1_MODE, 0x0); @@ -664,6 +698,7 @@ static const struct dev_pm_ops isl29028_pm_ops = { static const struct i2c_device_id isl29028_id[] = { {"isl29028", 0}, + {"isl29030", 0}, {} }; MODULE_DEVICE_TABLE(i2c, isl29028_id); @@ -671,6 +706,7 @@ MODULE_DEVICE_TABLE(i2c, isl29028_id); static const struct of_device_id isl29028_of_match[] = { { .compatible = "isl,isl29028", }, /* for backward compat., don't use */ { .compatible = "isil,isl29028", }, + { .compatible = "isil,isl29030", }, { }, }; MODULE_DEVICE_TABLE(of, isl29028_of_match); diff --git a/drivers/iio/light/rpr0521.c b/drivers/iio/light/rpr0521.c index 7de0f397194b..9d0c2e859bb2 100644 --- a/drivers/iio/light/rpr0521.c +++ b/drivers/iio/light/rpr0521.c @@ -9,7 +9,7 @@ * * IIO driver for RPR-0521RS (7-bit I2C slave address 0x38). * - * TODO: illuminance channel, PM support, buffer + * TODO: illuminance channel, buffer */ #include <linux/module.h> @@ -30,6 +30,7 @@ #define RPR0521_REG_PXS_DATA 0x44 /* 16-bit, little endian */ #define RPR0521_REG_ALS_DATA0 0x46 /* 16-bit, little endian */ #define RPR0521_REG_ALS_DATA1 0x48 /* 16-bit, little endian */ +#define RPR0521_REG_PS_OFFSET_LSB 0x53 #define RPR0521_REG_ID 0x92 #define RPR0521_MODE_ALS_MASK BIT(7) @@ -77,9 +78,9 @@ static const struct rpr0521_gain rpr0521_pxs_gain[3] = { }; enum rpr0521_channel { + RPR0521_CHAN_PXS, RPR0521_CHAN_ALS_DATA0, RPR0521_CHAN_ALS_DATA1, - RPR0521_CHAN_PXS, }; struct rpr0521_reg_desc { @@ -88,6 +89,10 @@ struct rpr0521_reg_desc { }; static const struct rpr0521_reg_desc rpr0521_data_reg[] = { + [RPR0521_CHAN_PXS] = { + .address = RPR0521_REG_PXS_DATA, + .device_mask = RPR0521_MODE_PXS_MASK, + }, [RPR0521_CHAN_ALS_DATA0] = { .address = RPR0521_REG_ALS_DATA0, .device_mask = RPR0521_MODE_ALS_MASK, @@ -96,10 +101,6 @@ static const struct rpr0521_reg_desc rpr0521_data_reg[] = { .address = RPR0521_REG_ALS_DATA1, .device_mask = RPR0521_MODE_ALS_MASK, }, - [RPR0521_CHAN_PXS] = { - .address = RPR0521_REG_PXS_DATA, - .device_mask = RPR0521_MODE_PXS_MASK, - }, }; static const struct rpr0521_gain_info { @@ -109,6 +110,13 @@ static const struct rpr0521_gain_info { const struct rpr0521_gain *gain; int size; } rpr0521_gain[] = { + [RPR0521_CHAN_PXS] = { + .reg = RPR0521_REG_PXS_CTRL, + .mask = RPR0521_PXS_GAIN_MASK, + .shift = RPR0521_PXS_GAIN_SHIFT, + .gain = rpr0521_pxs_gain, + .size = ARRAY_SIZE(rpr0521_pxs_gain), + }, [RPR0521_CHAN_ALS_DATA0] = { .reg = RPR0521_REG_ALS_CTRL, .mask = RPR0521_ALS_DATA0_GAIN_MASK, @@ -123,13 +131,30 @@ static const struct rpr0521_gain_info { .gain = rpr0521_als_gain, .size = ARRAY_SIZE(rpr0521_als_gain), }, - [RPR0521_CHAN_PXS] = { - .reg = RPR0521_REG_PXS_CTRL, - .mask = RPR0521_PXS_GAIN_MASK, - .shift = RPR0521_PXS_GAIN_SHIFT, - .gain = rpr0521_pxs_gain, - .size = ARRAY_SIZE(rpr0521_pxs_gain), - }, +}; + +struct rpr0521_samp_freq { + int als_hz; + int als_uhz; + int pxs_hz; + int pxs_uhz; +}; + +static const struct rpr0521_samp_freq rpr0521_samp_freq_i[13] = { +/* {ALS, PXS}, W==currently writable option */ + {0, 0, 0, 0}, /* W0000, 0=standby */ + {0, 0, 100, 0}, /* 0001 */ + {0, 0, 25, 0}, /* 0010 */ + {0, 0, 10, 0}, /* 0011 */ + {0, 0, 2, 500000}, /* 0100 */ + {10, 0, 20, 0}, /* 0101 */ + {10, 0, 10, 0}, /* W0110 */ + {10, 0, 2, 500000}, /* 0111 */ + {2, 500000, 20, 0}, /* 1000, measurement 100ms, sleep 300ms */ + {2, 500000, 10, 0}, /* 1001, measurement 100ms, sleep 300ms */ + {2, 500000, 0, 0}, /* 1010, high sensitivity mode */ + {2, 500000, 2, 500000}, /* W1011, high sensitivity mode */ + {20, 0, 20, 0} /* 1100, ALS_data x 0.5, see specification P.18 */ }; struct rpr0521_data { @@ -142,9 +167,11 @@ struct rpr0521_data { bool als_dev_en; bool pxs_dev_en; - /* optimize runtime pm ops - enable device only if needed */ + /* optimize runtime pm ops - enable/disable device only if needed */ bool als_ps_need_en; bool pxs_ps_need_en; + bool als_need_dis; + bool pxs_need_dis; struct regmap *regmap; }; @@ -152,9 +179,16 @@ struct rpr0521_data { static IIO_CONST_ATTR(in_intensity_scale_available, RPR0521_ALS_SCALE_AVAIL); static IIO_CONST_ATTR(in_proximity_scale_available, RPR0521_PXS_SCALE_AVAIL); +/* + * Start with easy freq first, whole table of freq combinations is more + * complicated. + */ +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("2.5 10"); + static struct attribute *rpr0521_attributes[] = { &iio_const_attr_in_intensity_scale_available.dev_attr.attr, &iio_const_attr_in_proximity_scale_available.dev_attr.attr, + &iio_const_attr_sampling_frequency_available.dev_attr.attr, NULL, }; @@ -164,12 +198,21 @@ static const struct attribute_group rpr0521_attribute_group = { static const struct iio_chan_spec rpr0521_channels[] = { { + .type = IIO_PROXIMITY, + .address = RPR0521_CHAN_PXS, + .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), + }, + { .type = IIO_INTENSITY, .modified = 1, .address = RPR0521_CHAN_ALS_DATA0, .channel2 = IIO_MOD_LIGHT_BOTH, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), }, { .type = IIO_INTENSITY, @@ -178,13 +221,8 @@ static const struct iio_chan_spec rpr0521_channels[] = { .channel2 = IIO_MOD_LIGHT_IR, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), }, - { - .type = IIO_PROXIMITY, - .address = RPR0521_CHAN_PXS, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_SCALE), - } }; static int rpr0521_als_enable(struct rpr0521_data *data, u8 status) @@ -197,7 +235,10 @@ static int rpr0521_als_enable(struct rpr0521_data *data, u8 status) if (ret < 0) return ret; - data->als_dev_en = true; + if (status & RPR0521_MODE_ALS_MASK) + data->als_dev_en = true; + else + data->als_dev_en = false; return 0; } @@ -212,7 +253,10 @@ static int rpr0521_pxs_enable(struct rpr0521_data *data, u8 status) if (ret < 0) return ret; - data->pxs_dev_en = true; + if (status & RPR0521_MODE_PXS_MASK) + data->pxs_dev_en = true; + else + data->pxs_dev_en = false; return 0; } @@ -224,40 +268,32 @@ static int rpr0521_pxs_enable(struct rpr0521_data *data, u8 status) * @on: state to be set for devices in @device_mask * @device_mask: bitmask specifying for which device we need to update @on state * - * We rely on rpr0521_runtime_resume to enable our @device_mask devices, but - * if (for example) PXS was enabled (pxs_dev_en = true) by a previous call to - * rpr0521_runtime_resume and we want to enable ALS we MUST set ALS enable - * bit of RPR0521_REG_MODE_CTRL here because rpr0521_runtime_resume will not - * be called twice. + * Calls for this function must be balanced so that each ON should have matching + * OFF. Otherwise pm usage_count gets out of sync. */ static int rpr0521_set_power_state(struct rpr0521_data *data, bool on, u8 device_mask) { #ifdef CONFIG_PM int ret; - u8 update_mask = 0; if (device_mask & RPR0521_MODE_ALS_MASK) { - if (on && !data->als_ps_need_en && data->pxs_dev_en) - update_mask |= RPR0521_MODE_ALS_MASK; - else - data->als_ps_need_en = on; + data->als_ps_need_en = on; + data->als_need_dis = !on; } if (device_mask & RPR0521_MODE_PXS_MASK) { - if (on && !data->pxs_ps_need_en && data->als_dev_en) - update_mask |= RPR0521_MODE_PXS_MASK; - else - data->pxs_ps_need_en = on; - } - - if (update_mask) { - ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL, - update_mask, update_mask); - if (ret < 0) - return ret; + data->pxs_ps_need_en = on; + data->pxs_need_dis = !on; } + /* + * On: _resume() is called only when we are suspended + * Off: _suspend() is called after delay if _resume() is not + * called before that. + * Note: If either measurement is re-enabled before _suspend(), + * both stay enabled until _suspend(). + */ if (on) { ret = pm_runtime_get_sync(&data->client->dev); } else { @@ -273,6 +309,23 @@ static int rpr0521_set_power_state(struct rpr0521_data *data, bool on, return ret; } + + if (on) { + /* If _resume() was not called, enable measurement now. */ + if (data->als_ps_need_en) { + ret = rpr0521_als_enable(data, RPR0521_MODE_ALS_ENABLE); + if (ret) + return ret; + data->als_ps_need_en = false; + } + + if (data->pxs_ps_need_en) { + ret = rpr0521_pxs_enable(data, RPR0521_MODE_PXS_ENABLE); + if (ret) + return ret; + data->pxs_ps_need_en = false; + } + } #endif return 0; } @@ -314,6 +367,106 @@ static int rpr0521_set_gain(struct rpr0521_data *data, int chan, idx << rpr0521_gain[chan].shift); } +static int rpr0521_read_samp_freq(struct rpr0521_data *data, + enum iio_chan_type chan_type, + int *val, int *val2) +{ + int reg, ret; + + ret = regmap_read(data->regmap, RPR0521_REG_MODE_CTRL, ®); + if (ret < 0) + return ret; + + reg &= RPR0521_MODE_MEAS_TIME_MASK; + if (reg >= ARRAY_SIZE(rpr0521_samp_freq_i)) + return -EINVAL; + + switch (chan_type) { + case IIO_INTENSITY: + *val = rpr0521_samp_freq_i[reg].als_hz; + *val2 = rpr0521_samp_freq_i[reg].als_uhz; + return 0; + + case IIO_PROXIMITY: + *val = rpr0521_samp_freq_i[reg].pxs_hz; + *val2 = rpr0521_samp_freq_i[reg].pxs_uhz; + return 0; + + default: + return -EINVAL; + } +} + +static int rpr0521_write_samp_freq_common(struct rpr0521_data *data, + enum iio_chan_type chan_type, + int val, int val2) +{ + int i; + + /* + * Ignore channel + * both pxs and als are setup only to same freq because of simplicity + */ + switch (val) { + case 0: + i = 0; + break; + + case 2: + if (val2 != 500000) + return -EINVAL; + + i = 11; + break; + + case 10: + i = 6; + break; + + default: + return -EINVAL; + } + + return regmap_update_bits(data->regmap, + RPR0521_REG_MODE_CTRL, + RPR0521_MODE_MEAS_TIME_MASK, + i); +} + +static int rpr0521_read_ps_offset(struct rpr0521_data *data, int *offset) +{ + int ret; + __le16 buffer; + + ret = regmap_bulk_read(data->regmap, + RPR0521_REG_PS_OFFSET_LSB, &buffer, sizeof(buffer)); + + if (ret < 0) { + dev_err(&data->client->dev, "Failed to read PS OFFSET register\n"); + return ret; + } + *offset = le16_to_cpu(buffer); + + return ret; +} + +static int rpr0521_write_ps_offset(struct rpr0521_data *data, int offset) +{ + int ret; + __le16 buffer; + + buffer = cpu_to_le16(offset & 0x3ff); + ret = regmap_raw_write(data->regmap, + RPR0521_REG_PS_OFFSET_LSB, &buffer, sizeof(buffer)); + + if (ret < 0) { + dev_err(&data->client->dev, "Failed to write PS OFFSET register\n"); + return ret; + } + + return ret; +} + static int rpr0521_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -339,7 +492,7 @@ static int rpr0521_read_raw(struct iio_dev *indio_dev, ret = regmap_bulk_read(data->regmap, rpr0521_data_reg[chan->address].address, - &raw_data, 2); + &raw_data, sizeof(raw_data)); if (ret < 0) { rpr0521_set_power_state(data, false, device_mask); mutex_unlock(&data->lock); @@ -354,6 +507,7 @@ static int rpr0521_read_raw(struct iio_dev *indio_dev, *val = le16_to_cpu(raw_data); return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: mutex_lock(&data->lock); ret = rpr0521_get_gain(data, chan->address, val, val2); @@ -362,6 +516,25 @@ static int rpr0521_read_raw(struct iio_dev *indio_dev, return ret; return IIO_VAL_INT_PLUS_MICRO; + + case IIO_CHAN_INFO_SAMP_FREQ: + mutex_lock(&data->lock); + ret = rpr0521_read_samp_freq(data, chan->type, val, val2); + mutex_unlock(&data->lock); + if (ret < 0) + return ret; + + return IIO_VAL_INT_PLUS_MICRO; + + case IIO_CHAN_INFO_OFFSET: + mutex_lock(&data->lock); + ret = rpr0521_read_ps_offset(data, val); + mutex_unlock(&data->lock); + if (ret < 0) + return ret; + + return IIO_VAL_INT; + default: return -EINVAL; } @@ -381,6 +554,22 @@ static int rpr0521_write_raw(struct iio_dev *indio_dev, mutex_unlock(&data->lock); return ret; + + case IIO_CHAN_INFO_SAMP_FREQ: + mutex_lock(&data->lock); + ret = rpr0521_write_samp_freq_common(data, chan->type, + val, val2); + mutex_unlock(&data->lock); + + return ret; + + case IIO_CHAN_INFO_OFFSET: + mutex_lock(&data->lock); + ret = rpr0521_write_ps_offset(data, val); + mutex_unlock(&data->lock); + + return ret; + default: return -EINVAL; } @@ -419,12 +608,14 @@ static int rpr0521_init(struct rpr0521_data *data) return ret; } +#ifndef CONFIG_PM ret = rpr0521_als_enable(data, RPR0521_MODE_ALS_ENABLE); if (ret < 0) return ret; ret = rpr0521_pxs_enable(data, RPR0521_MODE_PXS_ENABLE); if (ret < 0) return ret; +#endif return 0; } @@ -510,13 +701,26 @@ static int rpr0521_probe(struct i2c_client *client, ret = pm_runtime_set_active(&client->dev); if (ret < 0) - return ret; + goto err_poweroff; pm_runtime_enable(&client->dev); pm_runtime_set_autosuspend_delay(&client->dev, RPR0521_SLEEP_DELAY_MS); pm_runtime_use_autosuspend(&client->dev); - return iio_device_register(indio_dev); + ret = iio_device_register(indio_dev); + if (ret) + goto err_pm_disable; + + return 0; + +err_pm_disable: + pm_runtime_disable(&client->dev); + pm_runtime_set_suspended(&client->dev); + pm_runtime_put_noidle(&client->dev); +err_poweroff: + rpr0521_poweroff(data); + + return ret; } static int rpr0521_remove(struct i2c_client *client) @@ -541,9 +745,16 @@ static int rpr0521_runtime_suspend(struct device *dev) struct rpr0521_data *data = iio_priv(indio_dev); int ret; - /* disable channels and sets {als,pxs}_dev_en to false */ mutex_lock(&data->lock); + /* If measurements are enabled, enable them on resume */ + if (!data->als_need_dis) + data->als_ps_need_en = data->als_dev_en; + if (!data->pxs_need_dis) + data->pxs_ps_need_en = data->pxs_dev_en; + + /* disable channels and sets {als,pxs}_dev_en to false */ ret = rpr0521_poweroff(data); + regcache_mark_dirty(data->regmap); mutex_unlock(&data->lock); return ret; @@ -555,6 +766,7 @@ static int rpr0521_runtime_resume(struct device *dev) struct rpr0521_data *data = iio_priv(indio_dev); int ret; + regcache_sync(data->regmap); if (data->als_ps_need_en) { ret = rpr0521_als_enable(data, RPR0521_MODE_ALS_ENABLE); if (ret < 0) @@ -568,6 +780,7 @@ static int rpr0521_runtime_resume(struct device *dev) return ret; data->pxs_ps_need_en = false; } + msleep(100); //wait for first measurement result return 0; } diff --git a/drivers/iio/light/tsl2583.c b/drivers/iio/light/tsl2583.c index a78b6025c465..1679181d2bdd 100644 --- a/drivers/iio/light/tsl2583.c +++ b/drivers/iio/light/tsl2583.c @@ -3,7 +3,7 @@ * within the TAOS tsl258x family of devices (tsl2580, tsl2581, tsl2583). * * Copyright (c) 2011, TAOS Corporation. - * Copyright (c) 2016 Brian Masney <masneyb@onstation.org> + * Copyright (c) 2016-2017 Brian Masney <masneyb@onstation.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,6 +27,7 @@ #include <linux/module.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> +#include <linux/pm_runtime.h> /* Device Registers and Masks */ #define TSL2583_CNTRL 0x00 @@ -64,6 +65,8 @@ #define TSL2583_CHIP_ID 0x90 #define TSL2583_CHIP_ID_MASK 0xf0 +#define TSL2583_POWER_OFF_DELAY_MS 2000 + /* Per-device data */ struct tsl2583_als_info { u16 als_ch0; @@ -108,7 +111,6 @@ struct tsl2583_chip { struct tsl2583_settings als_settings; int als_time_scale; int als_saturation; - bool suspended; }; struct gainadj { @@ -460,8 +462,6 @@ static int tsl2583_chip_init_and_power_on(struct iio_dev *indio_dev) if (ret < 0) return ret; - chip->suspended = false; - return ret; } @@ -513,11 +513,6 @@ static ssize_t in_illuminance_calibrate_store(struct device *dev, mutex_lock(&chip->als_mutex); - if (chip->suspended) { - ret = -EBUSY; - goto done; - } - ret = tsl2583_als_calibrate(indio_dev); if (ret < 0) goto done; @@ -645,20 +640,36 @@ static const struct iio_chan_spec tsl2583_channels[] = { }, }; +static int tsl2583_set_pm_runtime_busy(struct tsl2583_chip *chip, bool on) +{ + int ret; + + if (on) { + ret = pm_runtime_get_sync(&chip->client->dev); + if (ret < 0) + pm_runtime_put_noidle(&chip->client->dev); + } else { + pm_runtime_mark_last_busy(&chip->client->dev); + ret = pm_runtime_put_autosuspend(&chip->client->dev); + } + + return ret; +} + static int tsl2583_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { struct tsl2583_chip *chip = iio_priv(indio_dev); - int ret = -EINVAL; + int ret, pm_ret; - mutex_lock(&chip->als_mutex); + ret = tsl2583_set_pm_runtime_busy(chip, true); + if (ret < 0) + return ret; - if (chip->suspended) { - ret = -EBUSY; - goto read_done; - } + mutex_lock(&chip->als_mutex); + ret = -EINVAL; switch (mask) { case IIO_CHAN_INFO_RAW: if (chan->type == IIO_LIGHT) { @@ -719,6 +730,18 @@ static int tsl2583_read_raw(struct iio_dev *indio_dev, read_done: mutex_unlock(&chip->als_mutex); + if (ret < 0) + return ret; + + /* + * Preserve the ret variable if the call to + * tsl2583_set_pm_runtime_busy() is successful so the reading + * (if applicable) is returned to user space. + */ + pm_ret = tsl2583_set_pm_runtime_busy(chip, false); + if (pm_ret < 0) + return pm_ret; + return ret; } @@ -727,15 +750,15 @@ static int tsl2583_write_raw(struct iio_dev *indio_dev, int val, int val2, long mask) { struct tsl2583_chip *chip = iio_priv(indio_dev); - int ret = -EINVAL; + int ret; - mutex_lock(&chip->als_mutex); + ret = tsl2583_set_pm_runtime_busy(chip, true); + if (ret < 0) + return ret; - if (chip->suspended) { - ret = -EBUSY; - goto write_done; - } + mutex_lock(&chip->als_mutex); + ret = -EINVAL; switch (mask) { case IIO_CHAN_INFO_CALIBBIAS: if (chan->type == IIO_LIGHT) { @@ -767,9 +790,15 @@ static int tsl2583_write_raw(struct iio_dev *indio_dev, break; } -write_done: mutex_unlock(&chip->als_mutex); + if (ret < 0) + return ret; + + ret = tsl2583_set_pm_runtime_busy(chip, false); + if (ret < 0) + return ret; + return ret; } @@ -803,7 +832,6 @@ static int tsl2583_probe(struct i2c_client *clientp, i2c_set_clientdata(clientp, indio_dev); mutex_init(&chip->als_mutex); - chip->suspended = true; ret = i2c_smbus_read_byte_data(clientp, TSL2583_CMD_REG | TSL2583_CHIPID); @@ -826,6 +854,11 @@ static int tsl2583_probe(struct i2c_client *clientp, indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->name = chip->client->name; + pm_runtime_enable(&clientp->dev); + pm_runtime_set_autosuspend_delay(&clientp->dev, + TSL2583_POWER_OFF_DELAY_MS); + pm_runtime_use_autosuspend(&clientp->dev); + ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev); if (ret) { dev_err(&clientp->dev, "%s: iio registration failed\n", @@ -836,16 +869,25 @@ static int tsl2583_probe(struct i2c_client *clientp, /* Load up the V2 defaults (these are hard coded defaults for now) */ tsl2583_defaults(chip); - /* Make sure the chip is on */ - ret = tsl2583_chip_init_and_power_on(indio_dev); - if (ret < 0) - return ret; - dev_info(&clientp->dev, "Light sensor found.\n"); return 0; } +static int tsl2583_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct tsl2583_chip *chip = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + pm_runtime_disable(&client->dev); + pm_runtime_set_suspended(&client->dev); + pm_runtime_put_noidle(&client->dev); + + return tsl2583_set_power_state(chip, TSL2583_CNTL_PWR_OFF); +} + static int __maybe_unused tsl2583_suspend(struct device *dev) { struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); @@ -855,7 +897,6 @@ static int __maybe_unused tsl2583_suspend(struct device *dev) mutex_lock(&chip->als_mutex); ret = tsl2583_set_power_state(chip, TSL2583_CNTL_PWR_OFF); - chip->suspended = true; mutex_unlock(&chip->als_mutex); @@ -877,7 +918,11 @@ static int __maybe_unused tsl2583_resume(struct device *dev) return ret; } -static SIMPLE_DEV_PM_OPS(tsl2583_pm_ops, tsl2583_suspend, tsl2583_resume); +static const struct dev_pm_ops tsl2583_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(tsl2583_suspend, tsl2583_resume, NULL) +}; static struct i2c_device_id tsl2583_idtable[] = { { "tsl2580", 0 }, @@ -904,6 +949,7 @@ static struct i2c_driver tsl2583_driver = { }, .id_table = tsl2583_idtable, .probe = tsl2583_probe, + .remove = tsl2583_remove, }; module_i2c_driver(tsl2583_driver); diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c index a97e802ca523..e9fa86c87db5 100644 --- a/drivers/iio/orientation/hid-sensor-rotation.c +++ b/drivers/iio/orientation/hid-sensor-rotation.c @@ -31,6 +31,10 @@ struct dev_rot_state { struct hid_sensor_common common_attributes; struct hid_sensor_hub_attribute_info quaternion; u32 sampled_vals[4]; + int scale_pre_decml; + int scale_post_decml; + int scale_precision; + int value_offset; }; /* Channel definitions */ @@ -41,6 +45,8 @@ static const struct iio_chan_spec dev_rot_channels[] = { .channel2 = IIO_MOD_QUATERNION, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | + BIT(IIO_CHAN_INFO_OFFSET) | + BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_HYSTERESIS) } }; @@ -80,6 +86,15 @@ static int dev_rot_read_raw(struct iio_dev *indio_dev, } else ret_type = -EINVAL; break; + case IIO_CHAN_INFO_SCALE: + vals[0] = rot_state->scale_pre_decml; + vals[1] = rot_state->scale_post_decml; + return rot_state->scale_precision; + + case IIO_CHAN_INFO_OFFSET: + *vals = rot_state->value_offset; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SAMP_FREQ: ret_type = hid_sensor_read_samp_freq_value( &rot_state->common_attributes, &vals[0], &vals[1]); @@ -199,6 +214,11 @@ static int dev_rot_parse_report(struct platform_device *pdev, dev_dbg(&pdev->dev, "dev_rot: attrib size %d\n", st->quaternion.size); + st->scale_precision = hid_sensor_format_scale( + hsdev->usage, + &st->quaternion, + &st->scale_pre_decml, &st->scale_post_decml); + /* Set Sensitivity field ids, when there is no individual modifier */ if (st->common_attributes.sensitivity.index < 0) { sensor_hub_input_get_attribute_info(hsdev, @@ -218,7 +238,7 @@ static int dev_rot_parse_report(struct platform_device *pdev, static int hid_dev_rot_probe(struct platform_device *pdev) { int ret; - static char *name = "dev_rotation"; + static char *name; struct iio_dev *indio_dev; struct dev_rot_state *rot_state; struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; @@ -234,8 +254,21 @@ static int hid_dev_rot_probe(struct platform_device *pdev) rot_state->common_attributes.hsdev = hsdev; rot_state->common_attributes.pdev = pdev; - ret = hid_sensor_parse_common_attributes(hsdev, - HID_USAGE_SENSOR_DEVICE_ORIENTATION, + switch (hsdev->usage) { + case HID_USAGE_SENSOR_DEVICE_ORIENTATION: + name = "dev_rotation"; + break; + case HID_USAGE_SENSOR_RELATIVE_ORIENTATION: + name = "relative_orientation"; + break; + case HID_USAGE_SENSOR_GEOMAGNETIC_ORIENTATION: + name = "geomagnetic_orientation"; + break; + default: + return -EINVAL; + } + + ret = hid_sensor_parse_common_attributes(hsdev, hsdev->usage, &rot_state->common_attributes); if (ret) { dev_err(&pdev->dev, "failed to setup common attributes\n"); @@ -252,8 +285,7 @@ static int hid_dev_rot_probe(struct platform_device *pdev) ret = dev_rot_parse_report(pdev, hsdev, (struct iio_chan_spec *)indio_dev->channels, - HID_USAGE_SENSOR_DEVICE_ORIENTATION, - rot_state); + hsdev->usage, rot_state); if (ret) { dev_err(&pdev->dev, "failed to setup attributes\n"); return ret; @@ -288,8 +320,7 @@ static int hid_dev_rot_probe(struct platform_device *pdev) rot_state->callbacks.send_event = dev_rot_proc_event; rot_state->callbacks.capture_sample = dev_rot_capture_sample; rot_state->callbacks.pdev = pdev; - ret = sensor_hub_register_callback(hsdev, - HID_USAGE_SENSOR_DEVICE_ORIENTATION, + ret = sensor_hub_register_callback(hsdev, hsdev->usage, &rot_state->callbacks); if (ret) { dev_err(&pdev->dev, "callback reg failed\n"); @@ -314,7 +345,7 @@ static int hid_dev_rot_remove(struct platform_device *pdev) struct iio_dev *indio_dev = platform_get_drvdata(pdev); struct dev_rot_state *rot_state = iio_priv(indio_dev); - sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_DEVICE_ORIENTATION); + sensor_hub_remove_callback(hsdev, hsdev->usage); iio_device_unregister(indio_dev); hid_sensor_remove_trigger(&rot_state->common_attributes); iio_triggered_buffer_cleanup(indio_dev); @@ -327,6 +358,14 @@ static const struct platform_device_id hid_dev_rot_ids[] = { /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ .name = "HID-SENSOR-20008a", }, + { + /* Relative orientation(AG) sensor */ + .name = "HID-SENSOR-20008e", + }, + { + /* Geomagnetic orientation(AM) sensor */ + .name = "HID-SENSOR-2000c1", + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(platform, hid_dev_rot_ids); diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index 5d16b252ab6b..eaa7cfcb4c2a 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -23,7 +23,7 @@ config BMP280 select BMP280_SPI if (SPI_MASTER) help Say yes here to build support for Bosch Sensortec BMP180 and BMP280 - pressure and temperature sensors. Also supports the BE280 with + pressure and temperature sensors. Also supports the BME280 with an additional humidity sensor channel. To compile this driver as a module, choose M here: the core module diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index fd0edca0e656..aa61ec15c139 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c @@ -568,6 +568,8 @@ static const struct iio_trigger_ops st_press_trigger_ops = { int st_press_common_probe(struct iio_dev *indio_dev) { struct st_sensor_data *press_data = iio_priv(indio_dev); + struct st_sensors_platform_data *pdata = + (struct st_sensors_platform_data *)press_data->dev->platform_data; int irq = press_data->get_irq_data_ready(indio_dev); int err; @@ -603,10 +605,8 @@ int st_press_common_probe(struct iio_dev *indio_dev) press_data->odr = press_data->sensor_settings->odr.odr_avl[0].hz; /* Some devices don't support a data ready pin. */ - if (!press_data->dev->platform_data && - press_data->sensor_settings->drdy_irq.addr) - press_data->dev->platform_data = - (struct st_sensors_platform_data *)&default_press_pdata; + if (!pdata && press_data->sensor_settings->drdy_irq.addr) + pdata = (struct st_sensors_platform_data *)&default_press_pdata; err = st_sensors_init_sensor(indio_dev, press_data->dev->platform_data); if (err < 0) diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c index e58a0ad07477..c92a95f9f52c 100644 --- a/drivers/iio/pressure/zpa2326.c +++ b/drivers/iio/pressure/zpa2326.c @@ -867,12 +867,13 @@ static int zpa2326_wait_oneshot_completion(const struct iio_dev *indio_dev, { int ret; unsigned int val; + long timeout; zpa2326_dbg(indio_dev, "waiting for one shot completion interrupt"); - ret = wait_for_completion_interruptible_timeout( + timeout = wait_for_completion_interruptible_timeout( &private->data_ready, ZPA2326_CONVERSION_JIFFIES); - if (ret > 0) + if (timeout > 0) /* * Interrupt handler completed before timeout: return operation * status. @@ -882,13 +883,16 @@ static int zpa2326_wait_oneshot_completion(const struct iio_dev *indio_dev, /* Clear all interrupts just to be sure. */ regmap_read(private->regmap, ZPA2326_INT_SOURCE_REG, &val); - if (!ret) + if (!timeout) { /* Timed out. */ + zpa2326_warn(indio_dev, "no one shot interrupt occurred (%ld)", + timeout); ret = -ETIME; - - if (ret != -ERESTARTSYS) - zpa2326_warn(indio_dev, "no one shot interrupt occurred (%d)", - ret); + } else if (timeout < 0) { + zpa2326_warn(indio_dev, + "wait for one shot interrupt cancelled"); + ret = -ERESTARTSYS; + } return ret; } diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c index ddf9bee89f77..aa0d0be1a608 100644 --- a/drivers/iio/proximity/as3935.c +++ b/drivers/iio/proximity/as3935.c @@ -176,13 +176,13 @@ static int as3935_read_raw(struct iio_dev *indio_dev, if (ret) return ret; - if (m == IIO_CHAN_INFO_RAW) - return IIO_VAL_INT; - /* storm out of range */ if (*val == AS3935_DATA_MASK) return -EINVAL; + if (m == IIO_CHAN_INFO_RAW) + return IIO_VAL_INT; + if (m == IIO_CHAN_INFO_PROCESSED) *val *= 1000; break; diff --git a/drivers/iio/temperature/maxim_thermocouple.c b/drivers/iio/temperature/maxim_thermocouple.c index 557214202eff..d70e2e53d6a7 100644 --- a/drivers/iio/temperature/maxim_thermocouple.c +++ b/drivers/iio/temperature/maxim_thermocouple.c @@ -267,6 +267,7 @@ static int maxim_thermocouple_remove(struct spi_device *spi) static const struct spi_device_id maxim_thermocouple_id[] = { {"max6675", MAX6675}, {"max31855", MAX31855}, + {"max31856", MAX31855}, {}, }; MODULE_DEVICE_TABLE(spi, maxim_thermocouple_id); diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c index 25248d644e7c..0797f2fe584f 100644 --- a/drivers/iio/trigger/stm32-timer-trigger.c +++ b/drivers/iio/trigger/stm32-timer-trigger.c @@ -14,19 +14,19 @@ #include <linux/module.h> #include <linux/platform_device.h> -#define MAX_TRIGGERS 6 +#define MAX_TRIGGERS 7 #define MAX_VALIDS 5 /* List the triggers created by each timer */ static const void *triggers_table[][MAX_TRIGGERS] = { - { TIM1_TRGO, TIM1_CH1, TIM1_CH2, TIM1_CH3, TIM1_CH4,}, + { TIM1_TRGO, TIM1_TRGO2, TIM1_CH1, TIM1_CH2, TIM1_CH3, TIM1_CH4,}, { TIM2_TRGO, TIM2_CH1, TIM2_CH2, TIM2_CH3, TIM2_CH4,}, { TIM3_TRGO, TIM3_CH1, TIM3_CH2, TIM3_CH3, TIM3_CH4,}, { TIM4_TRGO, TIM4_CH1, TIM4_CH2, TIM4_CH3, TIM4_CH4,}, { TIM5_TRGO, TIM5_CH1, TIM5_CH2, TIM5_CH3, TIM5_CH4,}, { TIM6_TRGO,}, { TIM7_TRGO,}, - { TIM8_TRGO, TIM8_CH1, TIM8_CH2, TIM8_CH3, TIM8_CH4,}, + { TIM8_TRGO, TIM8_TRGO2, TIM8_CH1, TIM8_CH2, TIM8_CH3, TIM8_CH4,}, { TIM9_TRGO, TIM9_CH1, TIM9_CH2,}, { }, /* timer 10 */ { }, /* timer 11 */ @@ -56,9 +56,16 @@ struct stm32_timer_trigger { u32 max_arr; const void *triggers; const void *valids; + bool has_trgo2; }; +static bool stm32_timer_is_trgo2_name(const char *name) +{ + return !!strstr(name, "trgo2"); +} + static int stm32_timer_start(struct stm32_timer_trigger *priv, + struct iio_trigger *trig, unsigned int frequency) { unsigned long long prd, div; @@ -102,7 +109,12 @@ static int stm32_timer_start(struct stm32_timer_trigger *priv, regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, TIM_CR1_ARPE); /* Force master mode to update mode */ - regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS, 0x20); + if (stm32_timer_is_trgo2_name(trig->name)) + regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, + 0x2 << TIM_CR2_MMS2_SHIFT); + else + regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS, + 0x2 << TIM_CR2_MMS_SHIFT); /* Make sure that registers are updated */ regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG); @@ -150,7 +162,7 @@ static ssize_t stm32_tt_store_frequency(struct device *dev, if (freq == 0) { stm32_timer_stop(priv); } else { - ret = stm32_timer_start(priv, freq); + ret = stm32_timer_start(priv, trig, freq); if (ret) return ret; } @@ -183,6 +195,9 @@ static IIO_DEV_ATTR_SAMP_FREQ(0660, stm32_tt_read_frequency, stm32_tt_store_frequency); +#define MASTER_MODE_MAX 7 +#define MASTER_MODE2_MAX 15 + static char *master_mode_table[] = { "reset", "enable", @@ -191,7 +206,16 @@ static char *master_mode_table[] = { "OC1REF", "OC2REF", "OC3REF", - "OC4REF" + "OC4REF", + /* Master mode selection 2 only */ + "OC5REF", + "OC6REF", + "compare_pulse_OC4REF", + "compare_pulse_OC6REF", + "compare_pulse_OC4REF_r_or_OC6REF_r", + "compare_pulse_OC4REF_r_or_OC6REF_f", + "compare_pulse_OC5REF_r_or_OC6REF_r", + "compare_pulse_OC5REF_r_or_OC6REF_f", }; static ssize_t stm32_tt_show_master_mode(struct device *dev, @@ -199,10 +223,15 @@ static ssize_t stm32_tt_show_master_mode(struct device *dev, char *buf) { struct stm32_timer_trigger *priv = dev_get_drvdata(dev); + struct iio_trigger *trig = to_iio_trigger(dev); u32 cr2; regmap_read(priv->regmap, TIM_CR2, &cr2); - cr2 = (cr2 & TIM_CR2_MMS) >> TIM_CR2_MMS_SHIFT; + + if (stm32_timer_is_trgo2_name(trig->name)) + cr2 = (cr2 & TIM_CR2_MMS2) >> TIM_CR2_MMS2_SHIFT; + else + cr2 = (cr2 & TIM_CR2_MMS) >> TIM_CR2_MMS_SHIFT; return snprintf(buf, PAGE_SIZE, "%s\n", master_mode_table[cr2]); } @@ -212,13 +241,25 @@ static ssize_t stm32_tt_store_master_mode(struct device *dev, const char *buf, size_t len) { struct stm32_timer_trigger *priv = dev_get_drvdata(dev); + struct iio_trigger *trig = to_iio_trigger(dev); + u32 mask, shift, master_mode_max; int i; - for (i = 0; i < ARRAY_SIZE(master_mode_table); i++) { + if (stm32_timer_is_trgo2_name(trig->name)) { + mask = TIM_CR2_MMS2; + shift = TIM_CR2_MMS2_SHIFT; + master_mode_max = MASTER_MODE2_MAX; + } else { + mask = TIM_CR2_MMS; + shift = TIM_CR2_MMS_SHIFT; + master_mode_max = MASTER_MODE_MAX; + } + + for (i = 0; i <= master_mode_max; i++) { if (!strncmp(master_mode_table[i], buf, strlen(master_mode_table[i]))) { - regmap_update_bits(priv->regmap, TIM_CR2, - TIM_CR2_MMS, i << TIM_CR2_MMS_SHIFT); + regmap_update_bits(priv->regmap, TIM_CR2, mask, + i << shift); /* Make sure that registers are updated */ regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG); @@ -229,8 +270,31 @@ static ssize_t stm32_tt_store_master_mode(struct device *dev, return -EINVAL; } -static IIO_CONST_ATTR(master_mode_available, - "reset enable update compare_pulse OC1REF OC2REF OC3REF OC4REF"); +static ssize_t stm32_tt_show_master_mode_avail(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_trigger *trig = to_iio_trigger(dev); + unsigned int i, master_mode_max; + size_t len = 0; + + if (stm32_timer_is_trgo2_name(trig->name)) + master_mode_max = MASTER_MODE2_MAX; + else + master_mode_max = MASTER_MODE_MAX; + + for (i = 0; i <= master_mode_max; i++) + len += scnprintf(buf + len, PAGE_SIZE - len, + "%s ", master_mode_table[i]); + + /* replace trailing space by newline */ + buf[len - 1] = '\n'; + + return len; +} + +static IIO_DEVICE_ATTR(master_mode_available, 0444, + stm32_tt_show_master_mode_avail, NULL, 0); static IIO_DEVICE_ATTR(master_mode, 0660, stm32_tt_show_master_mode, @@ -240,7 +304,7 @@ static IIO_DEVICE_ATTR(master_mode, 0660, static struct attribute *stm32_trigger_attrs[] = { &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_dev_attr_master_mode.dev_attr.attr, - &iio_const_attr_master_mode_available.dev_attr.attr, + &iio_dev_attr_master_mode_available.dev_attr.attr, NULL, }; @@ -264,6 +328,12 @@ static int stm32_setup_iio_triggers(struct stm32_timer_trigger *priv) while (cur && *cur) { struct iio_trigger *trig; + bool cur_is_trgo2 = stm32_timer_is_trgo2_name(*cur); + + if (cur_is_trgo2 && !priv->has_trgo2) { + cur++; + continue; + } trig = devm_iio_trigger_alloc(priv->dev, "%s", *cur); if (!trig) @@ -277,7 +347,7 @@ static int stm32_setup_iio_triggers(struct stm32_timer_trigger *priv) * should only be available on trgo trigger which * is always the first in the list. */ - if (cur == priv->triggers) + if (cur == priv->triggers || cur_is_trgo2) trig->dev.groups = stm32_trigger_attr_groups; iio_trigger_set_drvdata(trig, priv); @@ -584,6 +654,20 @@ bool is_stm32_timer_trigger(struct iio_trigger *trig) } EXPORT_SYMBOL(is_stm32_timer_trigger); +static void stm32_timer_detect_trgo2(struct stm32_timer_trigger *priv) +{ + u32 val; + + /* + * Master mode selection 2 bits can only be written and read back when + * timer supports it. + */ + regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, TIM_CR2_MMS2); + regmap_read(priv->regmap, TIM_CR2, &val); + regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, 0); + priv->has_trgo2 = !!val; +} + static int stm32_timer_trigger_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -614,6 +698,7 @@ static int stm32_timer_trigger_probe(struct platform_device *pdev) priv->max_arr = ddata->max_arr; priv->triggers = triggers_table[index]; priv->valids = valids_table[index]; + stm32_timer_detect_trgo2(priv); ret = stm32_setup_iio_triggers(priv); if (ret) diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c index af108e96b3ec..995acdd7c942 100644 --- a/drivers/staging/iio/frequency/ad9834.c +++ b/drivers/staging/iio/frequency/ad9834.c @@ -292,7 +292,7 @@ ssize_t ad9834_show_out0_wavetype_available(struct device *dev, return sprintf(buf, "%s\n", str); } -static IIO_DEVICE_ATTR(out_altvoltage0_out0_wavetype_available, S_IRUGO, +static IIO_DEVICE_ATTR(out_altvoltage0_out0_wavetype_available, 0444, ad9834_show_out0_wavetype_available, NULL, 0); static @@ -312,27 +312,27 @@ ssize_t ad9834_show_out1_wavetype_available(struct device *dev, return sprintf(buf, "%s\n", str); } -static IIO_DEVICE_ATTR(out_altvoltage0_out1_wavetype_available, S_IRUGO, +static IIO_DEVICE_ATTR(out_altvoltage0_out1_wavetype_available, 0444, ad9834_show_out1_wavetype_available, NULL, 0); /** * see dds.h for further information */ -static IIO_DEV_ATTR_FREQ(0, 0, S_IWUSR, NULL, ad9834_write, AD9834_REG_FREQ0); -static IIO_DEV_ATTR_FREQ(0, 1, S_IWUSR, NULL, ad9834_write, AD9834_REG_FREQ1); -static IIO_DEV_ATTR_FREQSYMBOL(0, S_IWUSR, NULL, ad9834_write, AD9834_FSEL); +static IIO_DEV_ATTR_FREQ(0, 0, 0200, NULL, ad9834_write, AD9834_REG_FREQ0); +static IIO_DEV_ATTR_FREQ(0, 1, 0200, NULL, ad9834_write, AD9834_REG_FREQ1); +static IIO_DEV_ATTR_FREQSYMBOL(0, 0200, NULL, ad9834_write, AD9834_FSEL); static IIO_CONST_ATTR_FREQ_SCALE(0, "1"); /* 1Hz */ -static IIO_DEV_ATTR_PHASE(0, 0, S_IWUSR, NULL, ad9834_write, AD9834_REG_PHASE0); -static IIO_DEV_ATTR_PHASE(0, 1, S_IWUSR, NULL, ad9834_write, AD9834_REG_PHASE1); -static IIO_DEV_ATTR_PHASESYMBOL(0, S_IWUSR, NULL, ad9834_write, AD9834_PSEL); +static IIO_DEV_ATTR_PHASE(0, 0, 0200, NULL, ad9834_write, AD9834_REG_PHASE0); +static IIO_DEV_ATTR_PHASE(0, 1, 0200, NULL, ad9834_write, AD9834_REG_PHASE1); +static IIO_DEV_ATTR_PHASESYMBOL(0, 0200, NULL, ad9834_write, AD9834_PSEL); static IIO_CONST_ATTR_PHASE_SCALE(0, "0.0015339808"); /* 2PI/2^12 rad*/ -static IIO_DEV_ATTR_PINCONTROL_EN(0, S_IWUSR, NULL, +static IIO_DEV_ATTR_PINCONTROL_EN(0, 0200, NULL, ad9834_write, AD9834_PIN_SW); -static IIO_DEV_ATTR_OUT_ENABLE(0, S_IWUSR, NULL, ad9834_write, AD9834_RESET); -static IIO_DEV_ATTR_OUTY_ENABLE(0, 1, S_IWUSR, NULL, +static IIO_DEV_ATTR_OUT_ENABLE(0, 0200, NULL, ad9834_write, AD9834_RESET); +static IIO_DEV_ATTR_OUTY_ENABLE(0, 1, 0200, NULL, ad9834_write, AD9834_OPBITEN); static IIO_DEV_ATTR_OUT_WAVETYPE(0, 0, ad9834_store_wavetype, 0); static IIO_DEV_ATTR_OUT_WAVETYPE(0, 1, ad9834_store_wavetype, 1); diff --git a/drivers/staging/iio/frequency/dds.h b/drivers/staging/iio/frequency/dds.h index fe53e7324c94..d6ccd99c14d7 100644 --- a/drivers/staging/iio/frequency/dds.h +++ b/drivers/staging/iio/frequency/dds.h @@ -101,7 +101,7 @@ #define IIO_DEV_ATTR_OUT_WAVETYPE(_channel, _output, _store, _addr) \ IIO_DEVICE_ATTR(out_altvoltage##_channel##_out##_output##_wavetype,\ - S_IWUSR, NULL, _store, _addr) + 0200, NULL, _store, _addr) /** * /sys/bus/iio/devices/.../out_altvoltageX_outY_wavetype_available diff --git a/drivers/staging/iio/light/Kconfig b/drivers/staging/iio/light/Kconfig index 4fbf6298c0f3..aacb0ae58c0e 100644 --- a/drivers/staging/iio/light/Kconfig +++ b/drivers/staging/iio/light/Kconfig @@ -3,16 +3,6 @@ # menu "Light sensors" -config SENSORS_ISL29028 - tristate "Intersil ISL29028 Concurrent Light and Proximity Sensor" - depends on I2C - select REGMAP_I2C - help - Provides driver for the Intersil's ISL29028 device. - This driver supports the sysfs interface to get the ALS, IR intensity, - Proximity value via iio. The ISL29028 provides the concurrent sensing - of ambient light and proximity. - config TSL2x7x tristate "TAOS TSL/TMD2x71 and TSL/TMD2x72 Family of light and proximity sensors" depends on I2C diff --git a/drivers/staging/iio/light/Makefile b/drivers/staging/iio/light/Makefile index f8693e9fdc94..ab8dc3a3d10b 100644 --- a/drivers/staging/iio/light/Makefile +++ b/drivers/staging/iio/light/Makefile @@ -2,5 +2,4 @@ # Makefile for industrial I/O Light sensors # -obj-$(CONFIG_SENSORS_ISL29028) += isl29028.o -obj-$(CONFIG_TSL2x7x) += tsl2x7x_core.o +obj-$(CONFIG_TSL2x7x) += tsl2x7x.o diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x.c index af3910bc1b4f..146719928fb3 100644 --- a/drivers/staging/iio/light/tsl2x7x_core.c +++ b/drivers/staging/iio/light/tsl2x7x.c @@ -13,10 +13,6 @@ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include <linux/kernel.h> @@ -919,7 +915,7 @@ static void tsl2x7x_prox_cal(struct iio_dev *indio_dev) tsl2x7x_chip_on(indio_dev); } -static ssize_t tsl2x7x_power_state_show(struct device *dev, +static ssize_t power_state_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -928,7 +924,7 @@ static ssize_t tsl2x7x_power_state_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", chip->tsl2x7x_chip_status); } -static ssize_t tsl2x7x_power_state_store(struct device *dev, +static ssize_t power_state_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { @@ -946,7 +942,7 @@ static ssize_t tsl2x7x_power_state_store(struct device *dev, return len; } -static ssize_t tsl2x7x_gain_available_show(struct device *dev, +static ssize_t in_illuminance0_calibscale_available_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -964,14 +960,14 @@ static ssize_t tsl2x7x_gain_available_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "%s\n", "1 8 16 120"); } -static ssize_t tsl2x7x_prox_gain_available_show(struct device *dev, +static ssize_t in_proximity0_calibscale_available_show(struct device *dev, struct device_attribute *attr, char *buf) { return snprintf(buf, PAGE_SIZE, "%s\n", "1 2 4 8"); } -static ssize_t tsl2x7x_als_time_show(struct device *dev, +static ssize_t in_illuminance0_integration_time_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -986,7 +982,7 @@ static ssize_t tsl2x7x_als_time_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d.%03d\n", y, z); } -static ssize_t tsl2x7x_als_time_store(struct device *dev, +static ssize_t in_illuminance0_integration_time_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { @@ -1014,7 +1010,7 @@ static ssize_t tsl2x7x_als_time_store(struct device *dev, static IIO_CONST_ATTR(in_illuminance0_integration_time_available, ".00272 - .696"); -static ssize_t tsl2x7x_als_cal_target_show(struct device *dev, +static ssize_t in_illuminance0_target_input_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1024,7 +1020,7 @@ static ssize_t tsl2x7x_als_cal_target_show(struct device *dev, chip->tsl2x7x_settings.als_cal_target); } -static ssize_t tsl2x7x_als_cal_target_store(struct device *dev, +static ssize_t in_illuminance0_target_input_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { @@ -1044,7 +1040,7 @@ static ssize_t tsl2x7x_als_cal_target_store(struct device *dev, } /* persistence settings */ -static ssize_t tsl2x7x_als_persistence_show(struct device *dev, +static ssize_t in_intensity0_thresh_period_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1061,7 +1057,7 @@ static ssize_t tsl2x7x_als_persistence_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d.%03d\n", y, z); } -static ssize_t tsl2x7x_als_persistence_store(struct device *dev, +static ssize_t in_intensity0_thresh_period_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { @@ -1092,7 +1088,7 @@ static ssize_t tsl2x7x_als_persistence_store(struct device *dev, return IIO_VAL_INT_PLUS_MICRO; } -static ssize_t tsl2x7x_prox_persistence_show(struct device *dev, +static ssize_t in_proximity0_thresh_period_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1109,7 +1105,7 @@ static ssize_t tsl2x7x_prox_persistence_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d.%03d\n", y, z); } -static ssize_t tsl2x7x_prox_persistence_store(struct device *dev, +static ssize_t in_proximity0_thresh_period_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { @@ -1140,7 +1136,7 @@ static ssize_t tsl2x7x_prox_persistence_store(struct device *dev, return IIO_VAL_INT_PLUS_MICRO; } -static ssize_t tsl2x7x_do_calibrate(struct device *dev, +static ssize_t in_illuminance0_calibrate_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { @@ -1158,7 +1154,7 @@ static ssize_t tsl2x7x_do_calibrate(struct device *dev, return len; } -static ssize_t tsl2x7x_luxtable_show(struct device *dev, +static ssize_t in_illuminance0_lux_table_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1186,7 +1182,7 @@ static ssize_t tsl2x7x_luxtable_show(struct device *dev, return offset; } -static ssize_t tsl2x7x_luxtable_store(struct device *dev, +static ssize_t in_illuminance0_lux_table_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { @@ -1226,7 +1222,7 @@ static ssize_t tsl2x7x_luxtable_store(struct device *dev, return len; } -static ssize_t tsl2x7x_do_prox_calibrate(struct device *dev, +static ssize_t in_proximity0_calibrate_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { @@ -1498,35 +1494,25 @@ static int tsl2x7x_write_raw(struct iio_dev *indio_dev, return 0; } -static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR, - tsl2x7x_power_state_show, tsl2x7x_power_state_store); +static DEVICE_ATTR_RW(power_state); -static DEVICE_ATTR(in_proximity0_calibscale_available, S_IRUGO, - tsl2x7x_prox_gain_available_show, NULL); +static DEVICE_ATTR_RO(in_proximity0_calibscale_available); -static DEVICE_ATTR(in_illuminance0_calibscale_available, S_IRUGO, - tsl2x7x_gain_available_show, NULL); +static DEVICE_ATTR_RO(in_illuminance0_calibscale_available); -static DEVICE_ATTR(in_illuminance0_integration_time, S_IRUGO | S_IWUSR, - tsl2x7x_als_time_show, tsl2x7x_als_time_store); +static DEVICE_ATTR_RW(in_illuminance0_integration_time); -static DEVICE_ATTR(in_illuminance0_target_input, S_IRUGO | S_IWUSR, - tsl2x7x_als_cal_target_show, tsl2x7x_als_cal_target_store); +static DEVICE_ATTR_RW(in_illuminance0_target_input); -static DEVICE_ATTR(in_illuminance0_calibrate, S_IWUSR, NULL, - tsl2x7x_do_calibrate); +static DEVICE_ATTR_WO(in_illuminance0_calibrate); -static DEVICE_ATTR(in_proximity0_calibrate, S_IWUSR, NULL, - tsl2x7x_do_prox_calibrate); +static DEVICE_ATTR_WO(in_proximity0_calibrate); -static DEVICE_ATTR(in_illuminance0_lux_table, S_IRUGO | S_IWUSR, - tsl2x7x_luxtable_show, tsl2x7x_luxtable_store); +static DEVICE_ATTR_RW(in_illuminance0_lux_table); -static DEVICE_ATTR(in_intensity0_thresh_period, S_IRUGO | S_IWUSR, - tsl2x7x_als_persistence_show, tsl2x7x_als_persistence_store); +static DEVICE_ATTR_RW(in_intensity0_thresh_period); -static DEVICE_ATTR(in_proximity0_thresh_period, S_IRUGO | S_IWUSR, - tsl2x7x_prox_persistence_show, tsl2x7x_prox_persistence_store); +static DEVICE_ATTR_RW(in_proximity0_thresh_period); /* Use the default register values to identify the Taos device */ static int tsl2x7x_device_id(unsigned char *id, int target) diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c index b71fbd313778..ce26abdeab92 100644 --- a/drivers/staging/iio/meter/ade7753.c +++ b/drivers/staging/iio/meter/ade7753.c @@ -107,9 +107,8 @@ static int ade7753_spi_write_reg_8(struct device *dev, return ret; } -static int ade7753_spi_write_reg_16(struct device *dev, - u8 reg_address, - u16 value) +static int ade7753_spi_write_reg_16(struct device *dev, u8 reg_address, + u16 value) { int ret; struct iio_dev *indio_dev = dev_to_iio_dev(dev); @@ -126,8 +125,8 @@ static int ade7753_spi_write_reg_16(struct device *dev, } static int ade7753_spi_read_reg_8(struct device *dev, - u8 reg_address, - u8 *val) + u8 reg_address, + u8 *val) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7753_state *st = iio_priv(indio_dev); @@ -136,7 +135,7 @@ static int ade7753_spi_read_reg_8(struct device *dev, ret = spi_w8r8(st->us, ADE7753_READ_REG(reg_address)); if (ret < 0) { dev_err(&st->us->dev, "problem when reading 8 bit register 0x%02X", - reg_address); + reg_address); return ret; } *val = ret; @@ -145,8 +144,8 @@ static int ade7753_spi_read_reg_8(struct device *dev, } static int ade7753_spi_read_reg_16(struct device *dev, - u8 reg_address, - u16 *val) + u8 reg_address, + u16 *val) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7753_state *st = iio_priv(indio_dev); @@ -165,8 +164,8 @@ static int ade7753_spi_read_reg_16(struct device *dev, } static int ade7753_spi_read_reg_24(struct device *dev, - u8 reg_address, - u32 *val) + u8 reg_address, + u32 *val) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7753_state *st = iio_priv(indio_dev); @@ -189,7 +188,7 @@ static int ade7753_spi_read_reg_24(struct device *dev, ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X", - reg_address); + reg_address); goto error_ret; } *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2]; @@ -200,8 +199,8 @@ error_ret: } static ssize_t ade7753_read_8bit(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { int ret; u8 val; @@ -215,8 +214,8 @@ static ssize_t ade7753_read_8bit(struct device *dev, } static ssize_t ade7753_read_16bit(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { int ret; u16 val; @@ -230,8 +229,8 @@ static ssize_t ade7753_read_16bit(struct device *dev, } static ssize_t ade7753_read_24bit(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { int ret; u32 val; @@ -245,9 +244,9 @@ static ssize_t ade7753_read_24bit(struct device *dev, } static ssize_t ade7753_write_8bit(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) + struct device_attribute *attr, + const char *buf, + size_t len) { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; @@ -263,9 +262,9 @@ error_ret: } static ssize_t ade7753_write_16bit(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) + struct device_attribute *attr, + const char *buf, + size_t len) { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret; @@ -298,92 +297,92 @@ static IIO_DEV_ATTR_AENERGY(ade7753_read_24bit, ADE7753_AENERGY); static IIO_DEV_ATTR_LAENERGY(ade7753_read_24bit, ADE7753_LAENERGY); static IIO_DEV_ATTR_VAENERGY(ade7753_read_24bit, ADE7753_VAENERGY); static IIO_DEV_ATTR_LVAENERGY(ade7753_read_24bit, ADE7753_LVAENERGY); -static IIO_DEV_ATTR_CFDEN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_CFDEN(0644, ade7753_read_16bit, ade7753_write_16bit, ADE7753_CFDEN); -static IIO_DEV_ATTR_CFNUM(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_CFNUM(0644, ade7753_read_8bit, ade7753_write_8bit, ADE7753_CFNUM); static IIO_DEV_ATTR_CHKSUM(ade7753_read_8bit, ADE7753_CHKSUM); -static IIO_DEV_ATTR_PHCAL(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_PHCAL(0644, ade7753_read_16bit, ade7753_write_16bit, ADE7753_PHCAL); -static IIO_DEV_ATTR_APOS(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_APOS(0644, ade7753_read_16bit, ade7753_write_16bit, ADE7753_APOS); -static IIO_DEV_ATTR_SAGCYC(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_SAGCYC(0644, ade7753_read_8bit, ade7753_write_8bit, ADE7753_SAGCYC); -static IIO_DEV_ATTR_SAGLVL(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_SAGLVL(0644, ade7753_read_8bit, ade7753_write_8bit, ADE7753_SAGLVL); -static IIO_DEV_ATTR_LINECYC(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_LINECYC(0644, ade7753_read_8bit, ade7753_write_8bit, ADE7753_LINECYC); -static IIO_DEV_ATTR_WDIV(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_WDIV(0644, ade7753_read_8bit, ade7753_write_8bit, ADE7753_WDIV); -static IIO_DEV_ATTR_IRMS(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_IRMS(0644, ade7753_read_24bit, NULL, ADE7753_IRMS); -static IIO_DEV_ATTR_VRMS(S_IRUGO, +static IIO_DEV_ATTR_VRMS(0444, ade7753_read_24bit, NULL, ADE7753_VRMS); -static IIO_DEV_ATTR_IRMSOS(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_IRMSOS(0644, ade7753_read_16bit, ade7753_write_16bit, ADE7753_IRMSOS); -static IIO_DEV_ATTR_VRMSOS(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_VRMSOS(0644, ade7753_read_16bit, ade7753_write_16bit, ADE7753_VRMSOS); -static IIO_DEV_ATTR_WGAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_WGAIN(0644, ade7753_read_16bit, ade7753_write_16bit, ADE7753_WGAIN); -static IIO_DEV_ATTR_VAGAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_VAGAIN(0644, ade7753_read_16bit, ade7753_write_16bit, ADE7753_VAGAIN); -static IIO_DEV_ATTR_PGA_GAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_PGA_GAIN(0644, ade7753_read_16bit, ade7753_write_16bit, ADE7753_GAIN); -static IIO_DEV_ATTR_IPKLVL(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_IPKLVL(0644, ade7753_read_8bit, ade7753_write_8bit, ADE7753_IPKLVL); -static IIO_DEV_ATTR_VPKLVL(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_VPKLVL(0644, ade7753_read_8bit, ade7753_write_8bit, ADE7753_VPKLVL); -static IIO_DEV_ATTR_IPEAK(S_IRUGO, +static IIO_DEV_ATTR_IPEAK(0444, ade7753_read_24bit, NULL, ADE7753_IPEAK); -static IIO_DEV_ATTR_VPEAK(S_IRUGO, +static IIO_DEV_ATTR_VPEAK(0444, ade7753_read_24bit, NULL, ADE7753_VPEAK); -static IIO_DEV_ATTR_VPERIOD(S_IRUGO, +static IIO_DEV_ATTR_VPERIOD(0444, ade7753_read_16bit, NULL, ADE7753_PERIOD); -static IIO_DEV_ATTR_CH_OFF(1, S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_CH_OFF(1, 0644, ade7753_read_8bit, ade7753_write_8bit, ADE7753_CH1OS); -static IIO_DEV_ATTR_CH_OFF(2, S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_CH_OFF(2, 0644, ade7753_read_8bit, ade7753_write_8bit, ADE7753_CH2OS); @@ -450,8 +449,8 @@ err_ret: } static ssize_t ade7753_read_frequency(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { int ret; u16 t; @@ -468,9 +467,9 @@ static ssize_t ade7753_read_frequency(struct device *dev, } static ssize_t ade7753_write_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) + struct device_attribute *attr, + const char *buf, + size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ade7753_state *st = iio_priv(indio_dev); @@ -514,7 +513,7 @@ static IIO_DEV_ATTR_TEMP_RAW(ade7753_read_8bit); static IIO_CONST_ATTR(in_temp_offset, "-25 C"); static IIO_CONST_ATTR(in_temp_scale, "0.67 C"); -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_SAMP_FREQ(0644, ade7753_read_frequency, ade7753_write_frequency); diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c index 32dc50341746..be0df3fe4230 100644 --- a/drivers/staging/iio/meter/ade7754.c +++ b/drivers/staging/iio/meter/ade7754.c @@ -316,111 +316,111 @@ static IIO_DEV_ATTR_AENERGY(ade7754_read_24bit, ADE7754_AENERGY); static IIO_DEV_ATTR_LAENERGY(ade7754_read_24bit, ADE7754_LAENERGY); static IIO_DEV_ATTR_VAENERGY(ade7754_read_24bit, ADE7754_VAENERGY); static IIO_DEV_ATTR_LVAENERGY(ade7754_read_24bit, ADE7754_LVAENERGY); -static IIO_DEV_ATTR_VPEAK(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_VPEAK(0644, ade7754_read_8bit, ade7754_write_8bit, ADE7754_VPEAK); -static IIO_DEV_ATTR_IPEAK(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_IPEAK(0644, ade7754_read_8bit, ade7754_write_8bit, ADE7754_VPEAK); -static IIO_DEV_ATTR_APHCAL(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_APHCAL(0644, ade7754_read_8bit, ade7754_write_8bit, ADE7754_APHCAL); -static IIO_DEV_ATTR_BPHCAL(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_BPHCAL(0644, ade7754_read_8bit, ade7754_write_8bit, ADE7754_BPHCAL); -static IIO_DEV_ATTR_CPHCAL(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_CPHCAL(0644, ade7754_read_8bit, ade7754_write_8bit, ADE7754_CPHCAL); -static IIO_DEV_ATTR_AAPOS(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_AAPOS(0644, ade7754_read_16bit, ade7754_write_16bit, ADE7754_AAPOS); -static IIO_DEV_ATTR_BAPOS(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_BAPOS(0644, ade7754_read_16bit, ade7754_write_16bit, ADE7754_BAPOS); -static IIO_DEV_ATTR_CAPOS(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_CAPOS(0644, ade7754_read_16bit, ade7754_write_16bit, ADE7754_CAPOS); -static IIO_DEV_ATTR_WDIV(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_WDIV(0644, ade7754_read_8bit, ade7754_write_8bit, ADE7754_WDIV); -static IIO_DEV_ATTR_VADIV(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_VADIV(0644, ade7754_read_8bit, ade7754_write_8bit, ADE7754_VADIV); -static IIO_DEV_ATTR_CFNUM(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_CFNUM(0644, ade7754_read_16bit, ade7754_write_16bit, ADE7754_CFNUM); -static IIO_DEV_ATTR_CFDEN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_CFDEN(0644, ade7754_read_16bit, ade7754_write_16bit, ADE7754_CFDEN); -static IIO_DEV_ATTR_ACTIVE_POWER_A_GAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_ACTIVE_POWER_A_GAIN(0644, ade7754_read_16bit, ade7754_write_16bit, ADE7754_AAPGAIN); -static IIO_DEV_ATTR_ACTIVE_POWER_B_GAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_ACTIVE_POWER_B_GAIN(0644, ade7754_read_16bit, ade7754_write_16bit, ADE7754_BAPGAIN); -static IIO_DEV_ATTR_ACTIVE_POWER_C_GAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_ACTIVE_POWER_C_GAIN(0644, ade7754_read_16bit, ade7754_write_16bit, ADE7754_CAPGAIN); -static IIO_DEV_ATTR_AIRMS(S_IRUGO, +static IIO_DEV_ATTR_AIRMS(0444, ade7754_read_24bit, NULL, ADE7754_AIRMS); -static IIO_DEV_ATTR_BIRMS(S_IRUGO, +static IIO_DEV_ATTR_BIRMS(0444, ade7754_read_24bit, NULL, ADE7754_BIRMS); -static IIO_DEV_ATTR_CIRMS(S_IRUGO, +static IIO_DEV_ATTR_CIRMS(0444, ade7754_read_24bit, NULL, ADE7754_CIRMS); -static IIO_DEV_ATTR_AVRMS(S_IRUGO, +static IIO_DEV_ATTR_AVRMS(0444, ade7754_read_24bit, NULL, ADE7754_AVRMS); -static IIO_DEV_ATTR_BVRMS(S_IRUGO, +static IIO_DEV_ATTR_BVRMS(0444, ade7754_read_24bit, NULL, ADE7754_BVRMS); -static IIO_DEV_ATTR_CVRMS(S_IRUGO, +static IIO_DEV_ATTR_CVRMS(0444, ade7754_read_24bit, NULL, ADE7754_CVRMS); -static IIO_DEV_ATTR_AIRMSOS(S_IRUGO, +static IIO_DEV_ATTR_AIRMSOS(0444, ade7754_read_16bit, ade7754_write_16bit, ADE7754_AIRMSOS); -static IIO_DEV_ATTR_BIRMSOS(S_IRUGO, +static IIO_DEV_ATTR_BIRMSOS(0444, ade7754_read_16bit, ade7754_write_16bit, ADE7754_BIRMSOS); -static IIO_DEV_ATTR_CIRMSOS(S_IRUGO, +static IIO_DEV_ATTR_CIRMSOS(0444, ade7754_read_16bit, ade7754_write_16bit, ADE7754_CIRMSOS); -static IIO_DEV_ATTR_AVRMSOS(S_IRUGO, +static IIO_DEV_ATTR_AVRMSOS(0444, ade7754_read_16bit, ade7754_write_16bit, ADE7754_AVRMSOS); -static IIO_DEV_ATTR_BVRMSOS(S_IRUGO, +static IIO_DEV_ATTR_BVRMSOS(0444, ade7754_read_16bit, ade7754_write_16bit, ADE7754_BVRMSOS); -static IIO_DEV_ATTR_CVRMSOS(S_IRUGO, +static IIO_DEV_ATTR_CVRMSOS(0444, ade7754_read_16bit, ade7754_write_16bit, ADE7754_CVRMSOS); @@ -549,7 +549,7 @@ static IIO_DEV_ATTR_TEMP_RAW(ade7754_read_8bit); static IIO_CONST_ATTR(in_temp_offset, "129 C"); static IIO_CONST_ATTR(in_temp_scale, "4 C"); -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_SAMP_FREQ(0644, ade7754_read_frequency, ade7754_write_frequency); diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c index 99c89e606c8d..40498af4dc46 100644 --- a/drivers/staging/iio/meter/ade7758_core.c +++ b/drivers/staging/iio/meter/ade7758_core.c @@ -301,103 +301,103 @@ static int ade7758_reset(struct device *dev) return ret; } -static IIO_DEV_ATTR_VPEAK(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_VPEAK(0644, ade7758_read_8bit, ade7758_write_8bit, ADE7758_VPEAK); -static IIO_DEV_ATTR_IPEAK(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_IPEAK(0644, ade7758_read_8bit, ade7758_write_8bit, ADE7758_VPEAK); -static IIO_DEV_ATTR_APHCAL(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_APHCAL(0644, ade7758_read_8bit, ade7758_write_8bit, ADE7758_APHCAL); -static IIO_DEV_ATTR_BPHCAL(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_BPHCAL(0644, ade7758_read_8bit, ade7758_write_8bit, ADE7758_BPHCAL); -static IIO_DEV_ATTR_CPHCAL(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_CPHCAL(0644, ade7758_read_8bit, ade7758_write_8bit, ADE7758_CPHCAL); -static IIO_DEV_ATTR_WDIV(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_WDIV(0644, ade7758_read_8bit, ade7758_write_8bit, ADE7758_WDIV); -static IIO_DEV_ATTR_VADIV(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_VADIV(0644, ade7758_read_8bit, ade7758_write_8bit, ADE7758_VADIV); -static IIO_DEV_ATTR_AIRMS(S_IRUGO, +static IIO_DEV_ATTR_AIRMS(0444, ade7758_read_24bit, NULL, ADE7758_AIRMS); -static IIO_DEV_ATTR_BIRMS(S_IRUGO, +static IIO_DEV_ATTR_BIRMS(0444, ade7758_read_24bit, NULL, ADE7758_BIRMS); -static IIO_DEV_ATTR_CIRMS(S_IRUGO, +static IIO_DEV_ATTR_CIRMS(0444, ade7758_read_24bit, NULL, ADE7758_CIRMS); -static IIO_DEV_ATTR_AVRMS(S_IRUGO, +static IIO_DEV_ATTR_AVRMS(0444, ade7758_read_24bit, NULL, ADE7758_AVRMS); -static IIO_DEV_ATTR_BVRMS(S_IRUGO, +static IIO_DEV_ATTR_BVRMS(0444, ade7758_read_24bit, NULL, ADE7758_BVRMS); -static IIO_DEV_ATTR_CVRMS(S_IRUGO, +static IIO_DEV_ATTR_CVRMS(0444, ade7758_read_24bit, NULL, ADE7758_CVRMS); -static IIO_DEV_ATTR_AIRMSOS(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_AIRMSOS(0644, ade7758_read_16bit, ade7758_write_16bit, ADE7758_AIRMSOS); -static IIO_DEV_ATTR_BIRMSOS(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_BIRMSOS(0644, ade7758_read_16bit, ade7758_write_16bit, ADE7758_BIRMSOS); -static IIO_DEV_ATTR_CIRMSOS(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_CIRMSOS(0644, ade7758_read_16bit, ade7758_write_16bit, ADE7758_CIRMSOS); -static IIO_DEV_ATTR_AVRMSOS(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_AVRMSOS(0644, ade7758_read_16bit, ade7758_write_16bit, ADE7758_AVRMSOS); -static IIO_DEV_ATTR_BVRMSOS(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_BVRMSOS(0644, ade7758_read_16bit, ade7758_write_16bit, ADE7758_BVRMSOS); -static IIO_DEV_ATTR_CVRMSOS(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_CVRMSOS(0644, ade7758_read_16bit, ade7758_write_16bit, ADE7758_CVRMSOS); -static IIO_DEV_ATTR_AIGAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_AIGAIN(0644, ade7758_read_16bit, ade7758_write_16bit, ADE7758_AIGAIN); -static IIO_DEV_ATTR_BIGAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_BIGAIN(0644, ade7758_read_16bit, ade7758_write_16bit, ADE7758_BIGAIN); -static IIO_DEV_ATTR_CIGAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_CIGAIN(0644, ade7758_read_16bit, ade7758_write_16bit, ADE7758_CIGAIN); -static IIO_DEV_ATTR_AVRMSGAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_AVRMSGAIN(0644, ade7758_read_16bit, ade7758_write_16bit, ADE7758_AVRMSGAIN); -static IIO_DEV_ATTR_BVRMSGAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_BVRMSGAIN(0644, ade7758_read_16bit, ade7758_write_16bit, ADE7758_BVRMSGAIN); -static IIO_DEV_ATTR_CVRMSGAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_CVRMSGAIN(0644, ade7758_read_16bit, ade7758_write_16bit, ADE7758_CVRMSGAIN); diff --git a/drivers/staging/iio/meter/ade7854.c b/drivers/staging/iio/meter/ade7854.c index c6cffc11b0ba..70612da64a8b 100644 --- a/drivers/staging/iio/meter/ade7854.c +++ b/drivers/staging/iio/meter/ade7854.c @@ -186,127 +186,127 @@ static int ade7854_reset(struct device *dev) return st->write_reg_16(dev, ADE7854_CONFIG, val); } -static IIO_DEV_ATTR_AIGAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_AIGAIN(0644, ade7854_read_24bit, ade7854_write_24bit, ADE7854_AIGAIN); -static IIO_DEV_ATTR_BIGAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_BIGAIN(0644, ade7854_read_24bit, ade7854_write_24bit, ADE7854_BIGAIN); -static IIO_DEV_ATTR_CIGAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_CIGAIN(0644, ade7854_read_24bit, ade7854_write_24bit, ADE7854_CIGAIN); -static IIO_DEV_ATTR_NIGAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_NIGAIN(0644, ade7854_read_24bit, ade7854_write_24bit, ADE7854_NIGAIN); -static IIO_DEV_ATTR_AVGAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_AVGAIN(0644, ade7854_read_24bit, ade7854_write_24bit, ADE7854_AVGAIN); -static IIO_DEV_ATTR_BVGAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_BVGAIN(0644, ade7854_read_24bit, ade7854_write_24bit, ADE7854_BVGAIN); -static IIO_DEV_ATTR_CVGAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_CVGAIN(0644, ade7854_read_24bit, ade7854_write_24bit, ADE7854_CVGAIN); -static IIO_DEV_ATTR_APPARENT_POWER_A_GAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_APPARENT_POWER_A_GAIN(0644, ade7854_read_24bit, ade7854_write_24bit, ADE7854_AVAGAIN); -static IIO_DEV_ATTR_APPARENT_POWER_B_GAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_APPARENT_POWER_B_GAIN(0644, ade7854_read_24bit, ade7854_write_24bit, ADE7854_BVAGAIN); -static IIO_DEV_ATTR_APPARENT_POWER_C_GAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_APPARENT_POWER_C_GAIN(0644, ade7854_read_24bit, ade7854_write_24bit, ADE7854_CVAGAIN); -static IIO_DEV_ATTR_ACTIVE_POWER_A_OFFSET(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_ACTIVE_POWER_A_OFFSET(0644, ade7854_read_24bit, ade7854_write_24bit, ADE7854_AWATTOS); -static IIO_DEV_ATTR_ACTIVE_POWER_B_OFFSET(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_ACTIVE_POWER_B_OFFSET(0644, ade7854_read_24bit, ade7854_write_24bit, ADE7854_BWATTOS); -static IIO_DEV_ATTR_ACTIVE_POWER_C_OFFSET(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_ACTIVE_POWER_C_OFFSET(0644, ade7854_read_24bit, ade7854_write_24bit, ADE7854_CWATTOS); -static IIO_DEV_ATTR_REACTIVE_POWER_A_GAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_REACTIVE_POWER_A_GAIN(0644, ade7854_read_24bit, ade7854_write_24bit, ADE7854_AVARGAIN); -static IIO_DEV_ATTR_REACTIVE_POWER_B_GAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_REACTIVE_POWER_B_GAIN(0644, ade7854_read_24bit, ade7854_write_24bit, ADE7854_BVARGAIN); -static IIO_DEV_ATTR_REACTIVE_POWER_C_GAIN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_REACTIVE_POWER_C_GAIN(0644, ade7854_read_24bit, ade7854_write_24bit, ADE7854_CVARGAIN); -static IIO_DEV_ATTR_REACTIVE_POWER_A_OFFSET(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_REACTIVE_POWER_A_OFFSET(0644, ade7854_read_24bit, ade7854_write_24bit, ADE7854_AVAROS); -static IIO_DEV_ATTR_REACTIVE_POWER_B_OFFSET(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_REACTIVE_POWER_B_OFFSET(0644, ade7854_read_24bit, ade7854_write_24bit, ADE7854_BVAROS); -static IIO_DEV_ATTR_REACTIVE_POWER_C_OFFSET(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_REACTIVE_POWER_C_OFFSET(0644, ade7854_read_24bit, ade7854_write_24bit, ADE7854_CVAROS); -static IIO_DEV_ATTR_VPEAK(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_VPEAK(0644, ade7854_read_32bit, ade7854_write_32bit, ADE7854_VPEAK); -static IIO_DEV_ATTR_IPEAK(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_IPEAK(0644, ade7854_read_32bit, ade7854_write_32bit, ADE7854_VPEAK); -static IIO_DEV_ATTR_APHCAL(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_APHCAL(0644, ade7854_read_16bit, ade7854_write_16bit, ADE7854_APHCAL); -static IIO_DEV_ATTR_BPHCAL(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_BPHCAL(0644, ade7854_read_16bit, ade7854_write_16bit, ADE7854_BPHCAL); -static IIO_DEV_ATTR_CPHCAL(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_CPHCAL(0644, ade7854_read_16bit, ade7854_write_16bit, ADE7854_CPHCAL); -static IIO_DEV_ATTR_CF1DEN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_CF1DEN(0644, ade7854_read_16bit, ade7854_write_16bit, ADE7854_CF1DEN); -static IIO_DEV_ATTR_CF2DEN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_CF2DEN(0644, ade7854_read_16bit, ade7854_write_16bit, ADE7854_CF2DEN); -static IIO_DEV_ATTR_CF3DEN(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_CF3DEN(0644, ade7854_read_16bit, ade7854_write_16bit, ADE7854_CF3DEN); -static IIO_DEV_ATTR_LINECYC(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_LINECYC(0644, ade7854_read_16bit, ade7854_write_16bit, ADE7854_LINECYC); -static IIO_DEV_ATTR_SAGCYC(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_SAGCYC(0644, ade7854_read_8bit, ade7854_write_8bit, ADE7854_SAGCYC); -static IIO_DEV_ATTR_CFCYC(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_CFCYC(0644, ade7854_read_8bit, ade7854_write_8bit, ADE7854_CFCYC); -static IIO_DEV_ATTR_PEAKCYC(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_PEAKCYC(0644, ade7854_read_8bit, ade7854_write_8bit, ADE7854_PEAKCYC); @@ -318,55 +318,55 @@ static IIO_DEV_ATTR_ANGLE1(ade7854_read_24bit, ADE7854_ANGLE1); static IIO_DEV_ATTR_ANGLE2(ade7854_read_24bit, ADE7854_ANGLE2); -static IIO_DEV_ATTR_AIRMS(S_IRUGO, +static IIO_DEV_ATTR_AIRMS(0444, ade7854_read_24bit, NULL, ADE7854_AIRMS); -static IIO_DEV_ATTR_BIRMS(S_IRUGO, +static IIO_DEV_ATTR_BIRMS(0444, ade7854_read_24bit, NULL, ADE7854_BIRMS); -static IIO_DEV_ATTR_CIRMS(S_IRUGO, +static IIO_DEV_ATTR_CIRMS(0444, ade7854_read_24bit, NULL, ADE7854_CIRMS); -static IIO_DEV_ATTR_NIRMS(S_IRUGO, +static IIO_DEV_ATTR_NIRMS(0444, ade7854_read_24bit, NULL, ADE7854_NIRMS); -static IIO_DEV_ATTR_AVRMS(S_IRUGO, +static IIO_DEV_ATTR_AVRMS(0444, ade7854_read_24bit, NULL, ADE7854_AVRMS); -static IIO_DEV_ATTR_BVRMS(S_IRUGO, +static IIO_DEV_ATTR_BVRMS(0444, ade7854_read_24bit, NULL, ADE7854_BVRMS); -static IIO_DEV_ATTR_CVRMS(S_IRUGO, +static IIO_DEV_ATTR_CVRMS(0444, ade7854_read_24bit, NULL, ADE7854_CVRMS); -static IIO_DEV_ATTR_AIRMSOS(S_IRUGO, +static IIO_DEV_ATTR_AIRMSOS(0444, ade7854_read_16bit, ade7854_write_16bit, ADE7854_AIRMSOS); -static IIO_DEV_ATTR_BIRMSOS(S_IRUGO, +static IIO_DEV_ATTR_BIRMSOS(0444, ade7854_read_16bit, ade7854_write_16bit, ADE7854_BIRMSOS); -static IIO_DEV_ATTR_CIRMSOS(S_IRUGO, +static IIO_DEV_ATTR_CIRMSOS(0444, ade7854_read_16bit, ade7854_write_16bit, ADE7854_CIRMSOS); -static IIO_DEV_ATTR_AVRMSOS(S_IRUGO, +static IIO_DEV_ATTR_AVRMSOS(0444, ade7854_read_16bit, ade7854_write_16bit, ADE7854_AVRMSOS); -static IIO_DEV_ATTR_BVRMSOS(S_IRUGO, +static IIO_DEV_ATTR_BVRMSOS(0444, ade7854_read_16bit, ade7854_write_16bit, ADE7854_BVRMSOS); -static IIO_DEV_ATTR_CVRMSOS(S_IRUGO, +static IIO_DEV_ATTR_CVRMSOS(0444, ade7854_read_16bit, ade7854_write_16bit, ADE7854_CVRMSOS); diff --git a/include/linux/hid-sensor-hub.h b/include/linux/hid-sensor-hub.h index f32d7c392c1e..fc7aae64dcde 100644 --- a/include/linux/hid-sensor-hub.h +++ b/include/linux/hid-sensor-hub.h @@ -233,12 +233,14 @@ struct hid_sensor_common { atomic_t user_requested_state; int poll_interval; int raw_hystersis; + int latency_ms; struct iio_trigger *trigger; int timestamp_ns_scale; struct hid_sensor_hub_attribute_info poll; struct hid_sensor_hub_attribute_info report_state; struct hid_sensor_hub_attribute_info power_state; struct hid_sensor_hub_attribute_info sensitivity; + struct hid_sensor_hub_attribute_info report_latency; struct work_struct work; }; @@ -276,5 +278,8 @@ s32 hid_sensor_read_poll_value(struct hid_sensor_common *st); int64_t hid_sensor_convert_timestamp(struct hid_sensor_common *st, int64_t raw_value); +bool hid_sensor_batch_mode_supported(struct hid_sensor_common *st); +int hid_sensor_set_report_latency(struct hid_sensor_common *st, int latency); +int hid_sensor_get_report_latency(struct hid_sensor_common *st); #endif diff --git a/include/linux/hid-sensor-ids.h b/include/linux/hid-sensor-ids.h index 761f86242473..76033e0420a7 100644 --- a/include/linux/hid-sensor-ids.h +++ b/include/linux/hid-sensor-ids.h @@ -90,6 +90,8 @@ #define HID_USAGE_SENSOR_ORIENT_TILT_Z 0x200481 #define HID_USAGE_SENSOR_DEVICE_ORIENTATION 0x20008A +#define HID_USAGE_SENSOR_RELATIVE_ORIENTATION 0x20008E +#define HID_USAGE_SENSOR_GEOMAGNETIC_ORIENTATION 0x2000C1 #define HID_USAGE_SENSOR_ORIENT_ROTATION_MATRIX 0x200482 #define HID_USAGE_SENSOR_ORIENT_QUATERNION 0x200483 #define HID_USAGE_SENSOR_ORIENT_MAGN_FLUX 0x200484 @@ -150,6 +152,9 @@ #define HID_USAGE_SENSOR_PROP_REPORT_STATE 0x200316 #define HID_USAGE_SENSOR_PROY_POWER_STATE 0x200319 +/* Batch mode selectors */ +#define HID_USAGE_SENSOR_PROP_REPORT_LATENCY 0x20031B + /* Per data field properties */ #define HID_USAGE_SENSOR_DATA_MOD_NONE 0x00 #define HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS 0x1000 diff --git a/include/linux/iio/timer/stm32-timer-trigger.h b/include/linux/iio/timer/stm32-timer-trigger.h index 55535aef2e6c..fa7d786ed99e 100644 --- a/include/linux/iio/timer/stm32-timer-trigger.h +++ b/include/linux/iio/timer/stm32-timer-trigger.h @@ -10,6 +10,7 @@ #define _STM32_TIMER_TRIGGER_H_ #define TIM1_TRGO "tim1_trgo" +#define TIM1_TRGO2 "tim1_trgo2" #define TIM1_CH1 "tim1_ch1" #define TIM1_CH2 "tim1_ch2" #define TIM1_CH3 "tim1_ch3" @@ -44,6 +45,7 @@ #define TIM7_TRGO "tim7_trgo" #define TIM8_TRGO "tim8_trgo" +#define TIM8_TRGO2 "tim8_trgo2" #define TIM8_CH1 "tim8_ch1" #define TIM8_CH2 "tim8_ch2" #define TIM8_CH3 "tim8_ch3" diff --git a/include/linux/mfd/stm32-timers.h b/include/linux/mfd/stm32-timers.h index 4a0abbc10ef6..ce7346e7f77a 100644 --- a/include/linux/mfd/stm32-timers.h +++ b/include/linux/mfd/stm32-timers.h @@ -34,6 +34,7 @@ #define TIM_CR1_DIR BIT(4) /* Counter Direction */ #define TIM_CR1_ARPE BIT(7) /* Auto-reload Preload Ena */ #define TIM_CR2_MMS (BIT(4) | BIT(5) | BIT(6)) /* Master mode selection */ +#define TIM_CR2_MMS2 GENMASK(23, 20) /* Master mode selection 2 */ #define TIM_SMCR_SMS (BIT(0) | BIT(1) | BIT(2)) /* Slave mode selection */ #define TIM_SMCR_TS (BIT(4) | BIT(5) | BIT(6)) /* Trigger selection */ #define TIM_DIER_UIE BIT(0) /* Update interrupt */ @@ -60,6 +61,7 @@ #define MAX_TIM_PSC 0xFFFF #define TIM_CR2_MMS_SHIFT 4 +#define TIM_CR2_MMS2_SHIFT 20 #define TIM_SMCR_TS_SHIFT 4 #define TIM_BDTR_BKF_MASK 0xF #define TIM_BDTR_BKF_SHIFT 16 diff --git a/tools/iio/Makefile b/tools/iio/Makefile index 5446d625e17d..8f08e03a9a5e 100644 --- a/tools/iio/Makefile +++ b/tools/iio/Makefile @@ -1,5 +1,5 @@ CC = $(CROSS_COMPILE)gcc -CFLAGS += -Wall -g -D_GNU_SOURCE +CFLAGS += -Wall -g -D_GNU_SOURCE -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include BINDIR=usr/bin INSTALL_PROGRAM=install -m 755 -p diff --git a/tools/iio/iio_utils.h b/tools/iio/iio_utils.h index 780f2014f8fa..8b379da26e35 100644 --- a/tools/iio/iio_utils.h +++ b/tools/iio/iio_utils.h @@ -13,7 +13,7 @@ #include <stdint.h> /* Made up value to limit allocation sizes */ -#define IIO_MAX_NAME_LENGTH 30 +#define IIO_MAX_NAME_LENGTH 64 #define FORMAT_SCAN_ELEMENTS_DIR "%s/scan_elements" #define FORMAT_TYPE_FILE "%s_type" |