Merge tag 'iio-for-5.9a-take2' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23...
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 17 Jul 2020 10:04:05 +0000 (12:04 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 17 Jul 2020 10:04:05 +0000 (12:04 +0200)
Jonathan writes:

First set of new device support, cleanups and features for IIO in the 5.9 cycle

Some new devices, but particularly good this time is the core rework coming
from Alexandru. Some of this has been in Analog's tree a long time, but other
parts are motivated by closing down common mistakes in new drivers.

Changes since first try at this pull request:
* Add missed patch to actually remove iio_priv_to_dev and as a result
  also drop a few ingenic patches that need to be updated to take this
  into account.
* Fix an ordering issue int he pollfunc attach in the core rework.

New device support
* qcom pmic7 adc
  - New driver using common qcom-vadc library. Some associated cleanups and
    refactors.
* invensense icm42600
  - New driver supporting icm42600, icm42602, icm42605 and icm42622 via i2c
    or spi.  These are all 6 axis IMUs with gyro and accelerometers.
    Driver supports buffered modes using the hardware fifo and interpolation
    for accurate timestamps.
* sensirion scd30
  - New driver for this carbon dioxide sensor including i2c and serial
    interfaces + bindings.

Features
* ak8975
  - Add reset gpio support.
* bma400
  - Support SPI.
* bmc150
  - Document and add support for bmc156b and bmm150b, tidy up _magn endings.
* bmi160
  - Regulator and mount matrix support.
* mxc4005
  - Add ID for mxc6655
* rockchip-saradc
  - Triggered buffer support.

DT bindings
* qcom spmi-vadc converted to yaml + pmic7 bindings
* ak8975 tidy up and convert to yaml + add reset-gpio binding
* ingenic-adc -convert to yaml.

Core rework all carried through by Alexandru Ardelean.
* Assign parent device in the core rather than every driver. A few devices
  need to provide specific non standard parents, so there is support for
  overriding.
* Start to take parts of struct iio_dev opaque to the drivers.
  This will be a long term job, but should reduce the number of drivers
  we get that use parts that are currently only 'internal' by documentation.
* Move attach and detach of pollfunc to the core.  Every triggered buffer
  using driver had to do the same thing, so lets do it in the core.  The
  hard part here was getting all the drivers into canonical form so there
  would be no functional changes in this final patch.  That's taken quite
  a lot of work over last couple of cycles!

Cleanups and minor fixes.
* docs
  - Improve IIO_CONCENTRATION channel type description in ABI docs.
  - Drop doubled word cases.
  - Http to Https conversion.
* core
  - Make iio_device_get_drvdata take a const struct iio_dev * avoiding some
    nasty casts.
* ADCs
  - Drop lots of users of of_match_ptr macro, includes of mod_devicetable.h
    and CONFIG_OF protections.  These prevent use of ACPI PRP0001 with these
    drivers and get coppied into lots of new drivers.
* ad5380
  - Constify iio_chan_spec_ext_info
* ad5592r
  - Constify iio_chan_spec_ext_info
  - Avoid use of iio_priv_to_dev (precursor to taking parts of iio_dev opaque)
* ad8366
  - Make gpio optional as doesn't matter if its there or not.
* adis16480
  - Use irq types instead of the flags.
* atlas-ezo-sensor
  - Minimize scope of ret variable.
* at91-adc
  - Add COMPILE_TEST dependency to driver to improve build coverage.
  - Avoid use of iio_priv_to_dev (precursor to taking parts of iio_dev opaque)
* at91-sama5d2
  - Avoid use of iio_priv_to_dev (precursor to taking parts of iio_dev opaque)
  - Drop Ludovic as a co-maintaienr.
* cros_ec
  - Reapply the range after resume.
  - Add a read only frequency entry for legacy version.
  - Typo fixes
* hts221
  - Avoid use of iio_priv_to_dev (precursor to taking parts of iio_dev opaque)
* inv_mpu
  - Drop double check on ACPI companion device.
* iqs621
  - Avoid use of iio_priv_to_dev (precursor to taking parts of iio_dev opaque)
* iqs624
  - Avoid use of iio_priv_to_dev (precursor to taking parts of iio_dev opaque)
* max11100
  - Constify iio_chan_spec
* mmc35240
  - Constify reg_default
* rockchip-saradc
  - Move to managed allocators for everything in probe.
  - Use more distinctive prefix for channel macros.
* stk3310
  - Constify regmap_config.
* stm32-adc
  - Avoid use of iio_priv_to_dev (precursor to taking parts of iio_dev opaque)
* stm32-dfsdm-adc
  - Avoid use of iio_priv_to_dev (precursor to taking parts of iio_dev opaque)
* ti-am335x
  - Use managed allocations where straight forward in probe function.
* tsl2563
  - Avoid use of iio_priv_to_dev (precursor to taking parts of iio_dev opaque)

* tag 'iio-for-5.9a-take2' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio: (107 commits)
  iio: buffer: fix attach/detach pollfunc order
  iio: core: remove iio_priv_to_dev() helper
  Replace HTTP links with HTTPS ones: drivers/iio
  Replace HTTP links with HTTPS ones: Documentation/devicetree/bindings/iio
  dt-bindings: iio/adc: Convert ingenic-adc docs to YAML.
  iio: cros_ec_accel_legacy: Add Read Only frequency entries
  MAINTAINERS: adc: at91-sama5d2_adc: remove myself as co-maintainer
  iio: adc: ti_am335x_adc: alloc kfifo & IRQ via devm_ functions
  iio: adc: ti_am335x_adc: alloc channels via devm_kcalloc()
  iio:adc:ingenic: drop of_match_ptr protection and include mod_devicetable.h
  iio:adc:ti-tlc4541: Drop CONFIG_OF and of_match_ptr protections.
  iio:adc:ti-adc161s626: Drop of_match_ptr protection.
  iio:adc:ti-adc084s021: drop of_match_ptr protection
  iio:adc:ti-adc0832: drop CONFIG_OF and of_match_ptr protections
  iio:adc:ti-adc081c: Drop of_match_ptr and change to mod_devicetable.h
  iio:adc:sd_adc_modulator: Drop of_match_ptr and tweak includes
  iio:adc:mcp3422: remove CONFIG_OF and of_match_ptr protections
  iio:adc:mcp320x: Drop CONFIG_OF and of_match_ptr protections
  iio:adc:max1118: Drop CONFIG_OF / of_match_ptr protections
  iio:adc:max11100: Drop of_match_ptr protection / add mod_devicetable.h include
  ...

429 files changed:
Documentation/ABI/testing/sysfs-bus-iio
Documentation/ABI/testing/sysfs-bus-iio-icm42600 [new file with mode: 0644]
Documentation/ABI/testing/sysfs-bus-iio-scd30 [new file with mode: 0644]
Documentation/devicetree/bindings/iio/accel/adi,adxl345.yaml
Documentation/devicetree/bindings/iio/adc/ingenic,adc.txt [deleted file]
Documentation/devicetree/bindings/iio/adc/ingenic,adc.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.txt [deleted file]
Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/iio/chemical/sensirion,scd30.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/iio/dac/ti,dac7612.txt
Documentation/devicetree/bindings/iio/iio-bindings.txt
Documentation/devicetree/bindings/iio/imu/bosch,bmi160.yaml
Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/iio/light/apds9300.txt
Documentation/devicetree/bindings/iio/light/apds9960.txt
Documentation/devicetree/bindings/iio/light/opt3001.txt
Documentation/devicetree/bindings/iio/light/vl6180.txt
Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt [deleted file]
Documentation/devicetree/bindings/iio/magnetometer/asahi-kasei,ak8975.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/iio/magnetometer/bmc150_magn.txt
Documentation/devicetree/bindings/iio/potentiometer/mcp41010.txt
Documentation/devicetree/bindings/iio/potentiostat/lmp91000.txt
Documentation/devicetree/bindings/iio/pressure/asc,dlhl60d.yaml
Documentation/devicetree/bindings/iio/proximity/devantech-srf04.yaml
Documentation/driver-api/generic-counter.rst
Documentation/driver-api/iio/buffers.rst
MAINTAINERS
drivers/counter/104-quad-8.c
drivers/counter/stm32-lptimer-cnt.c
drivers/iio/accel/Kconfig
drivers/iio/accel/Makefile
drivers/iio/accel/adis16201.c
drivers/iio/accel/adis16209.c
drivers/iio/accel/adxl345_core.c
drivers/iio/accel/adxl372.c
drivers/iio/accel/bma180.c
drivers/iio/accel/bma220_spi.c
drivers/iio/accel/bma400_core.c
drivers/iio/accel/bma400_spi.c [new file with mode: 0644]
drivers/iio/accel/bmc150-accel-core.c
drivers/iio/accel/cros_ec_accel_legacy.c
drivers/iio/accel/da280.c
drivers/iio/accel/da311.c
drivers/iio/accel/dmard06.c
drivers/iio/accel/dmard09.c
drivers/iio/accel/dmard10.c
drivers/iio/accel/hid-sensor-accel-3d.c
drivers/iio/accel/kxcjk-1013.c
drivers/iio/accel/kxsd9.c
drivers/iio/accel/mc3230.c
drivers/iio/accel/mma7455_core.c
drivers/iio/accel/mma7660.c
drivers/iio/accel/mma8452.c
drivers/iio/accel/mma9551.c
drivers/iio/accel/mma9553.c
drivers/iio/accel/mxc4005.c
drivers/iio/accel/mxc6255.c
drivers/iio/accel/sca3000.c
drivers/iio/accel/ssp_accel_sensor.c
drivers/iio/accel/st_accel_buffer.c
drivers/iio/accel/stk8312.c
drivers/iio/accel/stk8ba50.c
drivers/iio/adc/Kconfig
drivers/iio/adc/ab8500-gpadc.c
drivers/iio/adc/ad7091r-base.c
drivers/iio/adc/ad7124.c
drivers/iio/adc/ad7192.c
drivers/iio/adc/ad7266.c
drivers/iio/adc/ad7291.c
drivers/iio/adc/ad7292.c
drivers/iio/adc/ad7298.c
drivers/iio/adc/ad7476.c
drivers/iio/adc/ad7606.c
drivers/iio/adc/ad7766.c
drivers/iio/adc/ad7768-1.c
drivers/iio/adc/ad7780.c
drivers/iio/adc/ad7791.c
drivers/iio/adc/ad7793.c
drivers/iio/adc/ad7887.c
drivers/iio/adc/ad7923.c
drivers/iio/adc/ad7949.c
drivers/iio/adc/ad799x.c
drivers/iio/adc/ad_sigma_delta.c
drivers/iio/adc/adi-axi-adc.c
drivers/iio/adc/aspeed_adc.c
drivers/iio/adc/at91-sama5d2_adc.c
drivers/iio/adc/at91_adc.c
drivers/iio/adc/axp20x_adc.c
drivers/iio/adc/axp288_adc.c
drivers/iio/adc/bcm_iproc_adc.c
drivers/iio/adc/berlin2-adc.c
drivers/iio/adc/cc10001_adc.c
drivers/iio/adc/cpcap-adc.c
drivers/iio/adc/da9150-gpadc.c
drivers/iio/adc/dln2-adc.c
drivers/iio/adc/envelope-detector.c
drivers/iio/adc/ep93xx_adc.c
drivers/iio/adc/exynos_adc.c
drivers/iio/adc/fsl-imx25-gcq.c
drivers/iio/adc/hi8435.c
drivers/iio/adc/hx711.c
drivers/iio/adc/imx7d_adc.c
drivers/iio/adc/ina2xx-adc.c
drivers/iio/adc/ingenic-adc.c
drivers/iio/adc/intel_mrfld_adc.c
drivers/iio/adc/lp8788_adc.c
drivers/iio/adc/lpc18xx_adc.c
drivers/iio/adc/lpc32xx_adc.c
drivers/iio/adc/ltc2471.c
drivers/iio/adc/ltc2485.c
drivers/iio/adc/ltc2496.c
drivers/iio/adc/ltc2497-core.c
drivers/iio/adc/ltc2497.c
drivers/iio/adc/max1027.c
drivers/iio/adc/max11100.c
drivers/iio/adc/max1118.c
drivers/iio/adc/max1241.c
drivers/iio/adc/max1363.c
drivers/iio/adc/max9611.c
drivers/iio/adc/mcp320x.c
drivers/iio/adc/mcp3422.c
drivers/iio/adc/mcp3911.c
drivers/iio/adc/men_z188_adc.c
drivers/iio/adc/meson_saradc.c
drivers/iio/adc/mt6577_auxadc.c
drivers/iio/adc/mxs-lradc-adc.c
drivers/iio/adc/nau7802.c
drivers/iio/adc/npcm_adc.c
drivers/iio/adc/palmas_gpadc.c
drivers/iio/adc/qcom-pm8xxx-xoadc.c
drivers/iio/adc/qcom-spmi-adc5.c
drivers/iio/adc/qcom-spmi-iadc.c
drivers/iio/adc/qcom-spmi-vadc.c
drivers/iio/adc/qcom-vadc-common.c
drivers/iio/adc/qcom-vadc-common.h
drivers/iio/adc/rcar-gyroadc.c
drivers/iio/adc/rn5t618-adc.c
drivers/iio/adc/rockchip_saradc.c
drivers/iio/adc/sc27xx_adc.c
drivers/iio/adc/sd_adc_modulator.c
drivers/iio/adc/spear_adc.c
drivers/iio/adc/stm32-adc.c
drivers/iio/adc/stm32-dfsdm-adc.c
drivers/iio/adc/stmpe-adc.c
drivers/iio/adc/stx104.c
drivers/iio/adc/sun4i-gpadc-iio.c
drivers/iio/adc/ti-adc081c.c
drivers/iio/adc/ti-adc0832.c
drivers/iio/adc/ti-adc084s021.c
drivers/iio/adc/ti-adc108s102.c
drivers/iio/adc/ti-adc12138.c
drivers/iio/adc/ti-adc128s052.c
drivers/iio/adc/ti-adc161s626.c
drivers/iio/adc/ti-ads1015.c
drivers/iio/adc/ti-ads124s08.c
drivers/iio/adc/ti-ads7950.c
drivers/iio/adc/ti-ads8344.c
drivers/iio/adc/ti-ads8688.c
drivers/iio/adc/ti-tlc4541.c
drivers/iio/adc/ti_am335x_adc.c
drivers/iio/adc/twl4030-madc.c
drivers/iio/adc/twl6030-gpadc.c
drivers/iio/adc/vf610_adc.c
drivers/iio/adc/viperboard_adc.c
drivers/iio/adc/xilinx-xadc-core.c
drivers/iio/afe/iio-rescale.c
drivers/iio/amplifiers/ad8366.c
drivers/iio/amplifiers/hmc425a.c
drivers/iio/buffer/industrialio-triggered-buffer.c
drivers/iio/chemical/Kconfig
drivers/iio/chemical/Makefile
drivers/iio/chemical/ams-iaq-core.c
drivers/iio/chemical/atlas-ezo-sensor.c
drivers/iio/chemical/atlas-sensor.c
drivers/iio/chemical/bme680_core.c
drivers/iio/chemical/ccs811.c
drivers/iio/chemical/pms7003.c
drivers/iio/chemical/scd30.h [new file with mode: 0644]
drivers/iio/chemical/scd30_core.c [new file with mode: 0644]
drivers/iio/chemical/scd30_i2c.c [new file with mode: 0644]
drivers/iio/chemical/scd30_serial.c [new file with mode: 0644]
drivers/iio/chemical/sgp30.c
drivers/iio/chemical/sps30.c
drivers/iio/chemical/vz89x.c
drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
drivers/iio/common/st_sensors/st_sensors_i2c.c
drivers/iio/common/st_sensors/st_sensors_spi.c
drivers/iio/dac/ad5064.c
drivers/iio/dac/ad5360.c
drivers/iio/dac/ad5380.c
drivers/iio/dac/ad5421.c
drivers/iio/dac/ad5446.c
drivers/iio/dac/ad5449.c
drivers/iio/dac/ad5504.c
drivers/iio/dac/ad5592r-base.c
drivers/iio/dac/ad5624r_spi.c
drivers/iio/dac/ad5686.c
drivers/iio/dac/ad5755.c
drivers/iio/dac/ad5758.c
drivers/iio/dac/ad5761.c
drivers/iio/dac/ad5764.c
drivers/iio/dac/ad5770r.c
drivers/iio/dac/ad5791.c
drivers/iio/dac/ad7303.c
drivers/iio/dac/ad8801.c
drivers/iio/dac/cio-dac.c
drivers/iio/dac/dpot-dac.c
drivers/iio/dac/ds4424.c
drivers/iio/dac/lpc18xx_dac.c
drivers/iio/dac/ltc1660.c
drivers/iio/dac/ltc2632.c
drivers/iio/dac/m62332.c
drivers/iio/dac/max517.c
drivers/iio/dac/max5821.c
drivers/iio/dac/mcp4725.c
drivers/iio/dac/mcp4922.c
drivers/iio/dac/stm32-dac.c
drivers/iio/dac/ti-dac082s085.c
drivers/iio/dac/ti-dac5571.c
drivers/iio/dac/ti-dac7311.c
drivers/iio/dac/ti-dac7612.c
drivers/iio/dac/vf610_dac.c
drivers/iio/dummy/iio_simple_dummy.c
drivers/iio/dummy/iio_simple_dummy_buffer.c
drivers/iio/frequency/ad9523.c
drivers/iio/frequency/adf4350.c
drivers/iio/frequency/adf4371.c
drivers/iio/gyro/adis16080.c
drivers/iio/gyro/adis16130.c
drivers/iio/gyro/adis16136.c
drivers/iio/gyro/adis16260.c
drivers/iio/gyro/adxrs450.c
drivers/iio/gyro/bmg160_core.c
drivers/iio/gyro/fxas21002c_core.c
drivers/iio/gyro/hid-sensor-gyro-3d.c
drivers/iio/gyro/itg3200_core.c
drivers/iio/gyro/mpu3050-core.c
drivers/iio/gyro/ssp_gyro_sensor.c
drivers/iio/gyro/st_gyro_buffer.c
drivers/iio/health/afe4403.c
drivers/iio/health/afe4404.c
drivers/iio/health/afe440x.h
drivers/iio/health/max30100.c
drivers/iio/health/max30102.c
drivers/iio/humidity/am2315.c
drivers/iio/humidity/dht11.c
drivers/iio/humidity/hdc100x.c
drivers/iio/humidity/hid-sensor-humidity.c
drivers/iio/humidity/hts221.h
drivers/iio/humidity/hts221_buffer.c
drivers/iio/humidity/hts221_core.c
drivers/iio/humidity/htu21.c
drivers/iio/humidity/si7005.c
drivers/iio/humidity/si7020.c
drivers/iio/iio_core_trigger.h
drivers/iio/imu/Kconfig
drivers/iio/imu/Makefile
drivers/iio/imu/adis16400.c
drivers/iio/imu/adis16460.c
drivers/iio/imu/adis16475.c
drivers/iio/imu/adis16480.c
drivers/iio/imu/bmi160/bmi160.h
drivers/iio/imu/bmi160/bmi160_core.c
drivers/iio/imu/fxos8700_core.c
drivers/iio/imu/inv_icm42600/Kconfig [new file with mode: 0644]
drivers/iio/imu/inv_icm42600/Makefile [new file with mode: 0644]
drivers/iio/imu/inv_icm42600/inv_icm42600.h [new file with mode: 0644]
drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c [new file with mode: 0644]
drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c [new file with mode: 0644]
drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h [new file with mode: 0644]
drivers/iio/imu/inv_icm42600/inv_icm42600_core.c [new file with mode: 0644]
drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c [new file with mode: 0644]
drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c [new file with mode: 0644]
drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c [new file with mode: 0644]
drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c [new file with mode: 0644]
drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h [new file with mode: 0644]
drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c [new file with mode: 0644]
drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h [new file with mode: 0644]
drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
drivers/iio/imu/kmx61.c
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c
drivers/iio/industrialio-buffer.c
drivers/iio/industrialio-core.c
drivers/iio/industrialio-event.c
drivers/iio/industrialio-trigger.c
drivers/iio/light/acpi-als.c
drivers/iio/light/adjd_s311.c
drivers/iio/light/adux1020.c
drivers/iio/light/al3010.c
drivers/iio/light/al3320a.c
drivers/iio/light/apds9300.c
drivers/iio/light/apds9960.c
drivers/iio/light/bh1750.c
drivers/iio/light/bh1780.c
drivers/iio/light/cm32181.c
drivers/iio/light/cm3232.c
drivers/iio/light/cm3323.c
drivers/iio/light/cm3605.c
drivers/iio/light/cm36651.c
drivers/iio/light/cros_ec_light_prox.c
drivers/iio/light/gp2ap002.c
drivers/iio/light/gp2ap020a00f.c
drivers/iio/light/hid-sensor-als.c
drivers/iio/light/hid-sensor-prox.c
drivers/iio/light/iqs621-als.c
drivers/iio/light/isl29018.c
drivers/iio/light/isl29028.c
drivers/iio/light/isl29125.c
drivers/iio/light/jsa1212.c
drivers/iio/light/lm3533-als.c
drivers/iio/light/ltr501.c
drivers/iio/light/lv0104cs.c
drivers/iio/light/max44000.c
drivers/iio/light/max44009.c
drivers/iio/light/noa1305.c
drivers/iio/light/opt3001.c
drivers/iio/light/pa12203001.c
drivers/iio/light/rpr0521.c
drivers/iio/light/si1133.c
drivers/iio/light/si1145.c
drivers/iio/light/st_uvis25_core.c
drivers/iio/light/stk3310.c
drivers/iio/light/tcs3414.c
drivers/iio/light/tcs3472.c
drivers/iio/light/tsl2563.c
drivers/iio/light/tsl2583.c
drivers/iio/light/tsl2772.c
drivers/iio/light/tsl4531.c
drivers/iio/light/us5182d.c
drivers/iio/light/vcnl4000.c
drivers/iio/light/vcnl4035.c
drivers/iio/light/veml6030.c
drivers/iio/light/veml6070.c
drivers/iio/light/vl6180.c
drivers/iio/light/zopt2201.c
drivers/iio/magnetometer/ak8974.c
drivers/iio/magnetometer/ak8975.c
drivers/iio/magnetometer/bmc150_magn.c
drivers/iio/magnetometer/bmc150_magn_i2c.c
drivers/iio/magnetometer/hid-sensor-magn-3d.c
drivers/iio/magnetometer/hmc5843_core.c
drivers/iio/magnetometer/mag3110.c
drivers/iio/magnetometer/mmc35240.c
drivers/iio/magnetometer/rm3100-core.c
drivers/iio/magnetometer/st_magn_buffer.c
drivers/iio/multiplexer/iio-mux.c
drivers/iio/orientation/hid-sensor-incl-3d.c
drivers/iio/orientation/hid-sensor-rotation.c
drivers/iio/position/iqs624-pos.c
drivers/iio/potentiometer/ad5272.c
drivers/iio/potentiometer/ds1803.c
drivers/iio/potentiometer/max5432.c
drivers/iio/potentiometer/max5481.c
drivers/iio/potentiometer/max5487.c
drivers/iio/potentiometer/mcp4018.c
drivers/iio/potentiometer/mcp41010.c
drivers/iio/potentiometer/mcp4131.c
drivers/iio/potentiometer/mcp4531.c
drivers/iio/potentiometer/tpl0102.c
drivers/iio/potentiostat/lmp91000.c
drivers/iio/pressure/abp060mg.c
drivers/iio/pressure/bmp280-core.c
drivers/iio/pressure/cros_ec_baro.c
drivers/iio/pressure/dlhl60d.c
drivers/iio/pressure/dps310.c
drivers/iio/pressure/hid-sensor-press.c
drivers/iio/pressure/hp03.c
drivers/iio/pressure/hp206c.c
drivers/iio/pressure/icp10100.c
drivers/iio/pressure/mpl115.c
drivers/iio/pressure/mpl3115.c
drivers/iio/pressure/ms5611_core.c
drivers/iio/pressure/ms5637.c
drivers/iio/pressure/st_pressure_buffer.c
drivers/iio/pressure/t5403.c
drivers/iio/pressure/zpa2326.c
drivers/iio/proximity/as3935.c
drivers/iio/proximity/isl29501.c
drivers/iio/proximity/mb1232.c
drivers/iio/proximity/ping.c
drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
drivers/iio/proximity/rfd77402.c
drivers/iio/proximity/srf04.c
drivers/iio/proximity/srf08.c
drivers/iio/proximity/sx9310.c
drivers/iio/proximity/sx9500.c
drivers/iio/proximity/vcnl3020.c
drivers/iio/proximity/vl53l0x-i2c.c
drivers/iio/resolver/ad2s1200.c
drivers/iio/resolver/ad2s90.c
drivers/iio/temperature/hid-sensor-temperature.c
drivers/iio/temperature/iqs620at-temp.c
drivers/iio/temperature/ltc2983.c
drivers/iio/temperature/max31856.c
drivers/iio/temperature/maxim_thermocouple.c
drivers/iio/temperature/mlx90614.c
drivers/iio/temperature/mlx90632.c
drivers/iio/temperature/tmp006.c
drivers/iio/temperature/tmp007.c
drivers/iio/temperature/tsys01.c
drivers/iio/temperature/tsys02d.c
drivers/iio/trigger/stm32-timer-trigger.c
drivers/input/touchscreen/tsc2007_iio.c
drivers/platform/x86/toshiba_acpi.c
drivers/staging/iio/Documentation/device.txt
drivers/staging/iio/accel/adis16203.c
drivers/staging/iio/accel/adis16240.c
drivers/staging/iio/adc/ad7280a.c
drivers/staging/iio/adc/ad7816.c
drivers/staging/iio/addac/adt7316.c
drivers/staging/iio/cdc/ad7150.c
drivers/staging/iio/cdc/ad7746.c
drivers/staging/iio/frequency/ad9832.c
drivers/staging/iio/frequency/ad9834.c
drivers/staging/iio/impedance-analyzer/ad5933.c
drivers/staging/iio/resolver/ad2s1210.c
include/dt-bindings/iio/qcom,spmi-adc7-pm8350.h [new file with mode: 0644]
include/dt-bindings/iio/qcom,spmi-adc7-pm8350b.h [new file with mode: 0644]
include/dt-bindings/iio/qcom,spmi-adc7-pmk8350.h [new file with mode: 0644]
include/dt-bindings/iio/qcom,spmi-adc7-pmr735a.h [new file with mode: 0644]
include/dt-bindings/iio/qcom,spmi-adc7-pmr735b.h [new file with mode: 0644]
include/dt-bindings/iio/qcom,spmi-vadc.h
include/linux/iio/common/cros_ec_sensors_core.h
include/linux/iio/iio-opaque.h [new file with mode: 0644]
include/linux/iio/iio.h
include/linux/iio/trigger_consumer.h

index d3e53a6..5c62bfb 100644 (file)
@@ -1569,7 +1569,8 @@ What:             /sys/bus/iio/devices/iio:deviceX/in_concentrationX_voc_raw
 KernelVersion: 4.3
 Contact:       linux-iio@vger.kernel.org
 Description:
-               Raw (unscaled no offset etc.) percentage reading of a substance.
+               Raw (unscaled no offset etc.) reading of a substance. Units
+               after application of scale and offset are percents.
 
 What:          /sys/bus/iio/devices/iio:deviceX/in_resistance_raw
 What:          /sys/bus/iio/devices/iio:deviceX/in_resistanceX_raw
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-icm42600 b/Documentation/ABI/testing/sysfs-bus-iio-icm42600
new file mode 100644 (file)
index 0000000..0bf1fd4
--- /dev/null
@@ -0,0 +1,20 @@
+What:          /sys/bus/iio/devices/iio:deviceX/in_accel_x_calibbias
+What:          /sys/bus/iio/devices/iio:deviceX/in_accel_y_calibbias
+What:          /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibbias
+What:          /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibbias
+What:          /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibbias
+What:          /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibbias
+KernelVersion:  5.8
+Contact:        linux-iio@vger.kernel.org
+Description:
+               Hardware applied calibration offset (assumed to fix production
+               inaccuracies). Values represent a real physical offset expressed
+               in SI units (m/s^2 for accelerometer and rad/s for gyroscope).
+
+What:          /sys/bus/iio/devices/iio:deviceX/in_accel_calibbias_available
+What:          /sys/bus/iio/devices/iio:deviceX/in_anglvel_calibbias_available
+KernelVersion:  5.8
+Contact:        linux-iio@vger.kernel.org
+Description:
+               Range of available values for hardware offset. Values in SI
+               units (m/s^2 for accelerometer and rad/s for gyroscope).
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-scd30 b/Documentation/ABI/testing/sysfs-bus-iio-scd30
new file mode 100644 (file)
index 0000000..b9712f3
--- /dev/null
@@ -0,0 +1,34 @@
+What:          /sys/bus/iio/devices/iio:deviceX/calibration_auto_enable
+Date:          June 2020
+KernelVersion: 5.8
+Contact:       linux-iio@vger.kernel.org
+Description:
+               Contaminants build-up in the measurement chamber or optical
+               elements deterioration leads to sensor drift.
+
+               One can compensate for sensor drift by using automatic self
+               calibration procedure (asc).
+
+               Writing 1 or 0 to this attribute will respectively activate or
+               deactivate asc.
+
+               Upon reading current asc status is returned.
+
+What:          /sys/bus/iio/devices/iio:deviceX/calibration_forced_value
+Date:          June 2020
+KernelVersion: 5.8
+Contact:       linux-iio@vger.kernel.org
+Description:
+               Contaminants build-up in the measurement chamber or optical
+               elements deterioration leads to sensor drift.
+
+               One can compensate for sensor drift by using forced
+               recalibration (frc). This is useful in case there's known
+               co2 reference available nearby the sensor.
+
+               Picking value from the range [400 1 2000] and writing it to the
+               sensor will set frc.
+
+               Upon reading current frc value is returned. Note that after
+               power cycling default value (i.e 400) is returned even though
+               internally sensor had recalibrated itself.
index d124eba..fd4eaa3 100644 (file)
@@ -12,8 +12,8 @@ maintainers:
 description: |
   Analog Devices ADXL345/ADXL375 3-Axis Digital Accelerometers that supports
   both I2C & SPI interfaces.
-    http://www.analog.com/en/products/mems/accelerometers/adxl345.html
-    http://www.analog.com/en/products/sensors-mems/accelerometers/adxl375.html
+    https://www.analog.com/en/products/mems/accelerometers/adxl345.html
+    https://www.analog.com/en/products/sensors-mems/accelerometers/adxl375.html
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/iio/adc/ingenic,adc.txt b/Documentation/devicetree/bindings/iio/adc/ingenic,adc.txt
deleted file mode 100644 (file)
index cd9048c..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-* Ingenic JZ47xx ADC controller IIO bindings
-
-Required properties:
-
-- compatible: Should be one of:
-  * ingenic,jz4725b-adc
-  * ingenic,jz4740-adc
-  * ingenic,jz4770-adc
-- reg: ADC controller registers location and length.
-- clocks: phandle to the SoC's ADC clock.
-- clock-names: Must be set to "adc".
-- #io-channel-cells: Must be set to <1> to indicate channels are selected
-  by index.
-
-ADC clients must use the format described in iio-bindings.txt, giving
-a phandle and IIO specifier pair ("io-channels") to the ADC controller.
-
-Example:
-
-#include <dt-bindings/iio/adc/ingenic,adc.h>
-
-adc: adc@10070000 {
-       compatible = "ingenic,jz4740-adc";
-       #io-channel-cells = <1>;
-
-       reg = <0x10070000 0x30>;
-
-       clocks = <&cgu JZ4740_CLK_ADC>;
-       clock-names = "adc";
-
-       interrupt-parent = <&intc>;
-       interrupts = <18>;
-};
-
-adc-keys {
-       ...
-       compatible = "adc-keys";
-       io-channels = <&adc INGENIC_ADC_AUX>;
-       io-channel-names = "buttons";
-       ...
-};
-
-battery {
-       ...
-       compatible = "ingenic,jz4740-battery";
-       io-channels = <&adc INGENIC_ADC_BATTERY>;
-       io-channel-names = "battery";
-       ...
-};
diff --git a/Documentation/devicetree/bindings/iio/adc/ingenic,adc.yaml b/Documentation/devicetree/bindings/iio/adc/ingenic,adc.yaml
new file mode 100644 (file)
index 0000000..9f414db
--- /dev/null
@@ -0,0 +1,71 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2019-2020 Artur Rojek
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/iio/adc/ingenic,adc.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Ingenic JZ47xx ADC controller IIO bindings
+
+maintainers:
+  - Artur Rojek <contact@artur-rojek.eu>
+
+description: >
+  Industrial I/O subsystem bindings for ADC controller found in
+  Ingenic JZ47xx SoCs.
+
+  ADC clients must use the format described in iio-bindings.txt, giving
+  a phandle and IIO specifier pair ("io-channels") to the ADC controller.
+
+properties:
+  compatible:
+    enum:
+      - ingenic,jz4725b-adc
+      - ingenic,jz4740-adc
+      - ingenic,jz4770-adc
+
+  '#io-channel-cells':
+    const: 1
+    description:
+      Must be set to <1> to indicate channels are selected by index.
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    items:
+      - const: adc
+
+  interrupts:
+    maxItems: 1
+
+required:
+  - compatible
+  - '#io-channel-cells'
+  - reg
+  - clocks
+  - clock-names
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/jz4740-cgu.h>
+    #include <dt-bindings/iio/adc/ingenic,adc.h>
+
+    adc@10070000 {
+            compatible = "ingenic,jz4740-adc";
+            #io-channel-cells = <1>;
+
+            reg = <0x10070000 0x30>;
+
+            clocks = <&cgu JZ4740_CLK_ADC>;
+            clock-names = "adc";
+
+            interrupt-parent = <&intc>;
+            interrupts = <18>;
+    };
diff --git a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.txt b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.txt
deleted file mode 100644 (file)
index c878768..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-Qualcomm's SPMI PMIC ADC
-
-- SPMI PMIC voltage ADC (VADC) provides interface to clients to read
-  voltage. The VADC is a 15-bit sigma-delta ADC.
-- SPMI PMIC5 voltage ADC (ADC) provides interface to clients to read
-  voltage. The VADC is a 16-bit sigma-delta ADC.
-
-VADC node:
-
-- compatible:
-    Usage: required
-    Value type: <string>
-    Definition: Should contain "qcom,spmi-vadc".
-                Should contain "qcom,spmi-adc5" for PMIC5 ADC driver.
-                Should contain "qcom,spmi-adc-rev2" for PMIC rev2 ADC driver.
-                Should contain "qcom,pms405-adc" for PMS405 PMIC
-
-- reg:
-    Usage: required
-    Value type: <prop-encoded-array>
-    Definition: VADC base address in the SPMI PMIC register map.
-
-- #address-cells:
-    Usage: required
-    Value type: <u32>
-    Definition: Must be one. Child node 'reg' property should define ADC
-            channel number.
-
-- #size-cells:
-    Usage: required
-    Value type: <u32>
-    Definition: Must be zero.
-
-- #io-channel-cells:
-    Usage: required
-    Value type: <u32>
-    Definition: Must be one. For details about IIO bindings see:
-            Documentation/devicetree/bindings/iio/iio-bindings.txt
-
-- interrupts:
-    Usage: optional
-    Value type: <prop-encoded-array>
-    Definition: End of conversion interrupt.
-
-Channel node properties:
-
-- reg:
-    Usage: required
-    Value type: <u32>
-    Definition: ADC channel number.
-            See include/dt-bindings/iio/qcom,spmi-vadc.h
-
-- label:
-    Usage: required for "qcom,spmi-adc5" and "qcom,spmi-adc-rev2"
-    Value type: <empty>
-    Definition: ADC input of the platform as seen in the schematics.
-            For thermistor inputs connected to generic AMUX or GPIO inputs
-            these can vary across platform for the same pins. Hence select
-            the platform schematics name for this channel.
-
-- qcom,decimation:
-    Usage: optional
-    Value type: <u32>
-    Definition: This parameter is used to decrease ADC sampling rate.
-            Quicker measurements can be made by reducing decimation ratio.
-            - For compatible property "qcom,spmi-vadc", valid values are
-              512, 1024, 2048, 4096. If property is not found, default value
-              of 512 will be used.
-            - For compatible property "qcom,spmi-adc5", valid values are 250, 420
-              and 840. If property is not found, default value of 840 is used.
-            - For compatible property "qcom,spmi-adc-rev2", valid values are 256,
-              512 and 1024. If property is not present, default value is 1024.
-
-- qcom,pre-scaling:
-    Usage: optional
-    Value type: <u32 array>
-    Definition: Used for scaling the channel input signal before the signal is
-            fed to VADC. The configuration for this node is to know the
-            pre-determined ratio and use it for post scaling. Select one from
-            the following options.
-            <1 1>, <1 3>, <1 4>, <1 6>, <1 20>, <1 8>, <10 81>, <1 10>
-            If property is not found default value depending on chip will be used.
-
-- qcom,ratiometric:
-    Usage: optional
-    Value type: <empty>
-    Definition: Channel calibration type.
-            - For compatible property "qcom,spmi-vadc", if this property is
-              specified VADC will use the VDD reference (1.8V) and GND for
-              channel calibration. If property is not found, channel will be
-              calibrated with 0.625V and 1.25V reference channels, also
-              known as absolute calibration.
-            - For compatible property "qcom,spmi-adc5" and "qcom,spmi-adc-rev2",
-              if this property is specified VADC will use the VDD reference
-              (1.875V) and GND for channel calibration. If property is not found,
-              channel will be calibrated with 0V and 1.25V reference channels,
-              also known as absolute calibration.
-
-- qcom,hw-settle-time:
-    Usage: optional
-    Value type: <u32>
-    Definition: Time between AMUX getting configured and the ADC starting
-            conversion. The 'hw_settle_time' is an index used from valid values
-            and programmed in hardware to achieve the hardware settling delay.
-            - For compatible property "qcom,spmi-vadc" and "qcom,spmi-adc-rev2",
-              Delay = 100us * (hw_settle_time) for hw_settle_time < 11,
-              and 2ms * (hw_settle_time - 10) otherwise.
-              Valid values are: 0, 100, 200, 300, 400, 500, 600, 700, 800,
-              900 us and 1, 2, 4, 6, 8, 10 ms.
-              If property is not found, channel will use 0us.
-            - For compatible property "qcom,spmi-adc5", delay = 15us for
-              value 0, 100us * (value) for values < 11,
-              and 2ms * (value - 10) otherwise.
-              Valid values are: 15, 100, 200, 300, 400, 500, 600, 700, 800,
-              900 us and 1, 2, 4, 6, 8, 10 ms
-              Certain controller digital versions have valid values of
-              15, 100, 200, 300, 400, 500, 600, 700, 1, 2, 4, 8, 16, 32, 64, 128 ms
-              If property is not found, channel will use 15us.
-
-- qcom,avg-samples:
-    Usage: optional
-    Value type: <u32>
-    Definition: Number of samples to be used for measurement.
-            Averaging provides the option to obtain a single measurement
-            from the ADC that is an average of multiple samples. The value
-            selected is 2^(value).
-            - For compatible property "qcom,spmi-vadc", valid values
-              are: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512
-              If property is not found, 1 sample will be used.
-            - For compatible property "qcom,spmi-adc5" and "qcom,spmi-adc-rev2",
-              valid values are: 1, 2, 4, 8, 16
-              If property is not found, 1 sample will be used.
-
-NOTE:
-
-For compatible property "qcom,spmi-vadc" following channels, also known as
-reference point channels, are used for result calibration and their channel
-configuration nodes should be defined:
-VADC_REF_625MV and/or VADC_SPARE1(based on PMIC version) VADC_REF_1250MV,
-VADC_GND_REF and VADC_VDD_VADC.
-
-Example:
-
-#include <dt-bindings/iio/qcom,spmi-vadc.h>
-#include <linux/irq.h>
-/* ... */
-
-       /* VADC node */
-       pmic_vadc: vadc@3100 {
-               compatible = "qcom,spmi-vadc";
-               reg = <0x3100>;
-               interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-               #io-channel-cells = <1>;
-               io-channel-ranges;
-
-               /* Channel node */
-               adc-chan@VADC_LR_MUX10_USB_ID {
-                       reg = <VADC_LR_MUX10_USB_ID>;
-                       qcom,decimation = <512>;
-                       qcom,ratiometric;
-                       qcom,hw-settle-time = <200>;
-                       qcom,avg-samples = <1>;
-                       qcom,pre-scaling = <1 3>;
-               };
-       };
-
-       /* IIO client node */
-       usb {
-               io-channels = <&pmic_vadc VADC_LR_MUX10_USB_ID>;
-               io-channel-names = "vadc";
-       };
diff --git a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml
new file mode 100644 (file)
index 0000000..e6263b6
--- /dev/null
@@ -0,0 +1,278 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/qcom,spmi-vadc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm's SPMI PMIC ADC
+
+maintainers:
+  - Andy Gross <agross@kernel.org>
+  - Bjorn Andersson <bjorn.andersson@linaro.org>
+
+description: |
+  SPMI PMIC voltage ADC (VADC) provides interface to clients to read
+  voltage. The VADC is a 15-bit sigma-delta ADC.
+  SPMI PMIC5/PMIC7 voltage ADC (ADC) provides interface to clients to read
+  voltage. The VADC is a 16-bit sigma-delta ADC.
+
+properties:
+  compatible:
+    oneOf:
+      - items:
+          - const: qcom,pms405-adc
+          - const: qcom,spmi-adc-rev2
+
+      - items:
+        - enum:
+          - qcom,spmi-vadc
+          - qcom,spmi-adc5
+          - qcom,spmi-adc-rev2
+          - qcom,spmi-adc7
+
+  reg:
+    description: VADC base address in the SPMI PMIC register map
+    maxItems: 1
+
+  '#address-cells':
+    const: 1
+
+  '#size-cells':
+    const: 0
+
+  '#io-channel-cells':
+    const: 1
+
+  interrupts:
+    maxItems: 1
+    description:
+      End of conversion interrupt.
+
+required:
+  - compatible
+  - reg
+  - '#address-cells'
+  - '#size-cells'
+  - '#io-channel-cells'
+
+patternProperties:
+  "^.*@[0-9a-f]+$":
+    type: object
+    description: |
+      Represents the external channels which are connected to the ADC.
+      For compatible property "qcom,spmi-vadc" following channels, also known as
+      reference point channels, are used for result calibration and their channel
+      configuration nodes should be defined:
+      VADC_REF_625MV and/or VADC_SPARE1(based on PMIC version) VADC_REF_1250MV,
+      VADC_GND_REF and VADC_VDD_VADC.
+
+    properties:
+      reg:
+        description: |
+          ADC channel number.
+          See include/dt-bindings/iio/qcom,spmi-vadc.h
+          For PMIC7 ADC, the channel numbers are specified separately per PMIC
+          in the PMIC-specific files in include/dt-bindings/iio/.
+
+      label:
+        $ref: /schemas/types.yaml#/definitions/string
+        description: |
+            ADC input of the platform as seen in the schematics.
+            For thermistor inputs connected to generic AMUX or GPIO inputs
+            these can vary across platform for the same pins. Hence select
+            the platform schematics name for this channel.
+
+      qcom,decimation:
+        $ref: /schemas/types.yaml#/definitions/uint32
+        description: |
+            This parameter is used to decrease ADC sampling rate.
+            Quicker measurements can be made by reducing decimation ratio.
+
+      qcom,pre-scaling:
+        description: |
+            Used for scaling the channel input signal before the signal is
+            fed to VADC. The configuration for this node is to know the
+            pre-determined ratio and use it for post scaling. It is a pair of
+            integers, denoting the numerator and denominator of the fraction by which
+            input signal is multiplied. For example, <1 3> indicates the signal is scaled
+            down to 1/3 of its value before ADC measurement.
+            If property is not found default value depending on chip will be used.
+        allOf:
+          - $ref: /schemas/types.yaml#/definitions/uint32-array
+        oneOf:
+          - items:
+            - const: 1
+            - enum: [ 1, 3, 4, 6, 20, 8, 10 ]
+
+          - items:
+            - const: 10
+            - const: 81
+
+      qcom,ratiometric:
+        description: |
+            Channel calibration type.
+            - For compatible property "qcom,spmi-vadc", if this property is
+              specified VADC will use the VDD reference (1.8V) and GND for
+              channel calibration. If property is not found, channel will be
+              calibrated with 0.625V and 1.25V reference channels, also
+              known as absolute calibration.
+            - For compatible property "qcom,spmi-adc5", "qcom,spmi-adc7" and
+              "qcom,spmi-adc-rev2", if this property is specified VADC will use
+              the VDD reference (1.875V) and GND for channel calibration. If
+              property is not found, channel will be calibrated with 0V and 1.25V
+              reference channels, also known as absolute calibration.
+        type: boolean
+
+      qcom,hw-settle-time:
+        $ref: /schemas/types.yaml#/definitions/uint32
+        description: |
+            Time between AMUX getting configured and the ADC starting
+            conversion. The 'hw_settle_time' is an index used from valid values
+            and programmed in hardware to achieve the hardware settling delay.
+
+      qcom,avg-samples:
+        $ref: /schemas/types.yaml#/definitions/uint32
+        description: |
+            Number of samples to be used for measurement.
+            Averaging provides the option to obtain a single measurement
+            from the ADC that is an average of multiple samples. The value
+            selected is 2^(value).
+
+    required:
+      - reg
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: qcom,spmi-vadc
+
+    then:
+      patternProperties:
+        "^.*@[0-9a-f]+$":
+          properties:
+            qcom,decimation:
+              enum: [ 512, 1024, 2048, 4096 ]
+              default: 512
+
+            qcom,hw-settle-time:
+              enum: [ 0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1, 2,
+                      4, 6, 8, 10 ]
+              default: 0
+
+            qcom,avg-samples:
+              enum: [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 ]
+              default: 1
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: qcom,spmi-adc-rev2
+
+    then:
+      patternProperties:
+        "^.*@[0-9a-f]+$":
+          properties:
+            qcom,decimation:
+              enum: [ 256, 512, 1024 ]
+              default: 1024
+
+            qcom,hw-settle-time:
+              enum: [ 0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1, 2,
+                      4, 6, 8, 10 ]
+              default: 0
+
+            qcom,avg-samples:
+              enum: [ 1, 2, 4, 8, 16 ]
+              default: 1
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: qcom,spmi-adc5
+
+    then:
+      patternProperties:
+        "^.*@[0-9a-f]+$":
+          properties:
+            qcom,decimation:
+              enum: [ 250, 420, 840 ]
+              default: 840
+
+            qcom,hw-settle-time:
+              enum: [ 15, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1, 2,
+                      4, 6, 8, 10, 16, 32, 64, 128 ]
+              default: 15
+
+            qcom,avg-samples:
+              enum: [ 1, 2, 4, 8, 16 ]
+              default: 1
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: qcom,spmi-adc7
+
+    then:
+      patternProperties:
+        "^.*@[0-9a-f]+$":
+          properties:
+            qcom,decimation:
+              enum: [ 85, 340, 1360 ]
+              default: 1360
+
+            qcom,hw-settle-time:
+              enum: [ 15, 100, 200, 300, 400, 500, 600, 700, 1000, 2000, 4000,
+                      8000, 16000, 32000, 64000, 128000 ]
+              default: 15
+
+            qcom,avg-samples:
+              enum: [ 1, 2, 4, 8, 16 ]
+              default: 1
+
+examples:
+  - |
+    spmi_bus {
+      #address-cells = <1>;
+      #size-cells = <0>;
+      /* VADC node */
+      pmic_vadc: adc@3100 {
+        compatible = "qcom,spmi-vadc";
+        reg = <0x3100>;
+        interrupts = <0x0 0x31 0x0 0x1>;
+        #address-cells = <1>;
+        #size-cells = <0>;
+        #io-channel-cells = <1>;
+        io-channel-ranges;
+
+        /* Channel node */
+        adc-chan@39 {
+          reg = <0x39>;
+          qcom,decimation = <512>;
+          qcom,ratiometric;
+          qcom,hw-settle-time = <200>;
+          qcom,avg-samples = <1>;
+          qcom,pre-scaling = <1 3>;
+        };
+
+        adc-chan@9 {
+          reg = <0x9>;
+        };
+
+        adc-chan@a {
+          reg = <0xa>;
+        };
+
+        adc-chan@e {
+          reg = <0xe>;
+        };
+
+        adc-chan@f {
+          reg = <0xf>;
+        };
+      };
+    };
diff --git a/Documentation/devicetree/bindings/iio/chemical/sensirion,scd30.yaml b/Documentation/devicetree/bindings/iio/chemical/sensirion,scd30.yaml
new file mode 100644 (file)
index 0000000..40d8734
--- /dev/null
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/chemical/sensirion,scd30.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Sensirion SCD30 carbon dioxide sensor
+
+maintainers:
+  - Tomasz Duszynski <tomasz.duszynski@octakon.com>
+
+description: |
+  Air quality sensor capable of measuring co2 concentration, temperature
+  and relative humidity.
+
+properties:
+  compatible:
+    enum:
+      - sensirion,scd30
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  vdd-supply: true
+
+  sensirion,sel-gpios:
+    description: GPIO connected to the SEL line
+    maxItems: 1
+
+  sensirion,pwm-gpios:
+    description: GPIO connected to the PWM line
+    maxItems: 1
+
+required:
+  - compatible
+
+additionalProperties: false
+
+examples:
+  - |
+    # include <dt-bindings/interrupt-controller/irq.h>
+    i2c {
+      #address-cells = <1>;
+      #size-cells = <0>;
+
+      co2-sensor@61 {
+        compatible = "sensirion,scd30";
+        reg = <0x61>;
+        vdd-supply = <&vdd>;
+        interrupt-parent = <&gpio0>;
+        interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+      };
+    };
+  - |
+    # include <dt-bindings/interrupt-controller/irq.h>
+    serial {
+      co2-sensor {
+        compatible = "sensirion,scd30";
+        vdd-supply = <&vdd>;
+        interrupt-parent = <&gpio0>;
+        interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+      };
+    };
+
+...
index 639c94e..17af395 100644 (file)
@@ -6,7 +6,7 @@ Is is programmable through an SPI interface.
 
 The internal DACs are loaded when the LOADDACS pin is pulled down.
 
-http://www.ti.com/lit/ds/sbas106/sbas106.pdf
+https://www.ti.com/lit/ds/sbas106/sbas106.pdf
 
 Required Properties:
 - compatible: Should be one of:
index af33267..aa63cac 100644 (file)
@@ -9,7 +9,7 @@ specifier is an array of one or more cells identifying the IIO
 output on a device. The length of an IIO specifier is defined by the
 value of a #io-channel-cells property in the IIO provider node.
 
-[1] http://marc.info/?l=linux-iio&m=135902119507483&w=2
+[1] https://marc.info/?l=linux-iio&m=135902119507483&w=2
 
 ==IIO providers==
 
index 0d0ef84..33d8e9f 100644 (file)
@@ -37,6 +37,15 @@ properties:
       set if the specified interrupt pin should be configured as
       open drain. If not set, defaults to push-pull.
 
+  vdd-supply:
+    description: provide VDD power to the sensor.
+
+  vddio-supply:
+    description: provide VDD IO power to the sensor.
+
+  mount-matrix:
+    description: an optional 3x3 mounting rotation matrix
+
 required:
   - compatible
   - reg
@@ -52,9 +61,14 @@ examples:
         bmi160@68 {
                 compatible = "bosch,bmi160";
                 reg = <0x68>;
+                vdd-supply = <&pm8916_l17>;
+                vddio-supply = <&pm8916_l6>;
                 interrupt-parent = <&gpio4>;
                 interrupts = <12 IRQ_TYPE_EDGE_RISING>;
                 interrupt-names = "INT1";
+                mount-matrix = "0", "1", "0",
+                               "-1", "0", "0",
+                               "0", "0", "1";
         };
     };
   - |
diff --git a/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
new file mode 100644 (file)
index 0000000..abd8d25
--- /dev/null
@@ -0,0 +1,90 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/imu/invensense,icm42600.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: InvenSense ICM-426xx Inertial Measurement Unit
+
+maintainers:
+  - Jean-Baptiste Maneyrol <jmaneyrol@invensense.com>
+
+description: |
+  6-axis MotionTracking device that combines a 3-axis gyroscope and a 3-axis
+  accelerometer.
+
+  It has a configurable host interface that supports I3C, I2C and SPI serial
+  communication, features a 2kB FIFO and 2 programmable interrupts with
+  ultra-low-power wake-on-motion support to minimize system power consumption.
+
+  Other industry-leading features include InvenSense on-chip APEX Motion
+  Processing engine for gesture recognition, activity classification, and
+  pedometer, along with programmable digital filters, and an embedded
+  temperature sensor.
+
+  https://invensense.tdk.com/wp-content/uploads/2020/03/DS-000292-ICM-42605-v1.4.pdf
+
+properties:
+  compatible:
+    enum:
+      - invensense,icm42600
+      - invensense,icm42602
+      - invensense,icm42605
+      - invensense,icm42622
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  drive-open-drain:
+    type: boolean
+
+  vdd-supply:
+    description: Regulator that provides power to the sensor
+
+  vddio-supply:
+    description: Regulator that provides power to the bus
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+    i2c0 {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        icm42605@68 {
+          compatible = "invensense,icm42605";
+          reg = <0x68>;
+          interrupt-parent = <&gpio2>;
+          interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+          vdd-supply = <&vdd>;
+          vddio-supply = <&vddio>;
+        };
+    };
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+    spi0 {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        icm42602@0 {
+          compatible = "invensense,icm42602";
+          reg = <0>;
+          spi-max-frequency = <24000000>;
+          spi-cpha;
+          spi-cpol;
+          interrupt-parent = <&gpio1>;
+          interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
+          vdd-supply = <&vdd>;
+          vddio-supply = <&vddio>;
+        };
+    };
index aa199e0..3aa6db3 100644 (file)
@@ -1,6 +1,6 @@
 * Avago APDS9300 ambient light sensor
 
-http://www.avagotech.com/docs/AV02-1077EN
+https://www.avagotech.com/docs/AV02-1077EN
 
 Required properties:
 
index 3af325a..c53ddb8 100644 (file)
@@ -1,6 +1,6 @@
 * Avago APDS9960 gesture/RGB/ALS/proximity sensor
 
-http://www.avagotech.com/docs/AV02-4191EN
+https://www.avagotech.com/docs/AV02-4191EN
 
 Required properties:
 
index 47b13eb..9e6f299 100644 (file)
@@ -6,7 +6,7 @@ the optional generation of IIO events on rising/falling light threshold changes
 requires the use of interrupts. Without interrupts, only the simple reading
 of the current light value is supported through the IIO API.
 
-http://www.ti.com/product/opt3001
+https://www.ti.com/product/opt3001
 
 Required properties:
   - compatible: should be "ti,opt3001"
index 2c52952..fb9137d 100644 (file)
@@ -1,6 +1,6 @@
 STMicro VL6180 -  ALS, range and proximity sensor
 
-Link to datasheet: http://www.st.com/resource/en/datasheet/vl6180x.pdf
+Link to datasheet: https://www.st.com/resource/en/datasheet/vl6180x.pdf
 
 Required properties:
 
diff --git a/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt b/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt
deleted file mode 100644 (file)
index aa67ceb..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-* AsahiKASEI AK8975 magnetometer sensor
-
-Required properties:
-
-  - compatible : should be "asahi-kasei,ak8975"
-  - reg : the I2C address of the magnetometer
-
-Optional properties:
-
-  - gpios : should be device tree identifier of the magnetometer DRDY pin
-  - vdd-supply: an optional regulator that needs to be on to provide VDD
-  - mount-matrix: an optional 3x3 mounting rotation matrix
-
-Example:
-
-ak8975@c {
-        compatible = "asahi-kasei,ak8975";
-        reg = <0x0c>;
-        gpios = <&gpj0 7 0>;
-        vdd-supply = <&ldo_3v3_gnss>;
-        mount-matrix = "-0.984807753012208",  /* x0 */
-                       "0",                   /* y0 */
-                       "-0.173648177666930",  /* z0 */
-                       "0",                   /* x1 */
-                       "-1",                  /* y1 */
-                       "0",                   /* z1 */
-                       "-0.173648177666930",  /* x2 */
-                       "0",                   /* y2 */
-                       "0.984807753012208";   /* z2 */
-};
diff --git a/Documentation/devicetree/bindings/iio/magnetometer/asahi-kasei,ak8975.yaml b/Documentation/devicetree/bindings/iio/magnetometer/asahi-kasei,ak8975.yaml
new file mode 100644 (file)
index 0000000..f4393bf
--- /dev/null
@@ -0,0 +1,83 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/magnetometer/asahi-kasei,ak8975.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: AsahiKASEI AK8975 magnetometer sensor
+
+maintainers:
+  - Jonathan Albrieux <jonathan.albrieux@gmail.com>
+
+properties:
+  compatible:
+    oneOf:
+      - enum:
+        - asahi-kasei,ak8975
+        - asahi-kasei,ak8963
+        - asahi-kasei,ak09911
+        - asahi-kasei,ak09912
+      - enum:
+        - ak8975
+        - ak8963
+        - ak09911
+        - ak09912
+        deprecated: true
+
+  reg:
+    maxItems: 1
+
+  gpios:
+    maxItems: 1
+    description: |
+      AK8975 has a "Data ready" pin (DRDY) which informs that data
+      is ready to be read and is possible to listen on it. If used,
+      this should be active high. Prefer interrupt over this.
+
+  interrupts:
+    maxItems: 1
+    description: interrupt for DRDY pin. Triggered on rising edge.
+
+  vdd-supply:
+    description: |
+      an optional regulator that needs to be on to provide VDD power to
+      the sensor.
+
+  mount-matrix:
+    description: an optional 3x3 mounting rotation matrix.
+
+  reset-gpios:
+    description: |
+      an optional pin needed for AK09911 to set the reset state. This should
+      be usually active low
+
+required:
+  - compatible
+  - reg
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/gpio/gpio.h>
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        magnetometer@c {
+            compatible = "asahi-kasei,ak8975";
+            reg = <0x0c>;
+            interrupt-parent = <&gpio6>;
+            interrupts = <15 IRQ_TYPE_EDGE_RISING>;
+            vdd-supply = <&ldo_3v3_gnss>;
+            reset-gpios = <&msmgpio 111 GPIO_ACTIVE_LOW>;
+            mount-matrix = "-0.984807753012208",  /* x0 */
+                           "0",                   /* y0 */
+                           "-0.173648177666930",  /* z0 */
+                           "0",                   /* x1 */
+                           "-1",                  /* y1 */
+                           "0",                   /* z1 */
+                           "-0.173648177666930",  /* x2 */
+                           "0",                   /* y2 */
+                           "0.984807753012208";   /* z2 */
+        };
+    };
index fd5fca9..22912e4 100644 (file)
@@ -4,7 +4,11 @@ http://ae-bst.resource.bosch.com/media/products/dokumente/bmc150/BST-BMC150-DS00
 
 Required properties:
 
-  - compatible : should be "bosch,bmc150_magn"
+  - compatible : should be one of:
+                 "bosch,bmc150_magn"
+                 "bosch,bmc156_magn"
+                 "bosch,bmm150"
+                 "bosch,bmm150_magn" (DEPRECATED, use bosch,bmm150)
   - reg : the I2C address of the magnetometer
 
 Optional properties:
index 566711b..4f245e8 100644 (file)
@@ -1,7 +1,7 @@
 * Microchip MCP41010/41050/41100/42010/42050/42100 Digital Potentiometer
 
 Datasheet publicly available at:
-http://ww1.microchip.com/downloads/en/devicedoc/11195c.pdf
+https://ww1.microchip.com/downloads/en/devicedoc/11195c.pdf
 
 The node for this driver must be a child node of a SPI controller, hence
 all mandatory properties described in
index e6d0c2e..f3ab02b 100644 (file)
@@ -1,7 +1,7 @@
 * Texas Instruments LMP91000 series of potentiostats
 
-LMP91000: http://www.ti.com/lit/ds/symlink/lmp91000.pdf
-LMP91002: http://www.ti.com/lit/ds/symlink/lmp91002.pdf
+LMP91000: https://www.ti.com/lit/ds/symlink/lmp91000.pdf
+LMP91002: https://www.ti.com/lit/ds/symlink/lmp91002.pdf
 
 Required properties:
 
index 64c18f1..be2be4b 100644 (file)
@@ -13,7 +13,7 @@ description: |
   Bindings for the All Sensors DLH series pressure sensors.
 
   Specifications about the sensors can be found at:
-    http://www.allsensors.com/cad/DS-0355_Rev_B.PDF
+    https://www.allsensors.com/cad/DS-0355_Rev_B.PDF
 
 properties:
   compatible:
index f86f8b2..ce79527 100644 (file)
@@ -17,9 +17,9 @@ description: |
     until it is received once again
 
   Specifications about the devices can be found at:
-  http://www.robot-electronics.co.uk/htm/srf04tech.htm
+  https://www.robot-electronics.co.uk/htm/srf04tech.htm
 
-  http://www.maxbotix.com/documents/LV-MaxSonar-EZ_Datasheet.pdf
+  https://www.maxbotix.com/documents/LV-MaxSonar-EZ_Datasheet.pdf
 
 properties:
   compatible:
index e622f8f..b02c52c 100644 (file)
@@ -262,7 +262,7 @@ the system.
 Counter Counts may be allocated via counter_count structures, and
 respective Counter Signal associations (Synapses) made via
 counter_synapse structures. Associated counter_synapse structures are
-stored as an array and set to the the synapses array member of the
+stored as an array and set to the synapses array member of the
 respective counter_count structure. These counter_count structures are
 set to the counts array member of an allocated counter_device structure
 before the Counter is registered to the system.
index e9036ef..dd64c9c 100644 (file)
@@ -88,7 +88,7 @@ fields in iio_chan_spec definition::
 The driver implementing the accelerometer described above will have the
 following channel definition::
 
-   struct struct iio_chan_spec accel_channels[] = {
+   struct iio_chan_spec accel_channels[] = {
            {
                    .type = IIO_ACCEL,
                   .modified = 1,
index 0d23224..c7348e5 100644 (file)
@@ -8979,6 +8979,14 @@ F:       include/dt-bindings/interconnect/
 F:     include/linux/interconnect-provider.h
 F:     include/linux/interconnect.h
 
+INVENSENSE ICM-426xx IMU DRIVER
+M:     Jean-Baptiste Maneyrol <jmaneyrol@invensense.com>
+L:     linux-iio@vger.kernel.org
+S:     Maintained
+W      https://invensense.tdk.com/
+F:     Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
+F:     drivers/iio/imu/inv_icm42600/
+
 INVENSENSE MPU-3050 GYROSCOPE DRIVER
 M:     Linus Walleij <linus.walleij@linaro.org>
 L:     linux-iio@vger.kernel.org
@@ -11324,7 +11332,6 @@ F:      Documentation/devicetree/bindings/pwm/atmel-pwm.txt
 F:     drivers/pwm/pwm-atmel.c
 
 MICROCHIP SAMA5D2-COMPATIBLE ADC DRIVER
-M:     Ludovic Desroches <ludovic.desroches@microchip.com>
 M:     Eugen Hristev <eugen.hristev@microchip.com>
 L:     linux-iio@vger.kernel.org
 S:     Supported
@@ -15373,6 +15380,15 @@ S:     Maintained
 F:     drivers/misc/phantom.c
 F:     include/uapi/linux/phantom.h
 
+SENSIRION SCD30 CARBON DIOXIDE SENSOR DRIVER
+M:     Tomasz Duszynski <tomasz.duszynski@octakon.com>
+S:     Maintained
+F:     Documentation/devicetree/bindings/iio/chemical/sensirion,scd30.yaml
+F:     drivers/iio/chemical/scd30.h
+F:     drivers/iio/chemical/scd30_core.c
+F:     drivers/iio/chemical/scd30_i2c.c
+F:     drivers/iio/chemical/scd30_serial.c
+
 SENSIRION SPS30 AIR POLLUTION SENSOR DRIVER
 M:     Tomasz Duszynski <tduszyns@gmail.com>
 S:     Maintained
index aa13708..69fd34f 100644 (file)
@@ -1538,7 +1538,6 @@ static int quad8_probe(struct device *dev, unsigned int id)
        indio_dev->num_channels = ARRAY_SIZE(quad8_channels);
        indio_dev->channels = quad8_channels;
        indio_dev->name = dev_name(dev);
-       indio_dev->dev.parent = dev;
 
        /* Initialize Counter device and driver data */
        quad8iio = iio_priv(indio_dev);
index 8e276eb..fd6828e 100644 (file)
@@ -648,7 +648,6 @@ static int stm32_lptim_cnt_probe(struct platform_device *pdev)
 
        /* Initialize IIO device */
        indio_dev->name = dev_name(&pdev->dev);
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->dev.of_node = pdev->dev.of_node;
        indio_dev->info = &stm32_lptim_cnt_iio_info;
        if (ddata->has_encoder)
index 1080637..2e0c62c 100644 (file)
@@ -116,18 +116,24 @@ config BMA400
        tristate "Bosch BMA400 3-Axis Accelerometer Driver"
        select REGMAP
        select BMA400_I2C if I2C
+       select BMA400_SPI if SPI
        help
          Say Y here if you want to build a driver for the Bosch BMA400
          triaxial acceleration sensor.
 
          To compile this driver as a module, choose M here: the
          module will be called bma400_core and you will also get
-         bma400_i2c if I2C is enabled.
+         bma400_i2c if I2C is enabled and bma400_spi if SPI is
+         enabled.
 
 config BMA400_I2C
        tristate
        depends on BMA400
 
+config BMA400_SPI
+       tristate
+       depends on BMA400
+
 config BMC150_ACCEL
        tristate "Bosch BMC150 Accelerometer Driver"
        select IIO_BUFFER
index 3a051cf..4f6c1eb 100644 (file)
@@ -16,6 +16,7 @@ obj-$(CONFIG_BMA180) += bma180.o
 obj-$(CONFIG_BMA220) += bma220_spi.o
 obj-$(CONFIG_BMA400) += bma400_core.o
 obj-$(CONFIG_BMA400_I2C) += bma400_i2c.o
+obj-$(CONFIG_BMA400_SPI) += bma400_spi.o
 obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
 obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o
 obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o
index 4154e73..59a24c3 100644 (file)
@@ -271,7 +271,6 @@ static int adis16201_probe(struct spi_device *spi)
        spi_set_drvdata(spi, indio_dev);
 
        indio_dev->name = spi->dev.driver->name;
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &adis16201_info;
 
        indio_dev->channels = adis16201_channels;
index 31d45e7..3d5538e 100644 (file)
@@ -282,7 +282,6 @@ static int adis16209_probe(struct spi_device *spi)
        spi_set_drvdata(spi, indio_dev);
 
        indio_dev->name = spi->dev.driver->name;
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &adis16209_info;
        indio_dev->channels = adis16209_channels;
        indio_dev->num_channels = ARRAY_SIZE(adis16209_channels);
index 9c26979..3128665 100644 (file)
@@ -4,7 +4,7 @@
  *
  * Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com>
  *
- * Datasheet: http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf
+ * Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf
  */
 
 #include <linux/module.h>
@@ -246,7 +246,6 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap,
                return ret;
        }
 
-       indio_dev->dev.parent = dev;
        indio_dev->name = name;
        indio_dev->info = &adxl345_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 60daf04..e7e316b 100644 (file)
@@ -795,13 +795,9 @@ static int adxl372_buffer_postenable(struct iio_dev *indio_dev)
        unsigned int mask;
        int i, ret;
 
-       ret = iio_triggered_buffer_postenable(indio_dev);
-       if (ret < 0)
-               return ret;
-
        ret = adxl372_set_interrupts(st, ADXL372_INT1_MAP_FIFO_FULL_MSK, 0);
        if (ret < 0)
-               goto err;
+               return ret;
 
        mask = *indio_dev->active_scan_mask;
 
@@ -810,10 +806,8 @@ static int adxl372_buffer_postenable(struct iio_dev *indio_dev)
                        break;
        }
 
-       if (i == ARRAY_SIZE(adxl372_axis_lookup_table)) {
-               ret = -EINVAL;
-               goto err;
-       }
+       if (i == ARRAY_SIZE(adxl372_axis_lookup_table))
+               return -EINVAL;
 
        st->fifo_format = adxl372_axis_lookup_table[i].fifo_format;
        st->fifo_set_size = bitmap_weight(indio_dev->active_scan_mask,
@@ -833,14 +827,10 @@ static int adxl372_buffer_postenable(struct iio_dev *indio_dev)
        if (ret < 0) {
                st->fifo_mode = ADXL372_FIFO_BYPASSED;
                adxl372_set_interrupts(st, 0, 0);
-               goto err;
+               return ret;
        }
 
        return 0;
-
-err:
-       iio_triggered_buffer_predisable(indio_dev);
-       return ret;
 }
 
 static int adxl372_buffer_predisable(struct iio_dev *indio_dev)
@@ -851,7 +841,7 @@ static int adxl372_buffer_predisable(struct iio_dev *indio_dev)
        st->fifo_mode = ADXL372_FIFO_BYPASSED;
        adxl372_configure_fifo(st);
 
-       return iio_triggered_buffer_predisable(indio_dev);
+       return 0;
 }
 
 static const struct iio_buffer_setup_ops adxl372_buffer_ops = {
@@ -938,7 +928,6 @@ int adxl372_probe(struct device *dev, struct regmap *regmap,
        indio_dev->channels = adxl372_channels;
        indio_dev->num_channels = ARRAY_SIZE(adxl372_channels);
        indio_dev->available_scan_masks = adxl372_channel_masks;
-       indio_dev->dev.parent = dev;
        indio_dev->name = name;
        indio_dev->info = &adxl372_info;
        indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
index 265722e..5b7a467 100644 (file)
@@ -1038,7 +1038,6 @@ static int bma180_probe(struct i2c_client *client,
                goto err_chip_disable;
 
        mutex_init(&data->mutex);
-       indio_dev->dev.parent = dev;
        indio_dev->channels = data->part_info->channels;
        indio_dev->num_channels = data->part_info->num_channels;
        indio_dev->name = id->name;
index cae9050..cce8324 100644 (file)
@@ -237,7 +237,6 @@ static int bma220_probe(struct spi_device *spi)
        spi_set_drvdata(spi, indio_dev);
        mutex_init(&data->lock);
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &bma220_info;
        indio_dev->name = BMA220_DEVICE_NAME;
        indio_dev->modes = INDIO_DIRECT_MODE;
index cc77f89..7eeba80 100644 (file)
@@ -816,7 +816,6 @@ int bma400_probe(struct device *dev, struct regmap *regmap, const char *name)
                return ret;
 
        mutex_init(&data->mutex);
-       indio_dev->dev.parent = dev;
        indio_dev->name = name;
        indio_dev->info = &bma400_info;
        indio_dev->channels = bma400_channels;
diff --git a/drivers/iio/accel/bma400_spi.c b/drivers/iio/accel/bma400_spi.c
new file mode 100644 (file)
index 0000000..7c28259
--- /dev/null
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * SPI IIO driver for Bosch BMA400 triaxial acceleration sensor.
+ *
+ * Copyright 2020 Dan Robertson <dan@dlrobertson.com>
+ *
+ */
+#include <linux/bits.h>
+#include <linux/init.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+
+#include "bma400.h"
+
+#define BMA400_MAX_SPI_READ 2
+#define BMA400_SPI_READ_BUFFER_SIZE (BMA400_MAX_SPI_READ + 1)
+
+static int bma400_regmap_spi_read(void *context,
+                                 const void *reg, size_t reg_size,
+                                 void *val, size_t val_size)
+{
+       struct device *dev = context;
+       struct spi_device *spi = to_spi_device(dev);
+       u8 result[BMA400_SPI_READ_BUFFER_SIZE];
+       ssize_t status;
+
+       if (val_size > BMA400_MAX_SPI_READ)
+               return -EINVAL;
+
+       status = spi_write_then_read(spi, reg, 1, result, val_size + 1);
+       if (status)
+               return status;
+
+       /*
+        * From the BMA400 datasheet:
+        *
+        * > For a basic read operation two bytes have to be read and the first
+        * > has to be dropped and the second byte must be interpreted.
+        */
+       memcpy(val, result + 1, val_size);
+
+       return 0;
+}
+
+static int bma400_regmap_spi_write(void *context, const void *data,
+                                  size_t count)
+{
+       struct device *dev = context;
+       struct spi_device *spi = to_spi_device(dev);
+
+       return spi_write(spi, data, count);
+}
+
+static struct regmap_bus bma400_regmap_bus = {
+       .read = bma400_regmap_spi_read,
+       .write = bma400_regmap_spi_write,
+       .read_flag_mask = BIT(7),
+       .max_raw_read = BMA400_MAX_SPI_READ,
+};
+
+static int bma400_spi_probe(struct spi_device *spi)
+{
+       const struct spi_device_id *id = spi_get_device_id(spi);
+       struct regmap *regmap;
+       unsigned int val;
+       int ret;
+
+       regmap = devm_regmap_init(&spi->dev, &bma400_regmap_bus,
+                                 &spi->dev, &bma400_regmap_config);
+       if (IS_ERR(regmap)) {
+               dev_err(&spi->dev, "failed to create regmap\n");
+               return PTR_ERR(regmap);
+       }
+
+       /*
+        * Per the bma400 datasheet, the first SPI read may
+        * return garbage. As the datasheet recommends, the
+        * chip ID register will be read here and checked
+        * again in the following probe.
+        */
+       ret = regmap_read(regmap, BMA400_CHIP_ID_REG, &val);
+       if (ret)
+               dev_err(&spi->dev, "Failed to read chip id register\n");
+
+       return bma400_probe(&spi->dev, regmap, id->name);
+}
+
+static int bma400_spi_remove(struct spi_device *spi)
+{
+       return bma400_remove(&spi->dev);
+}
+
+static const struct spi_device_id bma400_spi_ids[] = {
+       { "bma400", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(spi, bma400_spi_ids);
+
+static const struct of_device_id bma400_of_spi_match[] = {
+       { .compatible = "bosch,bma400" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, bma400_of_spi_match);
+
+static struct spi_driver bma400_spi_driver = {
+       .driver = {
+               .name = "bma400",
+               .of_match_table = bma400_of_spi_match,
+       },
+       .probe    = bma400_spi_probe,
+       .remove   = bma400_spi_remove,
+       .id_table = bma400_spi_ids,
+};
+
+module_spi_driver(bma400_spi_driver);
+MODULE_AUTHOR("Dan Robertson <dan@dlrobertson.com>");
+MODULE_DESCRIPTION("Bosch BMA400 triaxial acceleration sensor (SPI)");
+MODULE_LICENSE("GPL");
index 121b4e8..24864d9 100644 (file)
@@ -1411,7 +1411,7 @@ static int bmc150_accel_buffer_postenable(struct iio_dev *indio_dev)
        int ret = 0;
 
        if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED)
-               return iio_triggered_buffer_postenable(indio_dev);
+               return 0;
 
        mutex_lock(&data->mutex);
 
@@ -1443,7 +1443,7 @@ static int bmc150_accel_buffer_predisable(struct iio_dev *indio_dev)
        struct bmc150_accel_data *data = iio_priv(indio_dev);
 
        if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED)
-               return iio_triggered_buffer_predisable(indio_dev);
+               return 0;
 
        mutex_lock(&data->mutex);
 
@@ -1574,7 +1574,6 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
 
        mutex_init(&data->mutex);
 
-       indio_dev->dev.parent = dev;
        indio_dev->channels = data->chip_info->channels;
        indio_dev->num_channels = data->chip_info->num_channels;
        indio_dev->name = name ? name : data->chip_info->name;
index 2532b9a..b6f3471 100644 (file)
  */
 #define ACCEL_LEGACY_NSCALE 9586168
 
+/*
+ * Sensor frequency is hard-coded to 10Hz.
+ */
+static const int cros_ec_legacy_sample_freq[] = { 10, 0 };
+
 static int cros_ec_accel_legacy_read_cmd(struct iio_dev *indio_dev,
                                  unsigned long scan_mask, s16 *data)
 {
@@ -96,6 +101,11 @@ static int cros_ec_accel_legacy_read(struct iio_dev *indio_dev,
                *val = 0;
                ret = IIO_VAL_INT;
                break;
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               *val = cros_ec_legacy_sample_freq[0];
+               *val2 = cros_ec_legacy_sample_freq[1];
+               ret = IIO_VAL_INT_PLUS_MICRO;
+               break;
        default:
                ret = cros_ec_sensors_core_read(st, chan, val, val2,
                                mask);
@@ -120,9 +130,39 @@ static int cros_ec_accel_legacy_write(struct iio_dev *indio_dev,
        return -EINVAL;
 }
 
+/**
+ * cros_ec_accel_legacy_read_avail() - get available values
+ * @indio_dev:         pointer to state information for device
+ * @chan:      channel specification structure table
+ * @vals:      list of available values
+ * @type:      type of data returned
+ * @length:    number of data returned in the array
+ * @mask:      specifies which values to be requested
+ *
+ * Return:     an error code or IIO_AVAIL_LIST
+ */
+static int cros_ec_accel_legacy_read_avail(struct iio_dev *indio_dev,
+                                          struct iio_chan_spec const *chan,
+                                          const int **vals,
+                                          int *type,
+                                          int *length,
+                                          long mask)
+{
+       switch (mask) {
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               *length = ARRAY_SIZE(cros_ec_legacy_sample_freq);
+               *vals = cros_ec_legacy_sample_freq;
+               *type = IIO_VAL_INT_PLUS_MICRO;
+               return IIO_AVAIL_LIST;
+       }
+
+       return -EINVAL;
+}
+
 static const struct iio_info cros_ec_accel_legacy_info = {
        .read_raw = &cros_ec_accel_legacy_read,
        .write_raw = &cros_ec_accel_legacy_write,
+       .read_avail = &cros_ec_accel_legacy_read_avail,
 };
 
 /*
@@ -142,7 +182,11 @@ static const struct iio_info cros_ec_accel_legacy_info = {
                .info_mask_separate =                                   \
                        BIT(IIO_CHAN_INFO_RAW) |                        \
                        BIT(IIO_CHAN_INFO_CALIBBIAS),                   \
-               .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE),    \
+               .info_mask_shared_by_all =                              \
+                       BIT(IIO_CHAN_INFO_SCALE) |                      \
+                       BIT(IIO_CHAN_INFO_SAMP_FREQ),                   \
+               .info_mask_shared_by_all_available =                    \
+                       BIT(IIO_CHAN_INFO_SAMP_FREQ),                   \
                .ext_info = cros_ec_sensors_ext_info,                   \
                .scan_type = {                                          \
                        .sign = 's',                                    \
index 227bea2..4472dde 100644 (file)
@@ -120,7 +120,6 @@ static int da280_probe(struct i2c_client *client,
        data->client = client;
        i2c_set_clientdata(client, indio_dev);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &da280_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = da280_channels;
index c209792..3b3df62 100644 (file)
@@ -231,7 +231,6 @@ static int da311_probe(struct i2c_client *client,
        data->client = client;
        i2c_set_clientdata(client, indio_dev);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &da311_info;
        indio_dev->name = "da311";
        indio_dev->modes = INDIO_DIRECT_MODE;
index ef89bde..de2868c 100644 (file)
@@ -161,7 +161,6 @@ static int dmard06_probe(struct i2c_client *client,
        dmard06->chip_id = ret;
 
        i2c_set_clientdata(client, indio_dev);
-       indio_dev->dev.parent = &client->dev;
        indio_dev->name = DMARD06_DRV_NAME;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = dmard06_channels;
index 2d666cd..e6e28c9 100644 (file)
@@ -116,7 +116,6 @@ static int dmard09_probe(struct i2c_client *client,
        }
 
        i2c_set_clientdata(client, indio_dev);
-       indio_dev->dev.parent = &client->dev;
        indio_dev->name = DMARD09_DRV_NAME;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = dmard09_channels;
index 71c852b..90206f0 100644 (file)
@@ -196,7 +196,6 @@ static int dmard10_probe(struct i2c_client *client,
        data->client = client;
        i2c_set_clientdata(client, indio_dev);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &dmard10_info;
        indio_dev->name = "dmard10";
        indio_dev->modes = INDIO_DIRECT_MODE;
index 0ec0533..4c5e594 100644 (file)
@@ -384,7 +384,6 @@ static int hid_accel_3d_probe(struct platform_device *pdev)
                goto error_free_dev_mem;
        }
 
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->info = &accel_3d_info;
        indio_dev->name = name;
        indio_dev->modes = INDIO_DIRECT_MODE;
index c9924a6..beb38d9 100644 (file)
@@ -1027,9 +1027,7 @@ static const struct iio_chan_spec kxcjk1013_channels[] = {
 
 static const struct iio_buffer_setup_ops kxcjk1013_buffer_setup_ops = {
        .preenable              = kxcjk1013_buffer_preenable,
-       .postenable             = iio_triggered_buffer_postenable,
        .postdisable            = kxcjk1013_buffer_postdisable,
-       .predisable             = iio_triggered_buffer_predisable,
 };
 
 static const struct iio_info kxcjk1013_info = {
@@ -1311,7 +1309,6 @@ static int kxcjk1013_probe(struct i2c_client *client,
 
        mutex_init(&data->mutex);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->channels = kxcjk1013_channels;
        indio_dev->num_channels = ARRAY_SIZE(kxcjk1013_channels);
        indio_dev->available_scan_masks = kxcjk1013_scan_masks;
index 0b876b2..66b2e4c 100644 (file)
@@ -252,8 +252,6 @@ static int kxsd9_buffer_postdisable(struct iio_dev *indio_dev)
 
 static const struct iio_buffer_setup_ops kxsd9_buffer_setup_ops = {
        .preenable = kxsd9_buffer_preenable,
-       .postenable = iio_triggered_buffer_postenable,
-       .predisable = iio_triggered_buffer_predisable,
        .postdisable = kxsd9_buffer_postdisable,
 };
 
@@ -411,7 +409,6 @@ int kxsd9_common_probe(struct device *dev,
        indio_dev->channels = kxsd9_channels;
        indio_dev->num_channels = ARRAY_SIZE(kxsd9_channels);
        indio_dev->name = name;
-       indio_dev->dev.parent = dev;
        indio_dev->info = &kxsd9_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->available_scan_masks = kxsd9_scan_masks;
index 02b3d25..46e4283 100644 (file)
@@ -132,7 +132,6 @@ static int mc3230_probe(struct i2c_client *client,
        data->client = client;
        i2c_set_clientdata(client, indio_dev);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &mc3230_info;
        indio_dev->name = "mc3230";
        indio_dev->modes = INDIO_DIRECT_MODE;
index 8b5a6af..7e99bcb 100644 (file)
@@ -260,7 +260,6 @@ int mma7455_core_probe(struct device *dev, struct regmap *regmap,
 
        indio_dev->info = &mma7455_info;
        indio_dev->name = name;
-       indio_dev->dev.parent = dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = mma7455_channels;
        indio_dev->num_channels = ARRAY_SIZE(mma7455_channels);
index 7faf6d8..b3c9136 100644 (file)
@@ -188,7 +188,6 @@ static int mma7660_probe(struct i2c_client *client,
        mutex_init(&data->lock);
        data->mode = MMA7660_MODE_STANDBY;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &mma7660_info;
        indio_dev->name = MMA7660_DRIVER_NAME;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 00e100f..ef3df40 100644 (file)
@@ -1592,7 +1592,6 @@ static int mma8452_probe(struct i2c_client *client,
        i2c_set_clientdata(client, indio_dev);
        indio_dev->info = &mma8452_info;
        indio_dev->name = id->name;
-       indio_dev->dev.parent = &client->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = data->chip_info->channels;
        indio_dev->num_channels = data->chip_info->num_channels;
index 99e4a21..08a2303 100644 (file)
@@ -473,7 +473,6 @@ static int mma9551_probe(struct i2c_client *client,
 
        mutex_init(&data->mutex);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->channels = mma9551_channels;
        indio_dev->num_channels = ARRAY_SIZE(mma9551_channels);
        indio_dev->name = name;
index 312070d..c15908f 100644 (file)
@@ -1103,7 +1103,6 @@ static int mma9553_probe(struct i2c_client *client,
        if (ret < 0)
                return ret;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->channels = mma9553_channels;
        indio_dev->num_channels = ARRAY_SIZE(mma9553_channels);
        indio_dev->name = name;
index 9d07642..f877263 100644 (file)
@@ -416,7 +416,6 @@ static int mxc4005_probe(struct i2c_client *client,
 
        mutex_init(&data->mutex);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->channels = mxc4005_channels;
        indio_dev->num_channels = ARRAY_SIZE(mxc4005_channels);
        indio_dev->available_scan_masks = mxc4005_scan_masks;
@@ -474,12 +473,14 @@ static int mxc4005_probe(struct i2c_client *client,
 
 static const struct acpi_device_id mxc4005_acpi_match[] = {
        {"MXC4005",     0},
+       {"MXC6655",     0},
        { },
 };
 MODULE_DEVICE_TABLE(acpi, mxc4005_acpi_match);
 
 static const struct i2c_device_id mxc4005_id[] = {
        {"mxc4005",     0},
+       {"mxc6655",     0},
        { },
 };
 MODULE_DEVICE_TABLE(i2c, mxc4005_id);
index f532f86..9aeeadc 100644 (file)
@@ -138,7 +138,6 @@ static int mxc6255_probe(struct i2c_client *client,
        data->regmap = regmap;
 
        indio_dev->name = MXC6255_DRV_NAME;
-       indio_dev->dev.parent = &client->dev;
        indio_dev->channels = mxc6255_channels;
        indio_dev->num_channels = ARRAY_SIZE(mxc6255_channels);
        indio_dev->modes = INDIO_DIRECT_MODE;
index 6e42907..6365be6 100644 (file)
@@ -1467,7 +1467,6 @@ static int sca3000_probe(struct spi_device *spi)
        st->info = &sca3000_spi_chip_info_tbl[spi_get_device_id(spi)
                                              ->driver_data];
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->info = &sca3000_info;
        if (st->info->temp_output) {
index c32647a..474477e 100644 (file)
@@ -108,8 +108,6 @@ static int ssp_accel_probe(struct platform_device *pdev)
        spd->type = SSP_ACCELEROMETER_SENSOR;
 
        indio_dev->name = ssp_accel_device_name;
-       indio_dev->dev.parent = &pdev->dev;
-       indio_dev->dev.of_node = pdev->dev.of_node;
        indio_dev->info = &ssp_accel_iio_info;
        indio_dev->modes = INDIO_BUFFER_SOFTWARE;
        indio_dev->channels = ssp_acc_channels;
index b5c814e..4922635 100644 (file)
@@ -33,13 +33,9 @@ static int st_accel_buffer_postenable(struct iio_dev *indio_dev)
 {
        int err;
 
-       err = iio_triggered_buffer_postenable(indio_dev);
-       if (err < 0)
-               return err;
-
        err = st_sensors_set_axis_enable(indio_dev, indio_dev->active_scan_mask[0]);
        if (err < 0)
-               goto st_accel_buffer_predisable;
+               return err;
 
        err = st_sensors_set_enable(indio_dev, true);
        if (err < 0)
@@ -49,27 +45,19 @@ static int st_accel_buffer_postenable(struct iio_dev *indio_dev)
 
 st_accel_buffer_enable_all_axis:
        st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
-st_accel_buffer_predisable:
-       iio_triggered_buffer_predisable(indio_dev);
        return err;
 }
 
 static int st_accel_buffer_predisable(struct iio_dev *indio_dev)
 {
-       int err, err2;
+       int err;
 
        err = st_sensors_set_enable(indio_dev, false);
        if (err < 0)
-               goto st_accel_buffer_predisable;
-
-       err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
-
-st_accel_buffer_predisable:
-       err2 = iio_triggered_buffer_predisable(indio_dev);
-       if (!err)
-               err = err2;
+               return err;
 
-       return err;
+       return st_sensors_set_axis_enable(indio_dev,
+                                         ST_SENSORS_ENABLE_ALL_AXIS);
 }
 
 static const struct iio_buffer_setup_ops st_accel_buffer_setup_ops = {
index 58c160c..3b59887 100644 (file)
@@ -492,8 +492,6 @@ static int stk8312_buffer_postdisable(struct iio_dev *indio_dev)
 
 static const struct iio_buffer_setup_ops stk8312_buffer_setup_ops = {
        .preenable   = stk8312_buffer_preenable,
-       .postenable  = iio_triggered_buffer_postenable,
-       .predisable  = iio_triggered_buffer_predisable,
        .postdisable = stk8312_buffer_postdisable,
 };
 
@@ -515,7 +513,6 @@ static int stk8312_probe(struct i2c_client *client,
        i2c_set_clientdata(client, indio_dev);
        mutex_init(&data->lock);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &stk8312_info;
        indio_dev->name = STK8312_DRIVER_NAME;
        indio_dev->modes = INDIO_DIRECT_MODE;
index c70ddec..3ead378 100644 (file)
@@ -376,8 +376,6 @@ static int stk8ba50_buffer_postdisable(struct iio_dev *indio_dev)
 
 static const struct iio_buffer_setup_ops stk8ba50_buffer_setup_ops = {
        .preenable   = stk8ba50_buffer_preenable,
-       .postenable  = iio_triggered_buffer_postenable,
-       .predisable  = iio_triggered_buffer_predisable,
        .postdisable = stk8ba50_buffer_postdisable,
 };
 
@@ -399,7 +397,6 @@ static int stk8ba50_probe(struct i2c_client *client,
        i2c_set_clientdata(client, indio_dev);
        mutex_init(&data->lock);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &stk8ba50_info;
        indio_dev->name = STK8BA50_DRIVER_NAME;
        indio_dev->modes = INDIO_DIRECT_MODE;
index ff35696..c4d3299 100644 (file)
@@ -294,7 +294,7 @@ config ASPEED_ADC
 
 config AT91_ADC
        tristate "Atmel AT91 ADC"
-       depends on ARCH_AT91
+       depends on ARCH_AT91 || COMPILE_TEST
        depends on INPUT && SYSFS
        select IIO_BUFFER
        select IIO_TRIGGERED_BUFFER
index fd5b18d..7fdc5d2 100644 (file)
@@ -1163,8 +1163,6 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
 
        pm_runtime_put(dev);
 
-       indio_dev->dev.parent = dev;
-       indio_dev->dev.of_node = np;
        indio_dev->name = "ab8500-gpadc";
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &ab8500_gpadc_info;
index 33c4035..63b4d6e 100644 (file)
@@ -224,7 +224,6 @@ int ad7091r_probe(struct device *dev, const char *name,
        st->chip_info = chip_info;
        st->map = map;
 
-       iio_dev->dev.parent = dev;
        iio_dev->name = name;
        iio_dev->info = &ad7091r_info;
        iio_dev->modes = INDIO_DIRECT_MODE;
index a3c0647..bb53ab2 100644 (file)
@@ -683,7 +683,6 @@ static int ad7124_probe(struct spi_device *spi)
 
        spi_set_drvdata(spi, indio_dev);
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &ad7124_info;
index 08ba1a8..a0837d7 100644 (file)
@@ -970,7 +970,6 @@ static int ad7192_probe(struct spi_device *spi)
 
        spi_set_drvdata(spi, indio_dev);
        st->chip_info = of_device_get_match_data(&spi->dev);
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = st->chip_info->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
index c8524f0..a8ec3ef 100644 (file)
@@ -74,8 +74,6 @@ static int ad7266_postdisable(struct iio_dev *indio_dev)
 
 static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
        .preenable = &ad7266_preenable,
-       .postenable = &iio_triggered_buffer_postenable,
-       .predisable = &iio_triggered_buffer_predisable,
        .postdisable = &ad7266_postdisable,
 };
 
@@ -437,8 +435,6 @@ static int ad7266_probe(struct spi_device *spi)
        spi_set_drvdata(spi, indio_dev);
        st->spi = spi;
 
-       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 = &ad7266_info;
index b2b137f..62fde2a 100644 (file)
@@ -502,8 +502,6 @@ static int ad7291_probe(struct i2c_client *client,
        indio_dev->channels = ad7291_channels;
        indio_dev->num_channels = ARRAY_SIZE(ad7291_channels);
 
-       indio_dev->dev.parent = &client->dev;
-       indio_dev->dev.of_node = client->dev.of_node;
        indio_dev->info = &ad7291_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
index 6595fd1..2eafbe7 100644 (file)
@@ -304,7 +304,6 @@ static int ad7292_probe(struct spi_device *spi)
                st->vref_mv = 1250;
        }
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &ad7292_info;
index dc8d8c5..733fb12 100644 (file)
@@ -312,8 +312,6 @@ static int ad7298_probe(struct spi_device *spi)
        st->spi = spi;
 
        indio_dev->name = spi_get_device_id(spi)->name;
-       indio_dev->dev.parent = &spi->dev;
-       indio_dev->dev.of_node = spi->dev.of_node;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = ad7298_channels;
        indio_dev->num_channels = ARRAY_SIZE(ad7298_channels);
index 4e816d7..66c55ae 100644 (file)
@@ -300,9 +300,6 @@ static int ad7476_probe(struct spi_device *spi)
 
        st->spi = spi;
 
-       /* Establish that the iio_dev is a child of the spi 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->channels = st->chip_info->channel;
index e4683a6..ee7b108 100644 (file)
@@ -499,7 +499,6 @@ static int ad7606_buffer_postenable(struct iio_dev *indio_dev)
 {
        struct ad7606_state *st = iio_priv(indio_dev);
 
-       iio_triggered_buffer_postenable(indio_dev);
        gpiod_set_value(st->gpio_convst, 1);
 
        return 0;
@@ -511,7 +510,7 @@ static int ad7606_buffer_predisable(struct iio_dev *indio_dev)
 
        gpiod_set_value(st->gpio_convst, 0);
 
-       return iio_triggered_buffer_predisable(indio_dev);
+       return 0;
 }
 
 static const struct iio_buffer_setup_ops ad7606_buffer_ops = {
@@ -614,7 +613,6 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
        if (ret)
                return ret;
 
-       indio_dev->dev.parent = dev;
        if (st->gpio_os) {
                if (st->gpio_range)
                        indio_dev->info = &ad7606_info_os_and_range;
index bc388ea..b6b6765 100644 (file)
@@ -178,8 +178,6 @@ static const struct ad7766_chip_info ad7766_chip_info[] = {
 
 static const struct iio_buffer_setup_ops ad7766_buffer_setup_ops = {
        .preenable = &ad7766_preenable,
-       .postenable = &iio_triggered_buffer_postenable,
-       .predisable = &iio_triggered_buffer_predisable,
        .postdisable = &ad7766_postdisable,
 };
 
@@ -242,7 +240,6 @@ static int ad7766_probe(struct spi_device *spi)
        if (IS_ERR(ad7766->pd_gpio))
                return PTR_ERR(ad7766->pd_gpio);
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = ad7766_channels;
index 0d13270..0e93b07 100644 (file)
@@ -490,7 +490,6 @@ static int ad7768_buffer_postenable(struct iio_dev *indio_dev)
 {
        struct ad7768_state *st = iio_priv(indio_dev);
 
-       iio_triggered_buffer_postenable(indio_dev);
        /*
         * Write a 1 to the LSB of the INTERFACE_FORMAT register to enter
         * continuous read mode. Subsequent data reads do not require an
@@ -502,17 +501,12 @@ static int ad7768_buffer_postenable(struct iio_dev *indio_dev)
 static int ad7768_buffer_predisable(struct iio_dev *indio_dev)
 {
        struct ad7768_state *st = iio_priv(indio_dev);
-       int ret;
 
        /*
         * To exit continuous read mode, perform a single read of the ADC_DATA
         * reg (0x2C), which allows further configuration of the device.
         */
-       ret = ad7768_spi_reg_read(st, AD7768_REG_ADC_DATA, 3);
-       if (ret < 0)
-               return ret;
-
-       return iio_triggered_buffer_predisable(indio_dev);
+       return ad7768_spi_reg_read(st, AD7768_REG_ADC_DATA, 3);
 }
 
 static const struct iio_buffer_setup_ops ad7768_buffer_ops = {
@@ -584,7 +578,6 @@ static int ad7768_probe(struct spi_device *spi)
 
        indio_dev->channels = ad7768_channels;
        indio_dev->num_channels = ARRAY_SIZE(ad7768_channels);
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->info = &ad7768_info;
        indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_TRIGGERED;
index f47606e..ecbbdfa 100644 (file)
@@ -320,7 +320,6 @@ static int ad7780_probe(struct spi_device *spi)
 
        spi_set_drvdata(spi, indio_dev);
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = &st->chip_info->channel;
index 48432b6..d57ad96 100644 (file)
@@ -425,8 +425,6 @@ static int ad7791_probe(struct spi_device *spi)
 
        spi_set_drvdata(spi, indio_dev);
 
-       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->channels = st->info->channels;
index 808485f..5e980a0 100644 (file)
@@ -818,8 +818,6 @@ static int ad7793_probe(struct spi_device *spi)
 
        spi_set_drvdata(spi, indio_dev);
 
-       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->channels = st->chip_info->channels;
index c6a3428..f8e6243 100644 (file)
@@ -136,8 +136,6 @@ done:
 
 static const struct iio_buffer_setup_ops ad7887_ring_setup_ops = {
        .preenable = &ad7887_ring_preenable,
-       .postenable = &iio_triggered_buffer_postenable,
-       .predisable = &iio_triggered_buffer_predisable,
        .postdisable = &ad7887_ring_postdisable,
 };
 
@@ -264,9 +262,6 @@ static int ad7887_probe(struct spi_device *spi)
        spi_set_drvdata(spi, indio_dev);
        st->spi = spi;
 
-       /* Estabilish that the iio_dev is a child of the spi 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->info = &ad7887_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 1d124c8..bd3ce6b 100644 (file)
@@ -315,8 +315,6 @@ static int ad7923_probe(struct spi_device *spi)
        info = &ad7923_chip_info[spi_get_device_id(spi)->driver_data];
 
        indio_dev->name = spi_get_device_id(spi)->name;
-       indio_dev->dev.parent = &spi->dev;
-       indio_dev->dev.of_node = spi->dev.of_node;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = info->channels;
        indio_dev->num_channels = info->num_channels;
index 2c6f60e..d9566a8 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2018 CMC NV
  *
- * http://www.analog.com/media/en/technical-documentation/data-sheets/AD7949.pdf
+ * https://www.analog.com/media/en/technical-documentation/data-sheets/AD7949.pdf
  */
 
 #include <linux/delay.h>
@@ -243,8 +243,6 @@ static int ad7949_spi_probe(struct spi_device *spi)
                return -ENOMEM;
        }
 
-       indio_dev->dev.parent = dev;
-       indio_dev->dev.of_node = dev->of_node;
        indio_dev->info = &ad7949_spi_info;
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
index ef013af..cfd814f 100644 (file)
@@ -814,8 +814,6 @@ static int ad799x_probe(struct i2c_client *client,
 
        st->client = client;
 
-       indio_dev->dev.parent = &client->dev;
-       indio_dev->dev.of_node = client->dev.of_node;
        indio_dev->name = id->name;
        indio_dev->info = st->chip_config->info;
 
index dd3d54b..3554ee6 100644 (file)
@@ -345,10 +345,6 @@ static int ad_sd_buffer_postenable(struct iio_dev *indio_dev)
        unsigned int channel;
        int ret;
 
-       ret = iio_triggered_buffer_postenable(indio_dev);
-       if (ret < 0)
-               return ret;
-
        channel = find_first_bit(indio_dev->active_scan_mask,
                                 indio_dev->masklength);
        ret = ad_sigma_delta_set_channel(sigma_delta,
@@ -441,7 +437,6 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
 
 static const struct iio_buffer_setup_ops ad_sd_buffer_setup_ops = {
        .postenable = &ad_sd_buffer_postenable,
-       .predisable = &iio_triggered_buffer_predisable,
        .postdisable = &ad_sd_buffer_postdisable,
        .validate_scan_mask = &iio_validate_scan_mask_onehot,
 };
index c24c8da..63d926e 100644 (file)
@@ -435,7 +435,6 @@ static int adi_axi_adc_probe(struct platform_device *pdev)
        }
 
        indio_dev->info = &adi_axi_adc_info;
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->name = "adi-axi-adc";
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->num_channels = conv->chip_info->num_channels;
index 1e53752..19efaa4 100644 (file)
@@ -252,7 +252,6 @@ static int aspeed_adc_probe(struct platform_device *pdev)
 
        model_data = of_device_get_match_data(&pdev->dev);
        indio_dev->name = model_data->model_name;
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->info = &aspeed_adc_iio_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = aspeed_adc_iio_channels;
index 9abbbdc..3d9b75e 100644 (file)
@@ -402,6 +402,7 @@ struct at91_adc_state {
        wait_queue_head_t               wq_data_available;
        struct at91_adc_dma             dma_st;
        struct at91_adc_touch           touch_st;
+       struct iio_dev                  *indio_dev;
        u16                             buffer[AT91_BUFFER_MAX_HWORDS];
        /*
         * lock to prevent concurrent 'single conversion' requests through
@@ -642,13 +643,13 @@ static u16 at91_adc_touch_pos(struct at91_adc_state *st, int reg)
        /* first half of register is the x or y, second half is the scale */
        val = at91_adc_readl(st, reg);
        if (!val)
-               dev_dbg(&iio_priv_to_dev(st)->dev, "pos is 0\n");
+               dev_dbg(&st->indio_dev->dev, "pos is 0\n");
 
        pos = val & AT91_SAMA5D2_XYZ_MASK;
        result = (pos << AT91_SAMA5D2_MAX_POS_BITS) - pos;
        scale = (val >> 16) & AT91_SAMA5D2_XYZ_MASK;
        if (scale == 0) {
-               dev_err(&iio_priv_to_dev(st)->dev, "scale is 0\n");
+               dev_err(&st->indio_dev->dev, "scale is 0\n");
                return 0;
        }
        result /= scale;
@@ -937,14 +938,6 @@ static int at91_adc_buffer_preenable(struct iio_dev *indio_dev)
        return 0;
 }
 
-static int at91_adc_buffer_postenable(struct iio_dev *indio_dev)
-{
-       if (at91_adc_current_chan_is_touch(indio_dev))
-               return 0;
-
-       return iio_triggered_buffer_postenable(indio_dev);
-}
-
 static int at91_adc_buffer_postdisable(struct iio_dev *indio_dev)
 {
        struct at91_adc_state *st = iio_priv(indio_dev);
@@ -995,19 +988,9 @@ static int at91_adc_buffer_postdisable(struct iio_dev *indio_dev)
        return 0;
 }
 
-static int at91_adc_buffer_predisable(struct iio_dev *indio_dev)
-{
-       if (at91_adc_current_chan_is_touch(indio_dev))
-               return 0;
-
-       return iio_triggered_buffer_predisable(indio_dev);
-}
-
 static const struct iio_buffer_setup_ops at91_buffer_setup_ops = {
        .preenable = &at91_adc_buffer_preenable,
        .postdisable = &at91_adc_buffer_postdisable,
-       .postenable = &at91_adc_buffer_postenable,
-       .predisable = &at91_adc_buffer_predisable,
 };
 
 static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio,
@@ -1204,9 +1187,9 @@ static unsigned at91_adc_startup_time(unsigned startup_time_min,
        return i;
 }
 
-static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq)
+static void at91_adc_setup_samp_freq(struct iio_dev *indio_dev, unsigned freq)
 {
-       struct iio_dev *indio_dev = iio_priv_to_dev(st);
+       struct at91_adc_state *st = iio_priv(indio_dev);
        unsigned f_per, prescal, startup, mr;
 
        f_per = clk_get_rate(st->per_clk);
@@ -1275,9 +1258,9 @@ static void at91_adc_pen_detect_interrupt(struct at91_adc_state *st)
        st->touch_st.touching = true;
 }
 
-static void at91_adc_no_pen_detect_interrupt(struct at91_adc_state *st)
+static void at91_adc_no_pen_detect_interrupt(struct iio_dev *indio_dev)
 {
-       struct iio_dev *indio_dev = iio_priv_to_dev(st);
+       struct at91_adc_state *st = iio_priv(indio_dev);
 
        at91_adc_writel(st, AT91_SAMA5D2_TRGR,
                        AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER);
@@ -1297,7 +1280,7 @@ static void at91_adc_workq_handler(struct work_struct *workq)
                                        struct at91_adc_touch, workq);
        struct at91_adc_state *st = container_of(touch_st,
                                        struct at91_adc_state, touch_st);
-       struct iio_dev *indio_dev = iio_priv_to_dev(st);
+       struct iio_dev *indio_dev = st->indio_dev;
 
        iio_push_to_buffers(indio_dev, st->buffer);
 }
@@ -1318,7 +1301,7 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private)
                at91_adc_pen_detect_interrupt(st);
        } else if ((status & AT91_SAMA5D2_IER_NOPEN)) {
                /* nopen detected IRQ */
-               at91_adc_no_pen_detect_interrupt(st);
+               at91_adc_no_pen_detect_interrupt(indio);
        } else if ((status & AT91_SAMA5D2_ISR_PENS) &&
                   ((status & rdy_mask) == rdy_mask)) {
                /* periodic trigger IRQ - during pen sense */
@@ -1486,7 +1469,7 @@ static int at91_adc_write_raw(struct iio_dev *indio_dev,
                    val > st->soc_info.max_sample_rate)
                        return -EINVAL;
 
-               at91_adc_setup_samp_freq(st, val);
+               at91_adc_setup_samp_freq(indio_dev, val);
                return 0;
        default:
                return -EINVAL;
@@ -1624,8 +1607,10 @@ static int at91_adc_update_scan_mode(struct iio_dev *indio_dev,
        return 0;
 }
 
-static void at91_adc_hw_init(struct at91_adc_state *st)
+static void at91_adc_hw_init(struct iio_dev *indio_dev)
 {
+       struct at91_adc_state *st = iio_priv(indio_dev);
+
        at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST);
        at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff);
        /*
@@ -1635,7 +1620,7 @@ static void at91_adc_hw_init(struct at91_adc_state *st)
        at91_adc_writel(st, AT91_SAMA5D2_MR,
                        AT91_SAMA5D2_MR_TRANSFER(2) | AT91_SAMA5D2_MR_ANACH);
 
-       at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate);
+       at91_adc_setup_samp_freq(indio_dev, st->soc_info.min_sample_rate);
 
        /* configure extended mode register */
        at91_adc_config_emr(st);
@@ -1710,7 +1695,6 @@ static int at91_adc_probe(struct platform_device *pdev)
        if (!indio_dev)
                return -ENOMEM;
 
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->name = dev_name(&pdev->dev);
        indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
        indio_dev->info = &at91_adc_info;
@@ -1718,6 +1702,7 @@ static int at91_adc_probe(struct platform_device *pdev)
        indio_dev->num_channels = ARRAY_SIZE(at91_adc_channels);
 
        st = iio_priv(indio_dev);
+       st->indio_dev = indio_dev;
 
        bitmap_set(&st->touch_st.channels_bitmask,
                   AT91_SAMA5D2_TOUCH_X_CHAN_IDX, 1);
@@ -1829,7 +1814,7 @@ static int at91_adc_probe(struct platform_device *pdev)
                goto vref_disable;
        }
 
-       at91_adc_hw_init(st);
+       at91_adc_hw_init(indio_dev);
 
        ret = clk_prepare_enable(st->per_clk);
        if (ret)
@@ -1945,7 +1930,7 @@ static __maybe_unused int at91_adc_resume(struct device *dev)
        if (ret)
                goto vref_disable_resume;
 
-       at91_adc_hw_init(st);
+       at91_adc_hw_init(indio_dev);
 
        /* reconfiguring trigger hardware state */
        if (!iio_buffer_enabled(indio_dev))
index 0368b6d..22b9b84 100644 (file)
@@ -287,13 +287,13 @@ static void handle_adc_eoc_trigger(int irq, struct iio_dev *idev)
        }
 }
 
-static int at91_ts_sample(struct at91_adc_state *st)
+static int at91_ts_sample(struct iio_dev *idev)
 {
+       struct at91_adc_state *st = iio_priv(idev);
        unsigned int xscale, yscale, reg, z1, z2;
        unsigned int x, y, pres, xpos, ypos;
        unsigned int rxp = 1;
        unsigned int factor = 1000;
-       struct iio_dev *idev = iio_priv_to_dev(st);
 
        unsigned int xyz_mask_bits = st->res;
        unsigned int xyz_mask = (1 << xyz_mask_bits) - 1;
@@ -449,7 +449,7 @@ static irqreturn_t at91_adc_9x5_interrupt(int irq, void *private)
 
                if (status & AT91_ADC_ISR_PENS) {
                        /* validate data by pen contact */
-                       at91_ts_sample(st);
+                       at91_ts_sample(idev);
                } else {
                        /* triggered by event that is no pen contact, just read
                         * them to clean the interrupt and discard all.
@@ -737,10 +737,10 @@ static int at91_adc_read_raw(struct iio_dev *idev,
        return -EINVAL;
 }
 
-static int at91_adc_of_get_resolution(struct at91_adc_state *st,
+static int at91_adc_of_get_resolution(struct iio_dev *idev,
                                      struct platform_device *pdev)
 {
-       struct iio_dev *idev = iio_priv_to_dev(st);
+       struct at91_adc_state *st = iio_priv(idev);
        struct device_node *np = pdev->dev.of_node;
        int count, i, ret = 0;
        char *res_name, *s;
@@ -866,10 +866,10 @@ static int at91_adc_probe_dt_ts(struct device_node *node,
        }
 }
 
-static int at91_adc_probe_dt(struct at91_adc_state *st,
+static int at91_adc_probe_dt(struct iio_dev *idev,
                             struct platform_device *pdev)
 {
-       struct iio_dev *idev = iio_priv_to_dev(st);
+       struct at91_adc_state *st = iio_priv(idev);
        struct device_node *node = pdev->dev.of_node;
        struct device_node *trig_node;
        int i = 0, ret;
@@ -910,7 +910,7 @@ static int at91_adc_probe_dt(struct at91_adc_state *st,
        }
        st->vref_mv = prop;
 
-       ret = at91_adc_of_get_resolution(st, pdev);
+       ret = at91_adc_of_get_resolution(idev, pdev);
        if (ret)
                goto error_ret;
 
@@ -1010,9 +1010,9 @@ static void atmel_ts_close(struct input_dev *dev)
                at91_adc_writel(st, AT91_ADC_IDR, AT91RL_ADC_IER_PEN);
 }
 
-static int at91_ts_hw_init(struct at91_adc_state *st, u32 adc_clk_khz)
+static int at91_ts_hw_init(struct iio_dev *idev, u32 adc_clk_khz)
 {
-       struct iio_dev *idev = iio_priv_to_dev(st);
+       struct at91_adc_state *st = iio_priv(idev);
        u32 reg = 0;
        u32 tssctim = 0;
        int i = 0;
@@ -1085,11 +1085,11 @@ static int at91_ts_hw_init(struct at91_adc_state *st, u32 adc_clk_khz)
        return 0;
 }
 
-static int at91_ts_register(struct at91_adc_state *st,
+static int at91_ts_register(struct iio_dev *idev,
                struct platform_device *pdev)
 {
+       struct at91_adc_state *st = iio_priv(idev);
        struct input_dev *input;
-       struct iio_dev *idev = iio_priv_to_dev(st);
        int ret;
 
        input = input_allocate_device();
@@ -1161,7 +1161,7 @@ static int at91_adc_probe(struct platform_device *pdev)
        st = iio_priv(idev);
 
        if (pdev->dev.of_node)
-               ret = at91_adc_probe_dt(st, pdev);
+               ret = at91_adc_probe_dt(idev, pdev);
        else
                ret = at91_adc_probe_pdata(st, pdev);
 
@@ -1172,7 +1172,6 @@ static int at91_adc_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, idev);
 
-       idev->dev.parent = &pdev->dev;
        idev->name = dev_name(&pdev->dev);
        idev->modes = INDIO_DIRECT_MODE;
        idev->info = &at91_adc_info;
@@ -1301,11 +1300,11 @@ static int at91_adc_probe(struct platform_device *pdev)
                        goto error_disable_adc_clk;
                }
        } else {
-               ret = at91_ts_register(st, pdev);
+               ret = at91_ts_register(idev, pdev);
                if (ret)
                        goto error_disable_adc_clk;
 
-               at91_ts_hw_init(st, adc_clk_khz);
+               at91_ts_hw_init(idev, adc_clk_khz);
        }
 
        ret = iio_device_register(idev);
index 8805948..798ff2d 100644 (file)
@@ -668,8 +668,6 @@ static int axp20x_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, indio_dev);
 
        info->regmap = axp20x_dev->regmap;
-       indio_dev->dev.parent = &pdev->dev;
-       indio_dev->dev.of_node = pdev->dev.of_node;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
        if (!pdev->dev.of_node) {
index 8ea2aed..5f5e8b3 100644 (file)
@@ -271,7 +271,6 @@ static int axp288_adc_probe(struct platform_device *pdev)
                return ret;
        }
 
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->name = pdev->name;
        indio_dev->channels = axp288_adc_channels;
        indio_dev->num_channels = ARRAY_SIZE(axp288_adc_channels);
index 5e39610..936da32 100644 (file)
@@ -573,8 +573,6 @@ static int iproc_adc_probe(struct platform_device *pdev)
        }
 
        indio_dev->name = "iproc-static-adc";
-       indio_dev->dev.parent = &pdev->dev;
-       indio_dev->dev.of_node = pdev->dev.of_node;
        indio_dev->info = &iproc_adc_iio_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = iproc_adc_iio_channels;
index 72d8fa9..8b04b95 100644 (file)
@@ -321,7 +321,6 @@ static int berlin2_adc_probe(struct platform_device *pdev)
        init_waitqueue_head(&priv->wq);
        mutex_init(&priv->lock);
 
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->name = dev_name(&pdev->dev);
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &berlin2_adc_info;
index fe92576..e16ac93 100644 (file)
@@ -334,7 +334,6 @@ static int cc10001_adc_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->name = dev_name(&pdev->dev);
        indio_dev->info = &cc10001_adc_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 5086a33..cc26cf3 100644 (file)
@@ -15,9 +15,9 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
+#include <linux/mod_devicetable.h>
 #include <linux/platform_device.h>
+#include <linux/property.h>
 #include <linux/regmap.h>
 
 #include <linux/iio/buffer.h>
@@ -955,22 +955,10 @@ MODULE_DEVICE_TABLE(of, cpcap_adc_id_table);
 
 static int cpcap_adc_probe(struct platform_device *pdev)
 {
-       const struct of_device_id *match;
        struct cpcap_adc *ddata;
        struct iio_dev *indio_dev;
        int error;
 
-       match = of_match_device(of_match_ptr(cpcap_adc_id_table),
-                               &pdev->dev);
-       if (!match)
-               return -EINVAL;
-
-       if (!match->data) {
-               dev_err(&pdev->dev, "no configuration data found\n");
-
-               return -ENODEV;
-       }
-
        indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*ddata));
        if (!indio_dev) {
                dev_err(&pdev->dev, "failed to allocate iio device\n");
@@ -978,15 +966,15 @@ static int cpcap_adc_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
        ddata = iio_priv(indio_dev);
-       ddata->ato = match->data;
+       ddata->ato = device_get_match_data(&pdev->dev);
+       if (!ddata->ato)
+               return -ENODEV;
        ddata->dev = &pdev->dev;
 
        mutex_init(&ddata->lock);
        init_waitqueue_head(&ddata->wq_data_avail);
 
        indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
-       indio_dev->dev.parent = &pdev->dev;
-       indio_dev->dev.of_node = pdev->dev.of_node;
        indio_dev->channels = cpcap_adc_channels;
        indio_dev->num_channels = ARRAY_SIZE(cpcap_adc_channels);
        indio_dev->name = dev_name(&pdev->dev);
@@ -1029,7 +1017,7 @@ static int cpcap_adc_probe(struct platform_device *pdev)
 static struct platform_driver cpcap_adc_driver = {
        .driver = {
                .name = "cpcap_adc",
-               .of_match_table = of_match_ptr(cpcap_adc_id_table),
+               .of_match_table = cpcap_adc_id_table,
        },
        .probe = cpcap_adc_probe,
 };
index ae8bcc3..7a7a54a 100644 (file)
@@ -354,8 +354,6 @@ static int da9150_gpadc_probe(struct platform_device *pdev)
        }
 
        indio_dev->name = dev_name(dev);
-       indio_dev->dev.parent = dev;
-       indio_dev->dev.of_node = pdev->dev.of_node;
        indio_dev->info = &da9150_gpadc_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = da9150_gpadc_channels;
index 65c7c93..0d53ef1 100644 (file)
@@ -524,10 +524,6 @@ static int dln2_adc_triggered_buffer_postenable(struct iio_dev *indio_dev)
        u16 conflict;
        unsigned int trigger_chan;
 
-       ret = iio_triggered_buffer_postenable(indio_dev);
-       if (ret)
-               return ret;
-
        mutex_lock(&dln2->mutex);
 
        /* Enable ADC */
@@ -541,7 +537,6 @@ static int dln2_adc_triggered_buffer_postenable(struct iio_dev *indio_dev)
                                (int)conflict);
                        ret = -EBUSY;
                }
-               iio_triggered_buffer_predisable(indio_dev);
                return ret;
        }
 
@@ -555,7 +550,6 @@ static int dln2_adc_triggered_buffer_postenable(struct iio_dev *indio_dev)
                mutex_unlock(&dln2->mutex);
                if (ret < 0) {
                        dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__);
-                       iio_triggered_buffer_predisable(indio_dev);
                        return ret;
                }
        } else {
@@ -568,7 +562,7 @@ static int dln2_adc_triggered_buffer_postenable(struct iio_dev *indio_dev)
 
 static int dln2_adc_triggered_buffer_predisable(struct iio_dev *indio_dev)
 {
-       int ret, ret2;
+       int ret;
        struct dln2_adc *dln2 = iio_priv(indio_dev);
 
        mutex_lock(&dln2->mutex);
@@ -586,10 +580,6 @@ static int dln2_adc_triggered_buffer_predisable(struct iio_dev *indio_dev)
        if (ret < 0)
                dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__);
 
-       ret2 = iio_triggered_buffer_predisable(indio_dev);
-       if (ret == 0)
-               ret = ret2;
-
        return ret;
 }
 
@@ -652,7 +642,6 @@ static int dln2_adc_probe(struct platform_device *pdev)
        IIO_CHAN_SOFT_TIMESTAMP_ASSIGN(dln2->iio_channels[i], i);
 
        indio_dev->name = DLN2_ADC_MOD_NAME;
-       indio_dev->dev.parent = dev;
        indio_dev->info = &dln2_adc_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = dln2->iio_channels;
index 28f3d67..2a4fd3b 100644 (file)
@@ -343,8 +343,6 @@ static int envelope_detector_probe(struct platform_device *pdev)
        INIT_DELAYED_WORK(&env->comp_timeout, envelope_detector_timeout);
 
        indio_dev->name = dev_name(dev);
-       indio_dev->dev.parent = dev;
-       indio_dev->dev.of_node = dev->of_node;
        indio_dev->info = &envelope_detector_info;
        indio_dev->channels = &envelope_detector_iio_channel;
        indio_dev->num_channels = 1;
index 5c97e8a..c08ab3c 100644 (file)
@@ -170,7 +170,6 @@ static int ep93xx_adc_probe(struct platform_device *pdev)
                return PTR_ERR(priv->base);
        }
 
-       iiodev->dev.parent = &pdev->dev;
        iiodev->name = dev_name(&pdev->dev);
        iiodev->modes = INDIO_DIRECT_MODE;
        iiodev->info = &ep93xx_adc_info;
index 6bda4f4..7d23b6c 100644 (file)
@@ -867,8 +867,6 @@ static int exynos_adc_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, indio_dev);
 
        indio_dev->name = dev_name(&pdev->dev);
-       indio_dev->dev.parent = &pdev->dev;
-       indio_dev->dev.of_node = pdev->dev.of_node;
        indio_dev->info = &exynos_adc_iio_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = exynos_adc_iio_channels;
index b0a4dc8..8cb51cf 100644 (file)
@@ -350,7 +350,6 @@ static int mx25_gcq_probe(struct platform_device *pdev)
                goto err_clk_unprepare;
        }
 
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->channels = mx25_gcq_channels;
        indio_dev->num_channels = ARRAY_SIZE(mx25_gcq_channels);
        indio_dev->info = &mx25_gcq_iio_info;
index 8da45bf..074c309 100644 (file)
@@ -15,9 +15,7 @@
 #include <linux/iio/triggered_event.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/of_gpio.h>
+#include <linux/mod_devicetable.h>
 #include <linux/spi/spi.h>
 #include <linux/gpio/consumer.h>
 
@@ -488,8 +486,6 @@ static int hi8435_probe(struct spi_device *spi)
        spi_set_drvdata(spi, idev);
        mutex_init(&priv->lock);
 
-       idev->dev.parent        = &spi->dev;
-       idev->dev.of_node       = spi->dev.of_node;
        idev->name              = spi_get_device_id(spi)->name;
        idev->modes             = INDIO_DIRECT_MODE;
        idev->info              = &hi8435_info;
@@ -542,7 +538,7 @@ MODULE_DEVICE_TABLE(spi, hi8435_id);
 static struct spi_driver hi8435_driver = {
        .driver = {
                .name           = DRV_NAME,
-               .of_match_table = of_match_ptr(hi8435_dt_ids),
+               .of_match_table = hi8435_dt_ids,
        },
        .probe          = hi8435_probe,
        .id_table       = hi8435_id,
index c868655..6a17353 100644 (file)
@@ -551,7 +551,6 @@ static int hx711_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, indio_dev);
 
        indio_dev->name = "hx711";
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->info = &hx711_iio_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = hx711_chan_spec;
index 2a2fbf7..4969a5f 100644 (file)
@@ -515,7 +515,6 @@ static int imx7d_adc_probe(struct platform_device *pdev)
        init_completion(&info->completion);
 
        indio_dev->name = dev_name(dev);
-       indio_dev->dev.parent = dev;
        indio_dev->info = &imx7d_adc_iio_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = imx7d_adc_iio_channels;
index bdd7cba..5ed63e8 100644 (file)
@@ -273,7 +273,7 @@ static int ina2xx_read_raw(struct iio_dev *indio_dev,
  * Available averaging rates for ina226. The indices correspond with
  * the bit values expected by the chip (according to the ina226 datasheet,
  * table 3 AVG bit settings, found at
- * http://www.ti.com/lit/ds/symlink/ina226.pdf.
+ * https://www.ti.com/lit/ds/symlink/ina226.pdf.
  */
 static const int ina226_avg_tab[] = { 1, 4, 16, 64, 128, 256, 512, 1024 };
 
@@ -1015,8 +1015,6 @@ static int ina2xx_probe(struct i2c_client *client,
        }
 
        indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
-       indio_dev->dev.parent = &client->dev;
-       indio_dev->dev.of_node = client->dev.of_node;
        if (id->driver_data == ina226) {
                indio_dev->channels = ina226_channels;
                indio_dev->num_channels = ARRAY_SIZE(ina226_channels);
index 39c0a60..fa7ae7f 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/iopoll.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/mod_devicetable.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
 
@@ -481,7 +482,6 @@ static int ingenic_adc_probe(struct platform_device *pdev)
                return ret;
        }
 
-       iio_dev->dev.parent = dev;
        iio_dev->name = "jz-adc";
        iio_dev->modes = INDIO_DIRECT_MODE;
        iio_dev->channels = ingenic_channels;
@@ -498,7 +498,6 @@ static int ingenic_adc_probe(struct platform_device *pdev)
        return ret;
 }
 
-#ifdef CONFIG_OF
 static const struct of_device_id ingenic_adc_of_match[] = {
        { .compatible = "ingenic,jz4725b-adc", .data = &jz4725b_adc_soc_data, },
        { .compatible = "ingenic,jz4740-adc", .data = &jz4740_adc_soc_data, },
@@ -506,12 +505,11 @@ static const struct of_device_id ingenic_adc_of_match[] = {
        { },
 };
 MODULE_DEVICE_TABLE(of, ingenic_adc_of_match);
-#endif
 
 static struct platform_driver ingenic_adc_driver = {
        .driver = {
                .name = "ingenic-adc",
-               .of_match_table = of_match_ptr(ingenic_adc_of_match),
+               .of_match_table = ingenic_adc_of_match,
        },
        .probe = ingenic_adc_probe,
 };
index a6d2e1f..7539435 100644 (file)
@@ -207,7 +207,6 @@ static int mrfld_adc_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, indio_dev);
 
-       indio_dev->dev.parent = dev;
        indio_dev->name = pdev->name;
 
        indio_dev->channels = mrfld_adc_channels;
index c1fc1b6..8fb57e3 100644 (file)
@@ -198,14 +198,12 @@ static int lp8788_adc_probe(struct platform_device *pdev)
        adc->lp = lp;
        platform_set_drvdata(pdev, indio_dev);
 
-       indio_dev->dev.of_node = pdev->dev.of_node;
        ret = lp8788_iio_map_register(indio_dev, lp->pdata, adc);
        if (ret)
                return ret;
 
        mutex_init(&adc->lock);
 
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->name = pdev->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &lp8788_adc_info;
index 4c6ac66..3566990 100644 (file)
@@ -152,7 +152,6 @@ static int lpc18xx_adc_probe(struct platform_device *pdev)
        }
 
        indio_dev->name = dev_name(&pdev->dev);
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->info = &lpc18xx_adc_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = lpc18xx_adc_iio_channels;
index b896f7f..b56ce15 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/mod_devicetable.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 
@@ -196,7 +197,6 @@ static int lpc32xx_adc_probe(struct platform_device *pdev)
        init_completion(&st->completion);
 
        iodev->name = LPC32XXAD_NAME;
-       iodev->dev.parent = &pdev->dev;
        iodev->info = &lpc32xx_adc_iio_info;
        iodev->modes = INDIO_DIRECT_MODE;
        iodev->num_channels = ARRAY_SIZE(lpc32xx_adc_iio_channels);
@@ -210,19 +210,17 @@ static int lpc32xx_adc_probe(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_OF
 static const struct of_device_id lpc32xx_adc_match[] = {
        { .compatible = "nxp,lpc3220-adc" },
        {},
 };
 MODULE_DEVICE_TABLE(of, lpc32xx_adc_match);
-#endif
 
 static struct platform_driver lpc32xx_adc_driver = {
        .probe          = lpc32xx_adc_probe,
        .driver         = {
                .name   = LPC32XXAD_NAME,
-               .of_match_table = of_match_ptr(lpc32xx_adc_match),
+               .of_match_table = lpc32xx_adc_match,
        },
 };
 
index 55fab61..0e0fe88 100644 (file)
@@ -116,7 +116,6 @@ static int ltc2471_i2c_probe(struct i2c_client *client,
        data = iio_priv(indio_dev);
        data->client = client;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->name = id->name;
        indio_dev->info = &ltc2471_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index c418466..37c762f 100644 (file)
@@ -108,7 +108,6 @@ static int ltc2485_probe(struct i2c_client *client,
        i2c_set_clientdata(client, indio_dev);
        data->client = client;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->name = id->name;
        indio_dev->info = &ltc2485_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 88a3015..dd956a7 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/iio/iio.h>
 #include <linux/iio/driver.h>
 #include <linux/module.h>
-#include <linux/of.h>
+#include <linux/mod_devicetable.h>
 
 #include "ltc2497.h"
 
@@ -96,7 +96,7 @@ MODULE_DEVICE_TABLE(of, ltc2496_of_match);
 static struct spi_driver ltc2496_driver = {
        .driver = {
                .name = "ltc2496",
-               .of_match_table = of_match_ptr(ltc2496_of_match),
+               .of_match_table = ltc2496_of_match,
        },
        .probe = ltc2496_probe,
        .remove = ltc2496_remove,
index f5f7039..9b8fd9c 100644 (file)
@@ -169,7 +169,6 @@ int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev)
        struct ltc2497core_driverdata *ddata = iio_priv(indio_dev);
        int ret;
 
-       indio_dev->dev.parent = dev;
        indio_dev->name = dev_name(dev);
        indio_dev->info = &ltc2497core_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 5db63d7..1adddf5 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/iio/iio.h>
 #include <linux/iio/driver.h>
 #include <linux/module.h>
-#include <linux/of.h>
+#include <linux/mod_devicetable.h>
 
 #include "ltc2497.h"
 
@@ -98,7 +98,7 @@ MODULE_DEVICE_TABLE(of, ltc2497_of_match);
 static struct i2c_driver ltc2497_driver = {
        .driver = {
                .name = "ltc2497",
-               .of_match_table = of_match_ptr(ltc2497_of_match),
+               .of_match_table = ltc2497_of_match,
        },
        .probe = ltc2497_probe,
        .remove = ltc2497_remove,
index 02834ca..ca1dff3 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/mod_devicetable.h>
 #include <linux/spi/spi.h>
 #include <linux/delay.h>
 
@@ -79,7 +80,6 @@ static const struct spi_device_id max1027_id[] = {
 };
 MODULE_DEVICE_TABLE(spi, max1027_id);
 
-#ifdef CONFIG_OF
 static const struct of_device_id max1027_adc_dt_ids[] = {
        { .compatible = "maxim,max1027" },
        { .compatible = "maxim,max1029" },
@@ -90,7 +90,6 @@ static const struct of_device_id max1027_adc_dt_ids[] = {
        {},
 };
 MODULE_DEVICE_TABLE(of, max1027_adc_dt_ids);
-#endif
 
 #define MAX1027_V_CHAN(index, depth)                                   \
        {                                                               \
@@ -440,8 +439,6 @@ static int max1027_probe(struct spi_device *spi)
        mutex_init(&st->lock);
 
        indio_dev->name = spi_get_device_id(spi)->name;
-       indio_dev->dev.parent = &spi->dev;
-       indio_dev->dev.of_node = spi->dev.of_node;
        indio_dev->info = &max1027_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = st->info->channels;
@@ -520,7 +517,7 @@ static int max1027_probe(struct spi_device *spi)
 static struct spi_driver max1027_driver = {
        .driver = {
                .name   = "max1027",
-               .of_match_table = of_match_ptr(max1027_adc_dt_ids),
+               .of_match_table = max1027_adc_dt_ids,
        },
        .probe          = max1027_probe,
        .id_table       = max1027_id,
index 3440539..6cf2175 100644 (file)
@@ -8,6 +8,7 @@
  */
 #include <linux/delay.h>
 #include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
@@ -37,7 +38,7 @@ struct max11100_state {
        u8 buffer[3] ____cacheline_aligned;
 };
 
-static struct iio_chan_spec max11100_channels[] = {
+static const struct iio_chan_spec max11100_channels[] = {
        { /* [0] */
                .type = IIO_VOLTAGE,
                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
@@ -115,8 +116,6 @@ static int max11100_probe(struct spi_device *spi)
        state = iio_priv(indio_dev);
        state->spi = spi;
 
-       indio_dev->dev.parent = &spi->dev;
-       indio_dev->dev.of_node = spi->dev.of_node;
        indio_dev->name = "max11100";
        indio_dev->info = &max11100_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
@@ -163,7 +162,7 @@ MODULE_DEVICE_TABLE(of, max11100_ids);
 static struct spi_driver max11100_driver = {
        .driver = {
                .name   = "max11100",
-               .of_match_table = of_match_ptr(max11100_ids),
+               .of_match_table = max11100_ids,
        },
        .probe          = max11100_probe,
        .remove         = max11100_remove,
index 0c5d7aa..01b20e4 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/mod_devicetable.h>
 #include <linux/spi/spi.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/buffer.h>
@@ -225,7 +226,6 @@ static int max1118_probe(struct spi_device *spi)
        spi_set_drvdata(spi, indio_dev);
 
        indio_dev->name = spi_get_device_id(spi)->name;
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &max1118_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = max1118_channels;
@@ -281,8 +281,6 @@ static const struct spi_device_id max1118_id[] = {
 };
 MODULE_DEVICE_TABLE(spi, max1118_id);
 
-#ifdef CONFIG_OF
-
 static const struct of_device_id max1118_dt_ids[] = {
        { .compatible = "maxim,max1117" },
        { .compatible = "maxim,max1118" },
@@ -291,12 +289,10 @@ static const struct of_device_id max1118_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, max1118_dt_ids);
 
-#endif
-
 static struct spi_driver max1118_spi_driver = {
        .driver = {
                .name = "max1118",
-               .of_match_table = of_match_ptr(max1118_dt_ids),
+               .of_match_table = max1118_dt_ids,
        },
        .probe = max1118_probe,
        .remove = max1118_remove,
index 541939c..0cbbb3c 100644 (file)
@@ -192,7 +192,6 @@ static int max1241_probe(struct spi_device *spi)
                dev_dbg(dev, "no shutdown pin passed, low-power mode disabled");
 
        indio_dev->name = spi_get_device_id(spi)->name;
-       indio_dev->dev.parent = dev;
        indio_dev->info = &max1241_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = max1241_channels;
index 9d92017..420e2ec 100644 (file)
@@ -22,8 +22,8 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/property.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
@@ -1529,8 +1529,6 @@ done:
        return IRQ_HANDLED;
 }
 
-#ifdef CONFIG_OF
-
 #define MAX1363_COMPATIBLE(of_compatible, cfg) {               \
                        .compatible = of_compatible,            \
                        .data = &max1363_chip_info_tbl[cfg],    \
@@ -1578,7 +1576,6 @@ static const struct of_device_id max1363_of_match[] = {
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, max1363_of_match);
-#endif
 
 static int max1363_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
@@ -1593,7 +1590,6 @@ static int max1363_probe(struct i2c_client *client,
        if (!indio_dev)
                return -ENOMEM;
 
-       indio_dev->dev.of_node = client->dev.of_node;
        ret = iio_map_array_register(indio_dev, client->dev.platform_data);
        if (ret < 0)
                return ret;
@@ -1614,7 +1610,7 @@ static int max1363_probe(struct i2c_client *client,
        /* this is only used for device removal purposes */
        i2c_set_clientdata(client, indio_dev);
 
-       st->chip_info = of_device_get_match_data(&client->dev);
+       st->chip_info = device_get_match_data(&client->dev);
        if (!st->chip_info)
                st->chip_info = &max1363_chip_info_tbl[id->driver_data];
        st->client = client;
@@ -1652,9 +1648,6 @@ static int max1363_probe(struct i2c_client *client,
        if (ret)
                goto error_disable_reg;
 
-       /* Establish that the iio_dev is a child of the i2c device */
-       indio_dev->dev.parent = &client->dev;
-       indio_dev->dev.of_node = client->dev.of_node;
        indio_dev->name = id->name;
        indio_dev->channels = st->chip_info->channels;
        indio_dev->num_channels = st->chip_info->num_channels;
@@ -1760,7 +1753,7 @@ MODULE_DEVICE_TABLE(i2c, max1363_id);
 static struct i2c_driver max1363_driver = {
        .driver = {
                .name = "max1363",
-               .of_match_table = of_match_ptr(max1363_of_match),
+               .of_match_table = max1363_of_match,
        },
        .probe = max1363_probe,
        .remove = max1363_remove,
index 04d5ff7..d7f150a 100644 (file)
@@ -545,8 +545,6 @@ static int max9611_probe(struct i2c_client *client,
        if (ret)
                return ret;
 
-       indio_dev->dev.parent   = &client->dev;
-       indio_dev->dev.of_node  = client->dev.of_node;
        indio_dev->name         = of_id->data;
        indio_dev->modes        = INDIO_DIRECT_MODE;
        indio_dev->info         = &indio_info;
index 2c0eb5d..8d1cff2 100644 (file)
  * MCP3553
  *
  * Datasheet can be found here:
- * http://ww1.microchip.com/downloads/en/DeviceDoc/21293C.pdf  mcp3001
- * http://ww1.microchip.com/downloads/en/DeviceDoc/21294E.pdf  mcp3002
- * http://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf  mcp3004/08
+ * https://ww1.microchip.com/downloads/en/DeviceDoc/21293C.pdf  mcp3001
+ * https://ww1.microchip.com/downloads/en/DeviceDoc/21294E.pdf  mcp3002
+ * https://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf  mcp3004/08
  * http://ww1.microchip.com/downloads/en/DeviceDoc/21290D.pdf  mcp3201
  * http://ww1.microchip.com/downloads/en/DeviceDoc/21034D.pdf  mcp3202
  * http://ww1.microchip.com/downloads/en/DeviceDoc/21298c.pdf  mcp3204/08
- * http://ww1.microchip.com/downloads/en/DeviceDoc/21700E.pdf  mcp3301
+ * https://ww1.microchip.com/downloads/en/DeviceDoc/21700E.pdf  mcp3301
  * http://ww1.microchip.com/downloads/en/DeviceDoc/21950D.pdf  mcp3550/1/3
  */
 
@@ -41,6 +41,7 @@
 #include <linux/delay.h>
 #include <linux/spi/spi.h>
 #include <linux/module.h>
+#include <linux/mod_devicetable.h>
 #include <linux/iio/iio.h>
 #include <linux/regulator/consumer.h>
 
@@ -384,8 +385,6 @@ static int mcp320x_probe(struct spi_device *spi)
        adc = iio_priv(indio_dev);
        adc->spi = spi;
 
-       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 = &mcp320x_info;
@@ -471,7 +470,6 @@ static int mcp320x_remove(struct spi_device *spi)
        return 0;
 }
 
-#if defined(CONFIG_OF)
 static const struct of_device_id mcp320x_dt_ids[] = {
        /* NOTE: The use of compatibles with no vendor prefix is deprecated. */
        { .compatible = "mcp3001" },
@@ -499,7 +497,6 @@ static const struct of_device_id mcp320x_dt_ids[] = {
        { }
 };
 MODULE_DEVICE_TABLE(of, mcp320x_dt_ids);
-#endif
 
 static const struct spi_device_id mcp320x_id[] = {
        { "mcp3001", mcp3001 },
@@ -522,7 +519,7 @@ MODULE_DEVICE_TABLE(spi, mcp320x_id);
 static struct spi_driver mcp320x_driver = {
        .driver = {
                .name = "mcp320x",
-               .of_match_table = of_match_ptr(mcp320x_dt_ids),
+               .of_match_table = mcp320x_dt_ids,
        },
        .probe = mcp320x_probe,
        .remove = mcp320x_remove,
index d86c0b5..5f1706d 100644 (file)
@@ -6,8 +6,8 @@
  * Author: Angelo Compagnucci <angelo.compagnucci@gmail.com>
  *
  * Datasheet: http://ww1.microchip.com/downloads/en/devicedoc/22088b.pdf
- *            http://ww1.microchip.com/downloads/en/DeviceDoc/22226a.pdf
- *            http://ww1.microchip.com/downloads/en/DeviceDoc/22072b.pdf
+ *            https://ww1.microchip.com/downloads/en/DeviceDoc/22226a.pdf
+ *            https://ww1.microchip.com/downloads/en/DeviceDoc/22072b.pdf
  *
  * This driver exports the value of analog input voltage to sysfs, the
  * voltage unit is nV.
@@ -16,9 +16,9 @@
 #include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
+#include <linux/mod_devicetable.h>
 #include <linux/delay.h>
 #include <linux/sysfs.h>
-#include <linux/of.h>
 #include <asm/unaligned.h>
 
 #include <linux/iio/iio.h>
@@ -347,8 +347,6 @@ static int mcp3422_probe(struct i2c_client *client,
 
        mutex_init(&adc->lock);
 
-       indio_dev->dev.parent = &client->dev;
-       indio_dev->dev.of_node = client->dev.of_node;
        indio_dev->name = dev_name(&client->dev);
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &mcp3422_info;
@@ -404,18 +402,16 @@ static const struct i2c_device_id mcp3422_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, mcp3422_id);
 
-#ifdef CONFIG_OF
 static const struct of_device_id mcp3422_of_match[] = {
        { .compatible = "mcp3422" },
        { }
 };
 MODULE_DEVICE_TABLE(of, mcp3422_of_match);
-#endif
 
 static struct i2c_driver mcp3422_driver = {
        .driver = {
                .name = "mcp3422",
-               .of_match_table = of_match_ptr(mcp3422_of_match),
+               .of_match_table = mcp3422_of_match,
        },
        .probe = mcp3422_probe,
        .id_table = mcp3422_id,
index dd52f08..e573da5 100644 (file)
@@ -293,8 +293,6 @@ static int mcp3911_probe(struct spi_device *spi)
        if (ret)
                goto clk_disable;
 
-       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 = &mcp3911_info;
index 196c822..42ea8bc 100644 (file)
@@ -110,7 +110,6 @@ static int men_z188_probe(struct mcb_device *dev,
 
        adc = iio_priv(indio_dev);
        indio_dev->name = "z188-adc";
-       indio_dev->dev.parent = &dev->dev;
        indio_dev->info = &z188_adc_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = z188_adc_iio_channels;
index 22a470d..93c2252 100644 (file)
@@ -1208,8 +1208,6 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
        priv->param = match_data->param;
 
        indio_dev->name = match_data->name;
-       indio_dev->dev.parent = &pdev->dev;
-       indio_dev->dev.of_node = pdev->dev.of_node;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &meson_sar_adc_iio_info;
 
index a4776d9..ac415cb 100644 (file)
@@ -245,7 +245,6 @@ static int mt6577_auxadc_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        adc_dev = iio_priv(indio_dev);
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->name = dev_name(&pdev->dev);
        indio_dev->info = &mt6577_auxadc_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 9d2f74c..30e29f4 100644 (file)
@@ -568,8 +568,6 @@ static bool mxs_lradc_adc_validate_scan_mask(struct iio_dev *iio,
 
 static const struct iio_buffer_setup_ops mxs_lradc_adc_buffer_ops = {
        .preenable = &mxs_lradc_adc_buffer_preenable,
-       .postenable = &iio_triggered_buffer_postenable,
-       .predisable = &iio_triggered_buffer_predisable,
        .postdisable = &mxs_lradc_adc_buffer_postdisable,
        .validate_scan_mask = &mxs_lradc_adc_validate_scan_mask,
 };
@@ -722,7 +720,6 @@ static int mxs_lradc_adc_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, iio);
 
        iio->name = pdev->name;
-       iio->dev.parent = dev;
        iio->dev.of_node = dev->parent->of_node;
        iio->info = &mxs_lradc_adc_iio_info;
        iio->modes = INDIO_DIRECT_MODE;
index 5725791..07c8543 100644 (file)
@@ -430,8 +430,6 @@ static int nau7802_probe(struct i2c_client *client,
 
        i2c_set_clientdata(client, indio_dev);
 
-       indio_dev->dev.parent = &client->dev;
-       indio_dev->dev.of_node = client->dev.of_node;
        indio_dev->name = dev_name(&client->dev);
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &nau7802_info;
index 83bad2d..d9d1059 100644 (file)
@@ -261,7 +261,6 @@ static int npcm_adc_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, indio_dev);
        indio_dev->name = dev_name(&pdev->dev);
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->info = &npcm_adc_iio_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = npcm_adc_iio_channels;
index 46e595e..768453c 100644 (file)
@@ -593,7 +593,6 @@ static int palmas_gpadc_probe(struct platform_device *pdev)
        adc->extended_delay = gpadc_pdata->extended_delay;
 
        indio_dev->name = MOD_NAME;
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->info = &palmas_gpadc_iio_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = palmas_gpadc_iio_channel;
index c599ffa..368ee4e 100644 (file)
@@ -933,8 +933,6 @@ static int pm8xxx_xoadc_probe(struct platform_device *pdev)
                goto out_disable_vref;
        }
 
-       indio_dev->dev.parent = dev;
-       indio_dev->dev.of_node = np;
        indio_dev->name = variant->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &pm8xxx_xoadc_info;
index 21fdcde..b4b73c9 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018, 2020, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/bitops.h>
@@ -23,6 +23,7 @@
 
 #define ADC5_USR_REVISION1                     0x0
 #define ADC5_USR_STATUS1                       0x8
+#define ADC5_USR_STATUS1_CONV_FAULT            BIT(7)
 #define ADC5_USR_STATUS1_REQ_STS               BIT(1)
 #define ADC5_USR_STATUS1_EOC                   BIT(0)
 #define ADC5_USR_STATUS1_REQ_STS_EOC_MASK      0x3
@@ -65,6 +66,9 @@
 
 #define ADC5_USR_IBAT_DATA1                    0x53
 
+#define ADC_CHANNEL_OFFSET                     0x8
+#define ADC_CHANNEL_MASK                       GENMASK(7, 0)
+
 /*
  * Conversion time varies based on the decimation, clock rate, fast average
  * samples and measurements queued across different VADC peripherals.
 #define ADC5_HW_SETTLE_DIFF_MINOR              3
 #define ADC5_HW_SETTLE_DIFF_MAJOR              5
 
+/* For PMIC7 */
+#define ADC_APP_SID                            0x40
+#define ADC_APP_SID_MASK                       GENMASK(3, 0)
+#define ADC7_CONV_TIMEOUT                      msecs_to_jiffies(10)
+
 enum adc5_cal_method {
        ADC5_NO_CAL = 0,
        ADC5_RATIOMETRIC_CAL,
@@ -96,6 +105,7 @@ enum adc5_cal_val {
  * @cal_method: calibration method.
  * @cal_val: calibration value
  * @decimation: sampling rate supported for the channel.
+ * @sid: slave id of PMIC owning the channel, for PMIC7.
  * @prescale: channel scaling performed on the input signal.
  * @hw_settle_time: the time between AMUX being configured and the
  *     start of conversion.
@@ -110,6 +120,7 @@ struct adc5_channel_prop {
        enum adc5_cal_method    cal_method;
        enum adc5_cal_val       cal_val;
        unsigned int            decimation;
+       unsigned int            sid;
        unsigned int            prescale;
        unsigned int            hw_settle_time;
        unsigned int            avg_samples;
@@ -165,6 +176,11 @@ static int adc5_write(struct adc5_chip *adc, u16 offset, u8 *data, int len)
        return regmap_bulk_write(adc->regmap, adc->base + offset, data, len);
 }
 
+static int adc5_masked_write(struct adc5_chip *adc, u16 offset, u8 mask, u8 val)
+{
+       return regmap_update_bits(adc->regmap, adc->base + offset, mask, val);
+}
+
 static int adc5_prescaling_from_dt(u32 num, u32 den)
 {
        unsigned int pre;
@@ -230,11 +246,11 @@ static int adc5_read_voltage_data(struct adc5_chip *adc, u16 *data)
        *data = (rslt_msb << 8) | rslt_lsb;
 
        if (*data == ADC5_USR_DATA_CHECK) {
-               pr_err("Invalid data:0x%x\n", *data);
+               dev_err(adc->dev, "Invalid data:0x%x\n", *data);
                return -EINVAL;
        }
 
-       pr_debug("voltage raw code:0x%x\n", *data);
+       dev_dbg(adc->dev, "voltage raw code:0x%x\n", *data);
 
        return 0;
 }
@@ -285,7 +301,7 @@ static int adc5_configure(struct adc5_chip *adc,
 
        /* Read registers 0x42 through 0x46 */
        ret = adc5_read(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf));
-       if (ret < 0)
+       if (ret)
                return ret;
 
        /* Digital param selection */
@@ -314,6 +330,47 @@ static int adc5_configure(struct adc5_chip *adc,
        return adc5_write(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf));
 }
 
+static int adc7_configure(struct adc5_chip *adc,
+                       struct adc5_channel_prop *prop)
+{
+       int ret;
+       u8 conv_req = 0, buf[4];
+
+       ret = adc5_masked_write(adc, ADC_APP_SID, ADC_APP_SID_MASK, prop->sid);
+       if (ret)
+               return ret;
+
+       ret = adc5_read(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf));
+       if (ret)
+               return ret;
+
+       /* Digital param selection */
+       adc5_update_dig_param(adc, prop, &buf[0]);
+
+       /* Update fast average sample value */
+       buf[1] &= ~ADC5_USR_FAST_AVG_CTL_SAMPLES_MASK;
+       buf[1] |= prop->avg_samples;
+
+       /* Select ADC channel */
+       buf[2] = prop->channel;
+
+       /* Select HW settle delay for channel */
+       buf[3] &= ~ADC5_USR_HW_SETTLE_DELAY_MASK;
+       buf[3] |= prop->hw_settle_time;
+
+       /* Select CONV request */
+       conv_req = ADC5_USR_CONV_REQ_REQ;
+
+       if (!adc->poll_eoc)
+               reinit_completion(&adc->complete);
+
+       ret = adc5_write(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf));
+       if (ret)
+               return ret;
+
+       return adc5_write(adc, ADC5_USR_CONV_REQ, &conv_req, 1);
+}
+
 static int adc5_do_conversion(struct adc5_chip *adc,
                        struct adc5_channel_prop *prop,
                        struct iio_chan_spec const *chan,
@@ -325,24 +382,24 @@ static int adc5_do_conversion(struct adc5_chip *adc,
 
        ret = adc5_configure(adc, prop);
        if (ret) {
-               pr_err("ADC configure failed with %d\n", ret);
+               dev_err(adc->dev, "ADC configure failed with %d\n", ret);
                goto unlock;
        }
 
        if (adc->poll_eoc) {
                ret = adc5_poll_wait_eoc(adc);
-               if (ret < 0) {
-                       pr_err("EOC bit not set\n");
+               if (ret) {
+                       dev_err(adc->dev, "EOC bit not set\n");
                        goto unlock;
                }
        } else {
                ret = wait_for_completion_timeout(&adc->complete,
                                                        ADC5_CONV_TIMEOUT);
                if (!ret) {
-                       pr_debug("Did not get completion timeout.\n");
+                       dev_dbg(adc->dev, "Did not get completion timeout.\n");
                        ret = adc5_poll_wait_eoc(adc);
-                       if (ret < 0) {
-                               pr_err("EOC bit not set\n");
+                       if (ret) {
+                               dev_err(adc->dev, "EOC bit not set\n");
                                goto unlock;
                        }
                }
@@ -355,6 +412,48 @@ unlock:
        return ret;
 }
 
+static int adc7_do_conversion(struct adc5_chip *adc,
+                       struct adc5_channel_prop *prop,
+                       struct iio_chan_spec const *chan,
+                       u16 *data_volt, u16 *data_cur)
+{
+       int ret;
+       u8 status;
+
+       mutex_lock(&adc->lock);
+
+       ret = adc7_configure(adc, prop);
+       if (ret) {
+               dev_err(adc->dev, "ADC configure failed with %d\n", ret);
+               goto unlock;
+       }
+
+       /* No support for polling mode at present */
+       wait_for_completion_timeout(&adc->complete, ADC7_CONV_TIMEOUT);
+
+       ret = adc5_read(adc, ADC5_USR_STATUS1, &status, 1);
+       if (ret)
+               goto unlock;
+
+       if (status & ADC5_USR_STATUS1_CONV_FAULT) {
+               dev_err(adc->dev, "Unexpected conversion fault\n");
+               ret = -EIO;
+               goto unlock;
+       }
+
+       ret = adc5_read_voltage_data(adc, data_volt);
+
+unlock:
+       mutex_unlock(&adc->lock);
+
+       return ret;
+}
+
+typedef int (*adc_do_conversion)(struct adc5_chip *adc,
+                       struct adc5_channel_prop *prop,
+                       struct iio_chan_spec const *chan,
+                       u16 *data_volt, u16 *data_cur);
+
 static irqreturn_t adc5_isr(int irq, void *dev_id)
 {
        struct adc5_chip *adc = dev_id;
@@ -377,9 +476,25 @@ static int adc5_of_xlate(struct iio_dev *indio_dev,
        return -EINVAL;
 }
 
-static int adc5_read_raw(struct iio_dev *indio_dev,
+static int adc7_of_xlate(struct iio_dev *indio_dev,
+                               const struct of_phandle_args *iiospec)
+{
+       struct adc5_chip *adc = iio_priv(indio_dev);
+       int i, v_channel;
+
+       for (i = 0; i < adc->nchannels; i++) {
+               v_channel = (adc->chan_props[i].sid << ADC_CHANNEL_OFFSET) |
+                       adc->chan_props[i].channel;
+               if (v_channel == iiospec->args[0])
+                       return i;
+       }
+
+       return -EINVAL;
+}
+
+static int adc_read_raw_common(struct iio_dev *indio_dev,
                         struct iio_chan_spec const *chan, int *val, int *val2,
-                        long mask)
+                        long mask, adc_do_conversion do_conv)
 {
        struct adc5_chip *adc = iio_priv(indio_dev);
        struct adc5_channel_prop *prop;
@@ -390,8 +505,8 @@ static int adc5_read_raw(struct iio_dev *indio_dev,
 
        switch (mask) {
        case IIO_CHAN_INFO_PROCESSED:
-               ret = adc5_do_conversion(adc, prop, chan,
-                               &adc_code_volt, &adc_code_cur);
+               ret = do_conv(adc, prop, chan,
+                                       &adc_code_volt, &adc_code_cur);
                if (ret)
                        return ret;
 
@@ -406,8 +521,22 @@ static int adc5_read_raw(struct iio_dev *indio_dev,
        default:
                return -EINVAL;
        }
+}
 
-       return 0;
+static int adc5_read_raw(struct iio_dev *indio_dev,
+                        struct iio_chan_spec const *chan, int *val, int *val2,
+                        long mask)
+{
+       return adc_read_raw_common(indio_dev, chan, val, val2,
+                               mask, adc5_do_conversion);
+}
+
+static int adc7_read_raw(struct iio_dev *indio_dev,
+                        struct iio_chan_spec const *chan, int *val, int *val2,
+                        long mask)
+{
+       return adc_read_raw_common(indio_dev, chan, val, val2,
+                               mask, adc7_do_conversion);
 }
 
 static const struct iio_info adc5_info = {
@@ -415,6 +544,11 @@ static const struct iio_info adc5_info = {
        .of_xlate = adc5_of_xlate,
 };
 
+static const struct iio_info adc7_info = {
+       .read_raw = adc7_read_raw,
+       .of_xlate = adc7_of_xlate,
+};
+
 struct adc5_channels {
        const char *datasheet_name;
        unsigned int prescale_index;
@@ -477,6 +611,39 @@ static const struct adc5_channels adc5_chans_pmic[ADC5_MAX_CHANNEL] = {
                                        SCALE_HW_CALIB_PM5_SMB_TEMP)
 };
 
+static const struct adc5_channels adc7_chans_pmic[ADC5_MAX_CHANNEL] = {
+       [ADC7_REF_GND]          = ADC5_CHAN_VOLT("ref_gnd", 0,
+                                       SCALE_HW_CALIB_DEFAULT)
+       [ADC7_1P25VREF]         = ADC5_CHAN_VOLT("vref_1p25", 0,
+                                       SCALE_HW_CALIB_DEFAULT)
+       [ADC7_VPH_PWR]          = ADC5_CHAN_VOLT("vph_pwr", 1,
+                                       SCALE_HW_CALIB_DEFAULT)
+       [ADC7_VBAT_SNS]         = ADC5_CHAN_VOLT("vbat_sns", 3,
+                                       SCALE_HW_CALIB_DEFAULT)
+       [ADC7_DIE_TEMP]         = ADC5_CHAN_TEMP("die_temp", 0,
+                                       SCALE_HW_CALIB_PMIC_THERM_PM7)
+       [ADC7_AMUX_THM1_100K_PU] = ADC5_CHAN_TEMP("amux_thm1_pu2", 0,
+                                       SCALE_HW_CALIB_THERM_100K_PU_PM7)
+       [ADC7_AMUX_THM2_100K_PU] = ADC5_CHAN_TEMP("amux_thm2_pu2", 0,
+                                       SCALE_HW_CALIB_THERM_100K_PU_PM7)
+       [ADC7_AMUX_THM3_100K_PU] = ADC5_CHAN_TEMP("amux_thm3_pu2", 0,
+                                       SCALE_HW_CALIB_THERM_100K_PU_PM7)
+       [ADC7_AMUX_THM4_100K_PU] = ADC5_CHAN_TEMP("amux_thm4_pu2", 0,
+                                       SCALE_HW_CALIB_THERM_100K_PU_PM7)
+       [ADC7_AMUX_THM5_100K_PU] = ADC5_CHAN_TEMP("amux_thm5_pu2", 0,
+                                       SCALE_HW_CALIB_THERM_100K_PU_PM7)
+       [ADC7_AMUX_THM6_100K_PU] = ADC5_CHAN_TEMP("amux_thm6_pu2", 0,
+                                       SCALE_HW_CALIB_THERM_100K_PU_PM7)
+       [ADC7_GPIO1_100K_PU]    = ADC5_CHAN_TEMP("gpio1_pu2", 0,
+                                       SCALE_HW_CALIB_THERM_100K_PU_PM7)
+       [ADC7_GPIO2_100K_PU]    = ADC5_CHAN_TEMP("gpio2_pu2", 0,
+                                       SCALE_HW_CALIB_THERM_100K_PU_PM7)
+       [ADC7_GPIO3_100K_PU]    = ADC5_CHAN_TEMP("gpio3_pu2", 0,
+                                       SCALE_HW_CALIB_THERM_100K_PU_PM7)
+       [ADC7_GPIO4_100K_PU]    = ADC5_CHAN_TEMP("gpio4_pu2", 0,
+                                       SCALE_HW_CALIB_THERM_100K_PU_PM7)
+};
+
 static const struct adc5_channels adc5_chans_rev2[ADC5_MAX_CHANNEL] = {
        [ADC5_REF_GND]          = ADC5_CHAN_VOLT("ref_gnd", 0,
                                        SCALE_HW_CALIB_DEFAULT)
@@ -511,6 +678,7 @@ static int adc5_get_dt_channel_data(struct adc5_chip *adc,
 {
        const char *name = node->name, *channel_name;
        u32 chan, value, varr[2];
+       u32 sid = 0;
        int ret;
        struct device *dev = adc->dev;
 
@@ -520,6 +688,15 @@ static int adc5_get_dt_channel_data(struct adc5_chip *adc,
                return ret;
        }
 
+       /* Value read from "reg" is virtual channel number */
+
+       /* virtual channel number = sid << 8 | channel number */
+
+       if (adc->data->info == &adc7_info) {
+               sid = chan >> ADC_CHANNEL_OFFSET;
+               chan = chan & ADC_CHANNEL_MASK;
+       }
+
        if (chan > ADC5_PARALLEL_ISENSE_VBAT_IDATA ||
            !data->adc_chans[chan].datasheet_name) {
                dev_err(dev, "%s invalid channel number %d\n", name, chan);
@@ -528,11 +705,12 @@ static int adc5_get_dt_channel_data(struct adc5_chip *adc,
 
        /* the channel has DT description */
        prop->channel = chan;
+       prop->sid = sid;
 
        channel_name = of_get_property(node,
                                "label", NULL) ? : node->name;
        if (!channel_name) {
-               pr_err("Invalid channel name\n");
+               dev_err(dev, "Invalid channel name\n");
                return -EINVAL;
        }
        prop->datasheet_name = channel_name;
@@ -570,16 +748,17 @@ static int adc5_get_dt_channel_data(struct adc5_chip *adc,
 
                ret = adc5_read(adc, ADC5_USR_REVISION1, dig_version,
                                                        sizeof(dig_version));
-               if (ret < 0) {
+               if (ret) {
                        dev_err(dev, "Invalid dig version read %d\n", ret);
                        return ret;
                }
 
-               pr_debug("dig_ver:minor:%d, major:%d\n", dig_version[0],
+               dev_dbg(dev, "dig_ver:minor:%d, major:%d\n", dig_version[0],
                                                dig_version[1]);
                /* Digital controller >= 5.3 have hw_settle_2 option */
-               if (dig_version[0] >= ADC5_HW_SETTLE_DIFF_MINOR &&
-                       dig_version[1] >= ADC5_HW_SETTLE_DIFF_MAJOR)
+               if ((dig_version[0] >= ADC5_HW_SETTLE_DIFF_MINOR &&
+                       dig_version[1] >= ADC5_HW_SETTLE_DIFF_MAJOR) ||
+                       adc->data->info == &adc7_info)
                        ret = adc5_hw_settle_time_from_dt(value,
                                                        data->hw_settle_2);
                else
@@ -629,6 +808,7 @@ static const struct adc5_data adc5_data_pmic = {
        .full_scale_code_volt = 0x70e4,
        .full_scale_code_cur = 0x2710,
        .adc_chans = adc5_chans_pmic,
+       .info = &adc5_info,
        .decimation = (unsigned int [ADC5_DECIMATION_SAMPLES_MAX])
                                {250, 420, 840},
        .hw_settle_1 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX])
@@ -639,10 +819,23 @@ static const struct adc5_data adc5_data_pmic = {
                                1, 2, 4, 8, 16, 32, 64, 128},
 };
 
+static const struct adc5_data adc7_data_pmic = {
+       .full_scale_code_volt = 0x70e4,
+       .adc_chans = adc7_chans_pmic,
+       .info = &adc7_info,
+       .decimation = (unsigned int [ADC5_DECIMATION_SAMPLES_MAX])
+                               {85, 340, 1360},
+       .hw_settle_2 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX])
+                               {15, 100, 200, 300, 400, 500, 600, 700,
+                               1000, 2000, 4000, 8000, 16000, 32000,
+                               64000, 128000},
+};
+
 static const struct adc5_data adc5_data_pmic_rev2 = {
        .full_scale_code_volt = 0x4000,
        .full_scale_code_cur = 0x1800,
        .adc_chans = adc5_chans_rev2,
+       .info = &adc5_info,
        .decimation = (unsigned int [ADC5_DECIMATION_SAMPLES_MAX])
                                {256, 512, 1024},
        .hw_settle_1 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX])
@@ -659,6 +852,10 @@ static const struct of_device_id adc5_match_table[] = {
                .data = &adc5_data_pmic,
        },
        {
+               .compatible = "qcom,spmi-adc7",
+               .data = &adc7_data_pmic,
+       },
+       {
                .compatible = "qcom,spmi-adc-rev2",
                .data = &adc5_data_pmic_rev2,
        },
@@ -752,12 +949,13 @@ static int adc5_probe(struct platform_device *pdev)
        adc->regmap = regmap;
        adc->dev = dev;
        adc->base = reg;
+
        init_completion(&adc->complete);
        mutex_init(&adc->lock);
 
        ret = adc5_get_dt_data(adc, node);
        if (ret) {
-               pr_err("adc get dt data failed\n");
+               dev_err(dev, "adc get dt data failed\n");
                return ret;
        }
 
@@ -773,11 +971,9 @@ static int adc5_probe(struct platform_device *pdev)
                        return ret;
        }
 
-       indio_dev->dev.parent = dev;
-       indio_dev->dev.of_node = node;
        indio_dev->name = pdev->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
-       indio_dev->info = &adc5_info;
+       indio_dev->info = adc->data->info;
        indio_dev->channels = adc->iio_chans;
        indio_dev->num_channels = adc->nchannels;
 
index 46858ed..acbda66 100644 (file)
@@ -553,8 +553,6 @@ static int iadc_probe(struct platform_device *pdev)
                return ret;
        }
 
-       indio_dev->dev.parent = dev;
-       indio_dev->dev.of_node = node;
        indio_dev->name = pdev->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &iadc_info;
index 203ad59..b0388f8 100644 (file)
@@ -907,8 +907,6 @@ static int vadc_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       indio_dev->dev.parent = dev;
-       indio_dev->dev.of_node = node;
        indio_dev->name = pdev->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &vadc_info;
index 2bb78d1..5113aaa 100644 (file)
@@ -89,6 +89,195 @@ static const struct vadc_map_pt adcmap_100k_104ef_104fb_1875_vref[] = {
        { 46,   125000 },
 };
 
+static const struct vadc_map_pt adcmap7_die_temp[] = {
+       { 433700, 1967},
+       { 473100, 1964},
+       { 512400, 1957},
+       { 551500, 1949},
+       { 590500, 1940},
+       { 629300, 1930},
+       { 667900, 1921},
+       { 706400, 1910},
+       { 744600, 1896},
+       { 782500, 1878},
+       { 820100, 1859},
+       { 857300, 0},
+};
+
+/*
+ * Resistance to temperature table for 100k pull up for NTCG104EF104.
+ */
+static const struct vadc_map_pt adcmap7_100k[] = {
+       { 4250657, -40960 },
+       { 3962085, -39936 },
+       { 3694875, -38912 },
+       { 3447322, -37888 },
+       { 3217867, -36864 },
+       { 3005082, -35840 },
+       { 2807660, -34816 },
+       { 2624405, -33792 },
+       { 2454218, -32768 },
+       { 2296094, -31744 },
+       { 2149108, -30720 },
+       { 2012414, -29696 },
+       { 1885232, -28672 },
+       { 1766846, -27648 },
+       { 1656598, -26624 },
+       { 1553884, -25600 },
+       { 1458147, -24576 },
+       { 1368873, -23552 },
+       { 1285590, -22528 },
+       { 1207863, -21504 },
+       { 1135290, -20480 },
+       { 1067501, -19456 },
+       { 1004155, -18432 },
+       { 944935, -17408 },
+       { 889550, -16384 },
+       { 837731, -15360 },
+       { 789229, -14336 },
+       { 743813, -13312 },
+       { 701271, -12288 },
+       { 661405, -11264 },
+       { 624032, -10240 },
+       { 588982, -9216 },
+       { 556100, -8192 },
+       { 525239, -7168 },
+       { 496264, -6144 },
+       { 469050, -5120 },
+       { 443480, -4096 },
+       { 419448, -3072 },
+       { 396851, -2048 },
+       { 375597, -1024 },
+       { 355598, 0 },
+       { 336775, 1024 },
+       { 319052, 2048 },
+       { 302359, 3072 },
+       { 286630, 4096 },
+       { 271806, 5120 },
+       { 257829, 6144 },
+       { 244646, 7168 },
+       { 232209, 8192 },
+       { 220471, 9216 },
+       { 209390, 10240 },
+       { 198926, 11264 },
+       { 189040, 12288 },
+       { 179698, 13312 },
+       { 170868, 14336 },
+       { 162519, 15360 },
+       { 154622, 16384 },
+       { 147150, 17408 },
+       { 140079, 18432 },
+       { 133385, 19456 },
+       { 127046, 20480 },
+       { 121042, 21504 },
+       { 115352, 22528 },
+       { 109960, 23552 },
+       { 104848, 24576 },
+       { 100000, 25600 },
+       { 95402, 26624 },
+       { 91038, 27648 },
+       { 86897, 28672 },
+       { 82965, 29696 },
+       { 79232, 30720 },
+       { 75686, 31744 },
+       { 72316, 32768 },
+       { 69114, 33792 },
+       { 66070, 34816 },
+       { 63176, 35840 },
+       { 60423, 36864 },
+       { 57804, 37888 },
+       { 55312, 38912 },
+       { 52940, 39936 },
+       { 50681, 40960 },
+       { 48531, 41984 },
+       { 46482, 43008 },
+       { 44530, 44032 },
+       { 42670, 45056 },
+       { 40897, 46080 },
+       { 39207, 47104 },
+       { 37595, 48128 },
+       { 36057, 49152 },
+       { 34590, 50176 },
+       { 33190, 51200 },
+       { 31853, 52224 },
+       { 30577, 53248 },
+       { 29358, 54272 },
+       { 28194, 55296 },
+       { 27082, 56320 },
+       { 26020, 57344 },
+       { 25004, 58368 },
+       { 24033, 59392 },
+       { 23104, 60416 },
+       { 22216, 61440 },
+       { 21367, 62464 },
+       { 20554, 63488 },
+       { 19776, 64512 },
+       { 19031, 65536 },
+       { 18318, 66560 },
+       { 17636, 67584 },
+       { 16982, 68608 },
+       { 16355, 69632 },
+       { 15755, 70656 },
+       { 15180, 71680 },
+       { 14628, 72704 },
+       { 14099, 73728 },
+       { 13592, 74752 },
+       { 13106, 75776 },
+       { 12640, 76800 },
+       { 12192, 77824 },
+       { 11762, 78848 },
+       { 11350, 79872 },
+       { 10954, 80896 },
+       { 10574, 81920 },
+       { 10209, 82944 },
+       { 9858, 83968 },
+       { 9521, 84992 },
+       { 9197, 86016 },
+       { 8886, 87040 },
+       { 8587, 88064 },
+       { 8299, 89088 },
+       { 8023, 90112 },
+       { 7757, 91136 },
+       { 7501, 92160 },
+       { 7254, 93184 },
+       { 7017, 94208 },
+       { 6789, 95232 },
+       { 6570, 96256 },
+       { 6358, 97280 },
+       { 6155, 98304 },
+       { 5959, 99328 },
+       { 5770, 100352 },
+       { 5588, 101376 },
+       { 5412, 102400 },
+       { 5243, 103424 },
+       { 5080, 104448 },
+       { 4923, 105472 },
+       { 4771, 106496 },
+       { 4625, 107520 },
+       { 4484, 108544 },
+       { 4348, 109568 },
+       { 4217, 110592 },
+       { 4090, 111616 },
+       { 3968, 112640 },
+       { 3850, 113664 },
+       { 3736, 114688 },
+       { 3626, 115712 },
+       { 3519, 116736 },
+       { 3417, 117760 },
+       { 3317, 118784 },
+       { 3221, 119808 },
+       { 3129, 120832 },
+       { 3039, 121856 },
+       { 2952, 122880 },
+       { 2868, 123904 },
+       { 2787, 124928 },
+       { 2709, 125952 },
+       { 2633, 126976 },
+       { 2560, 128000 },
+       { 2489, 129024 },
+       { 2420, 130048 }
+};
+
 static int qcom_vadc_scale_hw_calib_volt(
                                const struct vadc_prescale_ratio *prescale,
                                const struct adc5_data *data,
@@ -97,6 +286,10 @@ static int qcom_vadc_scale_hw_calib_therm(
                                const struct vadc_prescale_ratio *prescale,
                                const struct adc5_data *data,
                                u16 adc_code, int *result_mdec);
+static int qcom_vadc7_scale_hw_calib_therm(
+                               const struct vadc_prescale_ratio *prescale,
+                               const struct adc5_data *data,
+                               u16 adc_code, int *result_mdec);
 static int qcom_vadc_scale_hw_smb_temp(
                                const struct vadc_prescale_ratio *prescale,
                                const struct adc5_data *data,
@@ -109,12 +302,20 @@ static int qcom_vadc_scale_hw_calib_die_temp(
                                const struct vadc_prescale_ratio *prescale,
                                const struct adc5_data *data,
                                u16 adc_code, int *result_mdec);
+static int qcom_vadc7_scale_hw_calib_die_temp(
+                               const struct vadc_prescale_ratio *prescale,
+                               const struct adc5_data *data,
+                               u16 adc_code, int *result_mdec);
 
 static struct qcom_adc5_scale_type scale_adc5_fn[] = {
        [SCALE_HW_CALIB_DEFAULT] = {qcom_vadc_scale_hw_calib_volt},
        [SCALE_HW_CALIB_THERM_100K_PULLUP] = {qcom_vadc_scale_hw_calib_therm},
        [SCALE_HW_CALIB_XOTHERM] = {qcom_vadc_scale_hw_calib_therm},
+       [SCALE_HW_CALIB_THERM_100K_PU_PM7] = {
+                                       qcom_vadc7_scale_hw_calib_therm},
        [SCALE_HW_CALIB_PMIC_THERM] = {qcom_vadc_scale_hw_calib_die_temp},
+       [SCALE_HW_CALIB_PMIC_THERM_PM7] = {
+                                       qcom_vadc7_scale_hw_calib_die_temp},
        [SCALE_HW_CALIB_PM5_CHG_TEMP] = {qcom_vadc_scale_hw_chg5_temp},
        [SCALE_HW_CALIB_PM5_SMB_TEMP] = {qcom_vadc_scale_hw_smb_temp},
 };
@@ -291,6 +492,32 @@ static int qcom_vadc_scale_code_voltage_factor(u16 adc_code,
        return (int) voltage;
 }
 
+static int qcom_vadc7_scale_hw_calib_therm(
+                               const struct vadc_prescale_ratio *prescale,
+                               const struct adc5_data *data,
+                               u16 adc_code, int *result_mdec)
+{
+       s64 resistance = adc_code;
+       int ret, result;
+
+       if (adc_code >= RATIO_MAX_ADC7)
+               return -EINVAL;
+
+       /* (ADC code * R_PULLUP (100Kohm)) / (full_scale_code - ADC code)*/
+       resistance *= R_PU_100K;
+       resistance = div64_s64(resistance, RATIO_MAX_ADC7 - adc_code);
+
+       ret = qcom_vadc_map_voltage_temp(adcmap7_100k,
+                                ARRAY_SIZE(adcmap7_100k),
+                                resistance, &result);
+       if (ret)
+               return ret;
+
+       *result_mdec = result;
+
+       return 0;
+}
+
 static int qcom_vadc_scale_hw_calib_volt(
                                const struct vadc_prescale_ratio *prescale,
                                const struct adc5_data *data,
@@ -330,6 +557,41 @@ static int qcom_vadc_scale_hw_calib_die_temp(
        return 0;
 }
 
+static int qcom_vadc7_scale_hw_calib_die_temp(
+                               const struct vadc_prescale_ratio *prescale,
+                               const struct adc5_data *data,
+                               u16 adc_code, int *result_mdec)
+{
+
+       int voltage, vtemp0, temp, i;
+
+       voltage = qcom_vadc_scale_code_voltage_factor(adc_code,
+                               prescale, data, 1);
+
+       if (adcmap7_die_temp[0].x > voltage) {
+               *result_mdec = DIE_TEMP_ADC7_SCALE_1;
+               return 0;
+       }
+
+       if (adcmap7_die_temp[ARRAY_SIZE(adcmap7_die_temp) - 1].x <= voltage) {
+               *result_mdec = DIE_TEMP_ADC7_MAX;
+               return 0;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(adcmap7_die_temp); i++)
+               if (adcmap7_die_temp[i].x > voltage)
+                       break;
+
+       vtemp0 = adcmap7_die_temp[i - 1].x;
+       voltage = voltage - vtemp0;
+       temp = div64_s64(voltage * DIE_TEMP_ADC7_SCALE_FACTOR,
+               adcmap7_die_temp[i - 1].y);
+       temp += DIE_TEMP_ADC7_SCALE_1 + (DIE_TEMP_ADC7_SCALE_2 * (i - 1));
+       *result_mdec = temp;
+
+       return 0;
+}
+
 static int qcom_vadc_scale_hw_smb_temp(
                                const struct vadc_prescale_ratio *prescale,
                                const struct adc5_data *data,
index e074902..17b2fc4 100644 (file)
 #define ADC5_FULL_SCALE_CODE                   0x70e4
 #define ADC5_USR_DATA_CHECK                    0x8000
 
+#define R_PU_100K                              100000
+#define RATIO_MAX_ADC7                         BIT(14)
+
+#define DIE_TEMP_ADC7_SCALE_1                  -60000
+#define DIE_TEMP_ADC7_SCALE_2                  20000
+#define DIE_TEMP_ADC7_SCALE_FACTOR             1000
+#define DIE_TEMP_ADC7_MAX                      160000
+
 /**
  * struct vadc_map_pt - Map the graph representation for ADC channel
  * @x: Represent the ADC digitized code.
@@ -110,8 +118,12 @@ struct vadc_prescale_ratio {
  *     lookup table. The hardware applies offset/slope to adc code.
  * SCALE_HW_CALIB_XOTHERM: Returns XO thermistor voltage in millidegC using
  *     100k pullup. The hardware applies offset/slope to adc code.
+ * SCALE_HW_CALIB_THERM_100K_PU_PM7: Returns temperature in millidegC using
+ *     lookup table for PMIC7. The hardware applies offset/slope to adc code.
  * SCALE_HW_CALIB_PMIC_THERM: Returns result in milli degree's Centigrade.
  *     The hardware applies offset/slope to adc code.
+ * SCALE_HW_CALIB_PMIC_THERM: Returns result in milli degree's Centigrade.
+ *     The hardware applies offset/slope to adc code. This is for PMIC7.
  * SCALE_HW_CALIB_PM5_CHG_TEMP: Returns result in millidegrees for PMIC5
  *     charger temperature.
  * SCALE_HW_CALIB_PM5_SMB_TEMP: Returns result in millidegrees for PMIC5
@@ -126,7 +138,9 @@ enum vadc_scale_fn_type {
        SCALE_HW_CALIB_DEFAULT,
        SCALE_HW_CALIB_THERM_100K_PULLUP,
        SCALE_HW_CALIB_XOTHERM,
+       SCALE_HW_CALIB_THERM_100K_PU_PM7,
        SCALE_HW_CALIB_PMIC_THERM,
+       SCALE_HW_CALIB_PMIC_THERM_PM7,
        SCALE_HW_CALIB_PM5_CHG_TEMP,
        SCALE_HW_CALIB_PM5_SMB_TEMP,
        SCALE_HW_CALIB_INVALID,
@@ -136,6 +150,7 @@ struct adc5_data {
        const u32       full_scale_code_volt;
        const u32       full_scale_code_cur;
        const struct adc5_channels *adc_chans;
+       const struct iio_info *info;
        unsigned int    *decimation;
        unsigned int    *hw_settle_1;
        unsigned int    *hw_settle_2;
index 63ce743..d2c1419 100644 (file)
@@ -516,8 +516,6 @@ static int rcar_gyroadc_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, indio_dev);
 
        indio_dev->name = DRIVER_NAME;
-       indio_dev->dev.parent = dev;
-       indio_dev->dev.of_node = pdev->dev.of_node;
        indio_dev->info = &rcar_gyroadc_iio_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
index f21027e..7010c42 100644 (file)
@@ -218,7 +218,6 @@ static int rn5t618_adc_probe(struct platform_device *pdev)
        init_completion(&adc->conv_completion);
 
        iio_dev->name = dev_name(&pdev->dev);
-       iio_dev->dev.parent = &pdev->dev;
        iio_dev->info = &rn5t618_adc_iio_info;
        iio_dev->modes = INDIO_DIRECT_MODE;
        iio_dev->channels = rn5t618_adc_iio_channels;
index 582ba04..70af111 100644 (file)
 #include <linux/delay.h>
 #include <linux/reset.h>
 #include <linux/regulator/consumer.h>
+#include <linux/iio/buffer.h>
 #include <linux/iio/iio.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
 
 #define SARADC_DATA                    0x00
 
@@ -32,9 +35,9 @@
 #define SARADC_DLY_PU_SOC_MASK         0x3f
 
 #define SARADC_TIMEOUT                 msecs_to_jiffies(100)
+#define SARADC_MAX_CHANNELS            6
 
 struct rockchip_saradc_data {
-       int                             num_bits;
        const struct iio_chan_spec      *channels;
        int                             num_channels;
        unsigned long                   clk_rate;
@@ -49,8 +52,37 @@ struct rockchip_saradc {
        struct reset_control    *reset;
        const struct rockchip_saradc_data *data;
        u16                     last_val;
+       const struct iio_chan_spec *last_chan;
 };
 
+static void rockchip_saradc_power_down(struct rockchip_saradc *info)
+{
+       /* Clear irq & power down adc */
+       writel_relaxed(0, info->regs + SARADC_CTRL);
+}
+
+static int rockchip_saradc_conversion(struct rockchip_saradc *info,
+                                  struct iio_chan_spec const *chan)
+{
+       reinit_completion(&info->completion);
+
+       /* 8 clock periods as delay between power up and start cmd */
+       writel_relaxed(8, info->regs + SARADC_DLY_PU_SOC);
+
+       info->last_chan = chan;
+
+       /* Select the channel to be used and trigger conversion */
+       writel(SARADC_CTRL_POWER_CTRL
+                       | (chan->channel & SARADC_CTRL_CHN_MASK)
+                       | SARADC_CTRL_IRQ_ENABLE,
+                  info->regs + SARADC_CTRL);
+
+       if (!wait_for_completion_timeout(&info->completion, SARADC_TIMEOUT))
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
 static int rockchip_saradc_read_raw(struct iio_dev *indio_dev,
                                    struct iio_chan_spec const *chan,
                                    int *val, int *val2, long mask)
@@ -62,22 +94,11 @@ static int rockchip_saradc_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_RAW:
                mutex_lock(&indio_dev->mlock);
 
-               reinit_completion(&info->completion);
-
-               /* 8 clock periods as delay between power up and start cmd */
-               writel_relaxed(8, info->regs + SARADC_DLY_PU_SOC);
-
-               /* Select the channel to be used and trigger conversion */
-               writel(SARADC_CTRL_POWER_CTRL
-                               | (chan->channel & SARADC_CTRL_CHN_MASK)
-                               | SARADC_CTRL_IRQ_ENABLE,
-                      info->regs + SARADC_CTRL);
-
-               if (!wait_for_completion_timeout(&info->completion,
-                                                SARADC_TIMEOUT)) {
-                       writel_relaxed(0, info->regs + SARADC_CTRL);
+               ret = rockchip_saradc_conversion(info, chan);
+               if (ret) {
+                       rockchip_saradc_power_down(info);
                        mutex_unlock(&indio_dev->mlock);
-                       return -ETIMEDOUT;
+                       return ret;
                }
 
                *val = info->last_val;
@@ -91,7 +112,7 @@ static int rockchip_saradc_read_raw(struct iio_dev *indio_dev,
                }
 
                *val = ret / 1000;
-               *val2 = info->data->num_bits;
+               *val2 = chan->scan_type.realbits;
                return IIO_VAL_FRACTIONAL_LOG2;
        default:
                return -EINVAL;
@@ -104,10 +125,9 @@ static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id)
 
        /* Read value */
        info->last_val = readl_relaxed(info->regs + SARADC_DATA);
-       info->last_val &= GENMASK(info->data->num_bits - 1, 0);
+       info->last_val &= GENMASK(info->last_chan->scan_type.realbits - 1, 0);
 
-       /* Clear irq & power down adc */
-       writel_relaxed(0, info->regs + SARADC_CTRL);
+       rockchip_saradc_power_down(info);
 
        complete(&info->completion);
 
@@ -118,51 +138,55 @@ static const struct iio_info rockchip_saradc_iio_info = {
        .read_raw = rockchip_saradc_read_raw,
 };
 
-#define ADC_CHANNEL(_index, _id) {                             \
+#define SARADC_CHANNEL(_index, _id, _res) {                    \
        .type = IIO_VOLTAGE,                                    \
        .indexed = 1,                                           \
        .channel = _index,                                      \
        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
        .datasheet_name = _id,                                  \
+       .scan_index = _index,                                   \
+       .scan_type = {                                          \
+               .sign = 'u',                                    \
+               .realbits = _res,                               \
+               .storagebits = 16,                              \
+               .endianness = IIO_CPU,                          \
+       },                                                      \
 }
 
 static const struct iio_chan_spec rockchip_saradc_iio_channels[] = {
-       ADC_CHANNEL(0, "adc0"),
-       ADC_CHANNEL(1, "adc1"),
-       ADC_CHANNEL(2, "adc2"),
+       SARADC_CHANNEL(0, "adc0", 10),
+       SARADC_CHANNEL(1, "adc1", 10),
+       SARADC_CHANNEL(2, "adc2", 10),
 };
 
 static const struct rockchip_saradc_data saradc_data = {
-       .num_bits = 10,
        .channels = rockchip_saradc_iio_channels,
        .num_channels = ARRAY_SIZE(rockchip_saradc_iio_channels),
        .clk_rate = 1000000,
 };
 
 static const struct iio_chan_spec rockchip_rk3066_tsadc_iio_channels[] = {
-       ADC_CHANNEL(0, "adc0"),
-       ADC_CHANNEL(1, "adc1"),
+       SARADC_CHANNEL(0, "adc0", 12),
+       SARADC_CHANNEL(1, "adc1", 12),
 };
 
 static const struct rockchip_saradc_data rk3066_tsadc_data = {
-       .num_bits = 12,
        .channels = rockchip_rk3066_tsadc_iio_channels,
        .num_channels = ARRAY_SIZE(rockchip_rk3066_tsadc_iio_channels),
        .clk_rate = 50000,
 };
 
 static const struct iio_chan_spec rockchip_rk3399_saradc_iio_channels[] = {
-       ADC_CHANNEL(0, "adc0"),
-       ADC_CHANNEL(1, "adc1"),
-       ADC_CHANNEL(2, "adc2"),
-       ADC_CHANNEL(3, "adc3"),
-       ADC_CHANNEL(4, "adc4"),
-       ADC_CHANNEL(5, "adc5"),
+       SARADC_CHANNEL(0, "adc0", 10),
+       SARADC_CHANNEL(1, "adc1", 10),
+       SARADC_CHANNEL(2, "adc2", 10),
+       SARADC_CHANNEL(3, "adc3", 10),
+       SARADC_CHANNEL(4, "adc4", 10),
+       SARADC_CHANNEL(5, "adc5", 10),
 };
 
 static const struct rockchip_saradc_data rk3399_saradc_data = {
-       .num_bits = 10,
        .channels = rockchip_rk3399_saradc_iio_channels,
        .num_channels = ARRAY_SIZE(rockchip_rk3399_saradc_iio_channels),
        .clk_rate = 1000000,
@@ -193,6 +217,67 @@ static void rockchip_saradc_reset_controller(struct reset_control *reset)
        reset_control_deassert(reset);
 }
 
+static void rockchip_saradc_clk_disable(void *data)
+{
+       struct rockchip_saradc *info = data;
+
+       clk_disable_unprepare(info->clk);
+}
+
+static void rockchip_saradc_pclk_disable(void *data)
+{
+       struct rockchip_saradc *info = data;
+
+       clk_disable_unprepare(info->pclk);
+}
+
+static void rockchip_saradc_regulator_disable(void *data)
+{
+       struct rockchip_saradc *info = data;
+
+       regulator_disable(info->vref);
+}
+
+static irqreturn_t rockchip_saradc_trigger_handler(int irq, void *p)
+{
+       struct iio_poll_func *pf = p;
+       struct iio_dev *i_dev = pf->indio_dev;
+       struct rockchip_saradc *info = iio_priv(i_dev);
+       /*
+        * @values: each channel takes an u16 value
+        * @timestamp: will be 8-byte aligned automatically
+        */
+       struct {
+               u16 values[SARADC_MAX_CHANNELS];
+               int64_t timestamp;
+       } data;
+       int ret;
+       int i, j = 0;
+
+       mutex_lock(&i_dev->mlock);
+
+       for_each_set_bit(i, i_dev->active_scan_mask, i_dev->masklength) {
+               const struct iio_chan_spec *chan = &i_dev->channels[i];
+
+               ret = rockchip_saradc_conversion(info, chan);
+               if (ret) {
+                       rockchip_saradc_power_down(info);
+                       goto out;
+               }
+
+               data.values[j] = info->last_val;
+               j++;
+       }
+
+       iio_push_to_buffers_with_timestamp(i_dev, &data, iio_get_time_ns(i_dev));
+out:
+       mutex_unlock(&i_dev->mlock);
+
+       iio_trigger_notify_done(i_dev->trig);
+
+       return IRQ_HANDLED;
+}
+
 static int rockchip_saradc_probe(struct platform_device *pdev)
 {
        struct rockchip_saradc *info = NULL;
@@ -221,6 +306,12 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
 
        info->data = match->data;
 
+       /* Sanity check for possible later IP variants with more channels */
+       if (info->data->num_channels > SARADC_MAX_CHANNELS) {
+               dev_err(&pdev->dev, "max channels exceeded");
+               return -EINVAL;
+       }
+
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        info->regs = devm_ioremap_resource(&pdev->dev, mem);
        if (IS_ERR(info->regs))
@@ -291,56 +382,55 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "failed to enable vref regulator\n");
                return ret;
        }
+       ret = devm_add_action_or_reset(&pdev->dev,
+                                      rockchip_saradc_regulator_disable, info);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to register devm action, %d\n",
+                       ret);
+               return ret;
+       }
 
        ret = clk_prepare_enable(info->pclk);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to enable pclk\n");
-               goto err_reg_voltage;
+               return ret;
+       }
+       ret = devm_add_action_or_reset(&pdev->dev,
+                                      rockchip_saradc_pclk_disable, info);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to register devm action, %d\n",
+                       ret);
+               return ret;
        }
 
        ret = clk_prepare_enable(info->clk);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to enable converter clock\n");
-               goto err_pclk;
+               return ret;
+       }
+       ret = devm_add_action_or_reset(&pdev->dev,
+                                      rockchip_saradc_clk_disable, info);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to register devm action, %d\n",
+                       ret);
+               return ret;
        }
 
        platform_set_drvdata(pdev, indio_dev);
 
        indio_dev->name = dev_name(&pdev->dev);
-       indio_dev->dev.parent = &pdev->dev;
-       indio_dev->dev.of_node = pdev->dev.of_node;
        indio_dev->info = &rockchip_saradc_iio_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
        indio_dev->channels = info->data->channels;
        indio_dev->num_channels = info->data->num_channels;
-
-       ret = iio_device_register(indio_dev);
+       ret = devm_iio_triggered_buffer_setup(&indio_dev->dev, indio_dev, NULL,
+                                             rockchip_saradc_trigger_handler,
+                                             NULL);
        if (ret)
-               goto err_clk;
-
-       return 0;
-
-err_clk:
-       clk_disable_unprepare(info->clk);
-err_pclk:
-       clk_disable_unprepare(info->pclk);
-err_reg_voltage:
-       regulator_disable(info->vref);
-       return ret;
-}
-
-static int rockchip_saradc_remove(struct platform_device *pdev)
-{
-       struct iio_dev *indio_dev = platform_get_drvdata(pdev);
-       struct rockchip_saradc *info = iio_priv(indio_dev);
-
-       iio_device_unregister(indio_dev);
-       clk_disable_unprepare(info->clk);
-       clk_disable_unprepare(info->pclk);
-       regulator_disable(info->vref);
+               return ret;
 
-       return 0;
+       return devm_iio_device_register(&pdev->dev, indio_dev);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -383,7 +473,6 @@ static SIMPLE_DEV_PM_OPS(rockchip_saradc_pm_ops,
 
 static struct platform_driver rockchip_saradc_driver = {
        .probe          = rockchip_saradc_probe,
-       .remove         = rockchip_saradc_remove,
        .driver         = {
                .name   = "rockchip-saradc",
                .of_match_table = rockchip_saradc_match,
index 66b387f..aa32a1f 100644 (file)
@@ -533,7 +533,6 @@ static int sc27xx_adc_probe(struct platform_device *pdev)
                return ret;
        }
 
-       indio_dev->dev.parent = dev;
        indio_dev->name = dev_name(dev);
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &sc27xx_info;
index 560d8c7..327cc20 100644 (file)
@@ -9,7 +9,8 @@
 #include <linux/iio/iio.h>
 #include <linux/iio/triggered_buffer.h>
 #include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
 
 static const struct iio_info iio_sd_mod_iio_info;
 
@@ -32,8 +33,6 @@ static int iio_sd_mod_probe(struct platform_device *pdev)
        if (!iio)
                return -ENOMEM;
 
-       iio->dev.parent = dev;
-       iio->dev.of_node = dev->of_node;
        iio->name = dev_name(dev);
        iio->info = &iio_sd_mod_iio_info;
        iio->modes = INDIO_BUFFER_HARDWARE;
@@ -56,7 +55,7 @@ MODULE_DEVICE_TABLE(of, sd_adc_of_match);
 static struct platform_driver iio_sd_mod_adc = {
        .driver = {
                .name = "iio_sd_adc_mod",
-               .of_match_table = of_match_ptr(sd_adc_of_match),
+               .of_match_table = sd_adc_of_match,
        },
        .probe = iio_sd_mod_probe,
 };
index 0ad5364..1bc986a 100644 (file)
@@ -336,7 +336,6 @@ static int spear_adc_probe(struct platform_device *pdev)
        init_completion(&st->completion);
 
        indio_dev->name = SPEAR_ADC_MOD_NAME;
-       indio_dev->dev.parent = dev;
        indio_dev->info = &spear_adc_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = spear_adc_iio_channels;
index dfc3a30..3eb9ebe 100644 (file)
@@ -162,10 +162,10 @@ struct stm32_adc_cfg {
        struct stm32_adc_trig_info      *trigs;
        bool clk_required;
        bool has_vregready;
-       int (*prepare)(struct stm32_adc *);
-       void (*start_conv)(struct stm32_adc *, bool dma);
-       void (*stop_conv)(struct stm32_adc *);
-       void (*unprepare)(struct stm32_adc *);
+       int (*prepare)(struct iio_dev *);
+       void (*start_conv)(struct iio_dev *, bool dma);
+       void (*stop_conv)(struct iio_dev *);
+       void (*unprepare)(struct iio_dev *);
        const unsigned int *smp_cycles;
 };
 
@@ -538,10 +538,11 @@ static void stm32_adc_set_res(struct stm32_adc *adc)
 
 static int stm32_adc_hw_stop(struct device *dev)
 {
-       struct stm32_adc *adc = dev_get_drvdata(dev);
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct stm32_adc *adc = iio_priv(indio_dev);
 
        if (adc->cfg->unprepare)
-               adc->cfg->unprepare(adc);
+               adc->cfg->unprepare(indio_dev);
 
        if (adc->clk)
                clk_disable_unprepare(adc->clk);
@@ -551,7 +552,8 @@ static int stm32_adc_hw_stop(struct device *dev)
 
 static int stm32_adc_hw_start(struct device *dev)
 {
-       struct stm32_adc *adc = dev_get_drvdata(dev);
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct stm32_adc *adc = iio_priv(indio_dev);
        int ret;
 
        if (adc->clk) {
@@ -563,7 +565,7 @@ static int stm32_adc_hw_start(struct device *dev)
        stm32_adc_set_res(adc);
 
        if (adc->cfg->prepare) {
-               ret = adc->cfg->prepare(adc);
+               ret = adc->cfg->prepare(indio_dev);
                if (ret)
                        goto err_clk_dis;
        }
@@ -579,7 +581,7 @@ err_clk_dis:
 
 /**
  * stm32f4_adc_start_conv() - Start conversions for regular channels.
- * @adc: stm32 adc instance
+ * @indio_dev: IIO device instance
  * @dma: use dma to transfer conversion result
  *
  * Start conversions for regular channels.
@@ -587,8 +589,10 @@ err_clk_dis:
  * conversions, in IIO buffer modes. Otherwise, use ADC interrupt with direct
  * DR read instead (e.g. read_raw, or triggered buffer mode without DMA).
  */
-static void stm32f4_adc_start_conv(struct stm32_adc *adc, bool dma)
+static void stm32f4_adc_start_conv(struct iio_dev *indio_dev, bool dma)
 {
+       struct stm32_adc *adc = iio_priv(indio_dev);
+
        stm32_adc_set_bits(adc, STM32F4_ADC_CR1, STM32F4_SCAN);
 
        if (dma)
@@ -605,8 +609,10 @@ static void stm32f4_adc_start_conv(struct stm32_adc *adc, bool dma)
                stm32_adc_set_bits(adc, STM32F4_ADC_CR2, STM32F4_SWSTART);
 }
 
-static void stm32f4_adc_stop_conv(struct stm32_adc *adc)
+static void stm32f4_adc_stop_conv(struct iio_dev *indio_dev)
 {
+       struct stm32_adc *adc = iio_priv(indio_dev);
+
        stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_EXTEN_MASK);
        stm32_adc_clr_bits(adc, STM32F4_ADC_SR, STM32F4_STRT);
 
@@ -615,8 +621,9 @@ static void stm32f4_adc_stop_conv(struct stm32_adc *adc)
                           STM32F4_ADON | STM32F4_DMA | STM32F4_DDS);
 }
 
-static void stm32h7_adc_start_conv(struct stm32_adc *adc, bool dma)
+static void stm32h7_adc_start_conv(struct iio_dev *indio_dev, bool dma)
 {
+       struct stm32_adc *adc = iio_priv(indio_dev);
        enum stm32h7_adc_dmngt dmngt;
        unsigned long flags;
        u32 val;
@@ -635,9 +642,9 @@ static void stm32h7_adc_start_conv(struct stm32_adc *adc, bool dma)
        stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADSTART);
 }
 
-static void stm32h7_adc_stop_conv(struct stm32_adc *adc)
+static void stm32h7_adc_stop_conv(struct iio_dev *indio_dev)
 {
-       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+       struct stm32_adc *adc = iio_priv(indio_dev);
        int ret;
        u32 val;
 
@@ -652,9 +659,9 @@ static void stm32h7_adc_stop_conv(struct stm32_adc *adc)
        stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR, STM32H7_DMNGT_MASK);
 }
 
-static int stm32h7_adc_exit_pwr_down(struct stm32_adc *adc)
+static int stm32h7_adc_exit_pwr_down(struct iio_dev *indio_dev)
 {
-       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+       struct stm32_adc *adc = iio_priv(indio_dev);
        int ret;
        u32 val;
 
@@ -690,9 +697,9 @@ static void stm32h7_adc_enter_pwr_down(struct stm32_adc *adc)
        stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD);
 }
 
-static int stm32h7_adc_enable(struct stm32_adc *adc)
+static int stm32h7_adc_enable(struct iio_dev *indio_dev)
 {
-       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+       struct stm32_adc *adc = iio_priv(indio_dev);
        int ret;
        u32 val;
 
@@ -713,9 +720,9 @@ static int stm32h7_adc_enable(struct stm32_adc *adc)
        return ret;
 }
 
-static void stm32h7_adc_disable(struct stm32_adc *adc)
+static void stm32h7_adc_disable(struct iio_dev *indio_dev)
 {
-       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+       struct stm32_adc *adc = iio_priv(indio_dev);
        int ret;
        u32 val;
 
@@ -730,12 +737,12 @@ static void stm32h7_adc_disable(struct stm32_adc *adc)
 
 /**
  * stm32h7_adc_read_selfcalib() - read calibration shadow regs, save result
- * @adc: stm32 adc instance
+ * @indio_dev: IIO device instance
  * Note: Must be called once ADC is enabled, so LINCALRDYW[1..6] are writable
  */
-static int stm32h7_adc_read_selfcalib(struct stm32_adc *adc)
+static int stm32h7_adc_read_selfcalib(struct iio_dev *indio_dev)
 {
-       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+       struct stm32_adc *adc = iio_priv(indio_dev);
        int i, ret;
        u32 lincalrdyw_mask, val;
 
@@ -774,12 +781,12 @@ static int stm32h7_adc_read_selfcalib(struct stm32_adc *adc)
 
 /**
  * stm32h7_adc_restore_selfcalib() - Restore saved self-calibration result
- * @adc: stm32 adc instance
+ * @indio_dev: IIO device instance
  * Note: ADC must be enabled, with no on-going conversions.
  */
-static int stm32h7_adc_restore_selfcalib(struct stm32_adc *adc)
+static int stm32h7_adc_restore_selfcalib(struct iio_dev *indio_dev)
 {
-       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+       struct stm32_adc *adc = iio_priv(indio_dev);
        int i, ret;
        u32 lincalrdyw_mask, val;
 
@@ -847,12 +854,12 @@ static int stm32h7_adc_restore_selfcalib(struct stm32_adc *adc)
 
 /**
  * stm32h7_adc_selfcalib() - Procedure to calibrate ADC
- * @adc: stm32 adc instance
+ * @indio_dev: IIO device instance
  * Note: Must be called once ADC is out of power down.
  */
-static int stm32h7_adc_selfcalib(struct stm32_adc *adc)
+static int stm32h7_adc_selfcalib(struct iio_dev *indio_dev)
 {
-       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+       struct stm32_adc *adc = iio_priv(indio_dev);
        int ret;
        u32 val;
 
@@ -903,7 +910,7 @@ out:
 
 /**
  * stm32h7_adc_prepare() - Leave power down mode to enable ADC.
- * @adc: stm32 adc instance
+ * @indio_dev: IIO device instance
  * Leave power down mode.
  * Configure channels as single ended or differential before enabling ADC.
  * Enable ADC.
@@ -912,30 +919,31 @@ out:
  * - Only one input is selected for single ended (e.g. 'vinp')
  * - Two inputs are selected for differential channels (e.g. 'vinp' & 'vinn')
  */
-static int stm32h7_adc_prepare(struct stm32_adc *adc)
+static int stm32h7_adc_prepare(struct iio_dev *indio_dev)
 {
+       struct stm32_adc *adc = iio_priv(indio_dev);
        int calib, ret;
 
-       ret = stm32h7_adc_exit_pwr_down(adc);
+       ret = stm32h7_adc_exit_pwr_down(indio_dev);
        if (ret)
                return ret;
 
-       ret = stm32h7_adc_selfcalib(adc);
+       ret = stm32h7_adc_selfcalib(indio_dev);
        if (ret < 0)
                goto pwr_dwn;
        calib = ret;
 
        stm32_adc_writel(adc, STM32H7_ADC_DIFSEL, adc->difsel);
 
-       ret = stm32h7_adc_enable(adc);
+       ret = stm32h7_adc_enable(indio_dev);
        if (ret)
                goto pwr_dwn;
 
        /* Either restore or read calibration result for future reference */
        if (calib)
-               ret = stm32h7_adc_restore_selfcalib(adc);
+               ret = stm32h7_adc_restore_selfcalib(indio_dev);
        else
-               ret = stm32h7_adc_read_selfcalib(adc);
+               ret = stm32h7_adc_read_selfcalib(indio_dev);
        if (ret)
                goto disable;
 
@@ -944,16 +952,18 @@ static int stm32h7_adc_prepare(struct stm32_adc *adc)
        return 0;
 
 disable:
-       stm32h7_adc_disable(adc);
+       stm32h7_adc_disable(indio_dev);
 pwr_dwn:
        stm32h7_adc_enter_pwr_down(adc);
 
        return ret;
 }
 
-static void stm32h7_adc_unprepare(struct stm32_adc *adc)
+static void stm32h7_adc_unprepare(struct iio_dev *indio_dev)
 {
-       stm32h7_adc_disable(adc);
+       struct stm32_adc *adc = iio_priv(indio_dev);
+
+       stm32h7_adc_disable(indio_dev);
        stm32h7_adc_enter_pwr_down(adc);
 }
 
@@ -1160,7 +1170,7 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev,
 
        stm32_adc_conv_irq_enable(adc);
 
-       adc->cfg->start_conv(adc, false);
+       adc->cfg->start_conv(indio_dev, false);
 
        timeout = wait_for_completion_interruptible_timeout(
                                        &adc->completion, STM32_ADC_TIMEOUT);
@@ -1173,7 +1183,7 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev,
                ret = IIO_VAL_INT;
        }
 
-       adc->cfg->stop_conv(adc);
+       adc->cfg->stop_conv(indio_dev);
 
        stm32_adc_conv_irq_disable(adc);
 
@@ -1227,8 +1237,8 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev,
 
 static irqreturn_t stm32_adc_threaded_isr(int irq, void *data)
 {
-       struct stm32_adc *adc = data;
-       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+       struct iio_dev *indio_dev = data;
+       struct stm32_adc *adc = iio_priv(indio_dev);
        const struct stm32_adc_regspec *regs = adc->cfg->regs;
        u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg);
 
@@ -1240,8 +1250,8 @@ static irqreturn_t stm32_adc_threaded_isr(int irq, void *data)
 
 static irqreturn_t stm32_adc_isr(int irq, void *data)
 {
-       struct stm32_adc *adc = data;
-       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+       struct iio_dev *indio_dev = data;
+       struct stm32_adc *adc = iio_priv(indio_dev);
        const struct stm32_adc_regspec *regs = adc->cfg->regs;
        u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg);
 
@@ -1482,7 +1492,7 @@ static int stm32_adc_dma_start(struct iio_dev *indio_dev)
        return 0;
 }
 
-static int __stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
+static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
 {
        struct stm32_adc *adc = iio_priv(indio_dev);
        struct device *dev = indio_dev->dev.parent;
@@ -1514,7 +1524,7 @@ static int __stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
        if (!adc->dma_chan)
                stm32_adc_conv_irq_enable(adc);
 
-       adc->cfg->start_conv(adc, !!adc->dma_chan);
+       adc->cfg->start_conv(indio_dev, !!adc->dma_chan);
 
        return 0;
 
@@ -1527,27 +1537,12 @@ err_pm_put:
        return ret;
 }
 
-static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
-{
-       int ret;
-
-       ret = iio_triggered_buffer_postenable(indio_dev);
-       if (ret < 0)
-               return ret;
-
-       ret = __stm32_adc_buffer_postenable(indio_dev);
-       if (ret < 0)
-               iio_triggered_buffer_predisable(indio_dev);
-
-       return ret;
-}
-
-static void __stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
+static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
 {
        struct stm32_adc *adc = iio_priv(indio_dev);
        struct device *dev = indio_dev->dev.parent;
 
-       adc->cfg->stop_conv(adc);
+       adc->cfg->stop_conv(indio_dev);
        if (!adc->dma_chan)
                stm32_adc_conv_irq_disable(adc);
 
@@ -1561,19 +1556,8 @@ static void __stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
 
        pm_runtime_mark_last_busy(dev);
        pm_runtime_put_autosuspend(dev);
-}
-
-static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
-{
-       int ret;
 
-       __stm32_adc_buffer_predisable(indio_dev);
-
-       ret = iio_triggered_buffer_predisable(indio_dev);
-       if (ret < 0)
-               dev_err(&indio_dev->dev, "predisable failed\n");
-
-       return ret;
+       return 0;
 }
 
 static const struct iio_buffer_setup_ops stm32_adc_buffer_setup_ops = {
@@ -1886,12 +1870,11 @@ static int stm32_adc_probe(struct platform_device *pdev)
                of_match_device(dev->driver->of_match_table, dev)->data;
 
        indio_dev->name = dev_name(&pdev->dev);
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->dev.of_node = pdev->dev.of_node;
        indio_dev->info = &stm32_adc_iio_info;
        indio_dev->modes = INDIO_DIRECT_MODE | INDIO_HARDWARE_TRIGGERED;
 
-       platform_set_drvdata(pdev, adc);
+       platform_set_drvdata(pdev, indio_dev);
 
        ret = of_property_read_u32(pdev->dev.of_node, "reg", &adc->offset);
        if (ret != 0) {
@@ -1905,7 +1888,7 @@ static int stm32_adc_probe(struct platform_device *pdev)
 
        ret = devm_request_threaded_irq(&pdev->dev, adc->irq, stm32_adc_isr,
                                        stm32_adc_threaded_isr,
-                                       0, pdev->name, adc);
+                                       0, pdev->name, indio_dev);
        if (ret) {
                dev_err(&pdev->dev, "failed to request IRQ\n");
                return ret;
@@ -1989,8 +1972,8 @@ err_dma_disable:
 
 static int stm32_adc_remove(struct platform_device *pdev)
 {
-       struct stm32_adc *adc = platform_get_drvdata(pdev);
-       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+       struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+       struct stm32_adc *adc = iio_priv(indio_dev);
 
        pm_runtime_get_sync(&pdev->dev);
        iio_device_unregister(indio_dev);
@@ -2012,19 +1995,17 @@ static int stm32_adc_remove(struct platform_device *pdev)
 #if defined(CONFIG_PM_SLEEP)
 static int stm32_adc_suspend(struct device *dev)
 {
-       struct stm32_adc *adc = dev_get_drvdata(dev);
-       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
 
        if (iio_buffer_enabled(indio_dev))
-               __stm32_adc_buffer_predisable(indio_dev);
+               stm32_adc_buffer_predisable(indio_dev);
 
        return pm_runtime_force_suspend(dev);
 }
 
 static int stm32_adc_resume(struct device *dev)
 {
-       struct stm32_adc *adc = dev_get_drvdata(dev);
-       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
        int ret;
 
        ret = pm_runtime_force_resume(dev);
@@ -2039,7 +2020,7 @@ static int stm32_adc_resume(struct device *dev)
        if (ret < 0)
                return ret;
 
-       return __stm32_adc_buffer_postenable(indio_dev);
+       return stm32_adc_buffer_postenable(indio_dev);
 }
 #endif
 
index 506bf51..5e10fb4 100644 (file)
@@ -330,9 +330,9 @@ static int stm32_dfsdm_compute_all_osrs(struct iio_dev *indio_dev,
        return 0;
 }
 
-static int stm32_dfsdm_start_channel(struct stm32_dfsdm_adc *adc)
+static int stm32_dfsdm_start_channel(struct iio_dev *indio_dev)
 {
-       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+       struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
        struct regmap *regmap = adc->dfsdm->regmap;
        const struct iio_chan_spec *chan;
        unsigned int bit;
@@ -350,9 +350,9 @@ static int stm32_dfsdm_start_channel(struct stm32_dfsdm_adc *adc)
        return 0;
 }
 
-static void stm32_dfsdm_stop_channel(struct stm32_dfsdm_adc *adc)
+static void stm32_dfsdm_stop_channel(struct iio_dev *indio_dev)
 {
-       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+       struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
        struct regmap *regmap = adc->dfsdm->regmap;
        const struct iio_chan_spec *chan;
        unsigned int bit;
@@ -418,11 +418,11 @@ static void stm32_dfsdm_stop_filter(struct stm32_dfsdm *dfsdm,
                           DFSDM_CR1_DFEN_MASK, DFSDM_CR1_DFEN(0));
 }
 
-static int stm32_dfsdm_filter_set_trig(struct stm32_dfsdm_adc *adc,
+static int stm32_dfsdm_filter_set_trig(struct iio_dev *indio_dev,
                                       unsigned int fl_id,
                                       struct iio_trigger *trig)
 {
-       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+       struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
        struct regmap *regmap = adc->dfsdm->regmap;
        u32 jextsel = 0, jexten = STM32_DFSDM_JEXTEN_DISABLED;
        int ret;
@@ -447,11 +447,11 @@ static int stm32_dfsdm_filter_set_trig(struct stm32_dfsdm_adc *adc,
        return 0;
 }
 
-static int stm32_dfsdm_channels_configure(struct stm32_dfsdm_adc *adc,
+static int stm32_dfsdm_channels_configure(struct iio_dev *indio_dev,
                                          unsigned int fl_id,
                                          struct iio_trigger *trig)
 {
-       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+       struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
        struct regmap *regmap = adc->dfsdm->regmap;
        struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[fl_id];
        struct stm32_dfsdm_filter_osr *flo = &fl->flo[0];
@@ -491,11 +491,11 @@ static int stm32_dfsdm_channels_configure(struct stm32_dfsdm_adc *adc,
        return 0;
 }
 
-static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc,
+static int stm32_dfsdm_filter_configure(struct iio_dev *indio_dev,
                                        unsigned int fl_id,
                                        struct iio_trigger *trig)
 {
-       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+       struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
        struct regmap *regmap = adc->dfsdm->regmap;
        struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[fl_id];
        struct stm32_dfsdm_filter_osr *flo = &fl->flo[fl->fast];
@@ -521,7 +521,7 @@ static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc,
        if (ret)
                return ret;
 
-       ret = stm32_dfsdm_filter_set_trig(adc, fl_id, trig);
+       ret = stm32_dfsdm_filter_set_trig(indio_dev, fl_id, trig);
        if (ret)
                return ret;
 
@@ -729,21 +729,22 @@ static ssize_t dfsdm_adc_audio_set_spiclk(struct iio_dev *indio_dev,
        return len;
 }
 
-static int stm32_dfsdm_start_conv(struct stm32_dfsdm_adc *adc,
+static int stm32_dfsdm_start_conv(struct iio_dev *indio_dev,
                                  struct iio_trigger *trig)
 {
+       struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
        struct regmap *regmap = adc->dfsdm->regmap;
        int ret;
 
-       ret = stm32_dfsdm_channels_configure(adc, adc->fl_id, trig);
+       ret = stm32_dfsdm_channels_configure(indio_dev, adc->fl_id, trig);
        if (ret < 0)
                return ret;
 
-       ret = stm32_dfsdm_start_channel(adc);
+       ret = stm32_dfsdm_start_channel(indio_dev);
        if (ret < 0)
                return ret;
 
-       ret = stm32_dfsdm_filter_configure(adc, adc->fl_id, trig);
+       ret = stm32_dfsdm_filter_configure(indio_dev, adc->fl_id, trig);
        if (ret < 0)
                goto stop_channels;
 
@@ -757,13 +758,14 @@ filter_unconfigure:
        regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id),
                           DFSDM_CR1_CFG_MASK, 0);
 stop_channels:
-       stm32_dfsdm_stop_channel(adc);
+       stm32_dfsdm_stop_channel(indio_dev);
 
        return ret;
 }
 
-static void stm32_dfsdm_stop_conv(struct stm32_dfsdm_adc *adc)
+static void stm32_dfsdm_stop_conv(struct iio_dev *indio_dev)
 {
+       struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
        struct regmap *regmap = adc->dfsdm->regmap;
 
        stm32_dfsdm_stop_filter(adc->dfsdm, adc->fl_id);
@@ -771,7 +773,7 @@ static void stm32_dfsdm_stop_conv(struct stm32_dfsdm_adc *adc)
        regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id),
                           DFSDM_CR1_CFG_MASK, 0);
 
-       stm32_dfsdm_stop_channel(adc);
+       stm32_dfsdm_stop_channel(indio_dev);
 }
 
 static int stm32_dfsdm_set_watermark(struct iio_dev *indio_dev,
@@ -993,7 +995,7 @@ static int stm32_dfsdm_update_scan_mode(struct iio_dev *indio_dev,
        return 0;
 }
 
-static int __stm32_dfsdm_postenable(struct iio_dev *indio_dev)
+static int stm32_dfsdm_postenable(struct iio_dev *indio_dev)
 {
        struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
        int ret;
@@ -1017,7 +1019,7 @@ static int __stm32_dfsdm_postenable(struct iio_dev *indio_dev)
                goto stop_dfsdm;
        }
 
-       ret = stm32_dfsdm_start_conv(adc, indio_dev->trig);
+       ret = stm32_dfsdm_start_conv(indio_dev, indio_dev->trig);
        if (ret) {
                dev_err(&indio_dev->dev, "Can't start conversion\n");
                goto err_stop_dma;
@@ -1036,34 +1038,11 @@ err_stop_hwc:
        return ret;
 }
 
-static int stm32_dfsdm_postenable(struct iio_dev *indio_dev)
-{
-       int ret;
-
-       if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
-               ret = iio_triggered_buffer_postenable(indio_dev);
-               if (ret < 0)
-                       return ret;
-       }
-
-       ret = __stm32_dfsdm_postenable(indio_dev);
-       if (ret < 0)
-               goto err_predisable;
-
-       return 0;
-
-err_predisable:
-       if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED)
-               iio_triggered_buffer_predisable(indio_dev);
-
-       return ret;
-}
-
-static void __stm32_dfsdm_predisable(struct iio_dev *indio_dev)
+static int stm32_dfsdm_predisable(struct iio_dev *indio_dev)
 {
        struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
 
-       stm32_dfsdm_stop_conv(adc);
+       stm32_dfsdm_stop_conv(indio_dev);
 
        stm32_dfsdm_adc_dma_stop(indio_dev);
 
@@ -1071,14 +1050,6 @@ static void __stm32_dfsdm_predisable(struct iio_dev *indio_dev)
 
        if (adc->hwc)
                iio_hw_consumer_disable(adc->hwc);
-}
-
-static int stm32_dfsdm_predisable(struct iio_dev *indio_dev)
-{
-       __stm32_dfsdm_predisable(indio_dev);
-
-       if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED)
-               iio_triggered_buffer_predisable(indio_dev);
 
        return 0;
 }
@@ -1159,7 +1130,7 @@ static int stm32_dfsdm_single_conv(struct iio_dev *indio_dev,
 
        adc->nconv = 1;
        adc->smask = BIT(chan->scan_index);
-       ret = stm32_dfsdm_start_conv(adc, NULL);
+       ret = stm32_dfsdm_start_conv(indio_dev, NULL);
        if (ret < 0) {
                regmap_update_bits(adc->dfsdm->regmap, DFSDM_CR2(adc->fl_id),
                                   DFSDM_CR2_REOCIE_MASK, DFSDM_CR2_REOCIE(0));
@@ -1180,7 +1151,7 @@ static int stm32_dfsdm_single_conv(struct iio_dev *indio_dev,
        else
                ret = IIO_VAL_INT;
 
-       stm32_dfsdm_stop_conv(adc);
+       stm32_dfsdm_stop_conv(indio_dev);
 
        stm32_dfsdm_process_data(adc, res);
 
@@ -1313,8 +1284,8 @@ static const struct iio_info stm32_dfsdm_info_adc = {
 
 static irqreturn_t stm32_dfsdm_irq(int irq, void *arg)
 {
-       struct stm32_dfsdm_adc *adc = arg;
-       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+       struct iio_dev *indio_dev = arg;
+       struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
        struct regmap *regmap = adc->dfsdm->regmap;
        unsigned int status, int_en;
 
@@ -1571,11 +1542,10 @@ static int stm32_dfsdm_adc_probe(struct platform_device *pdev)
        adc = iio_priv(iio);
        adc->dfsdm = dev_get_drvdata(dev->parent);
 
-       iio->dev.parent = dev;
        iio->dev.of_node = np;
        iio->modes = INDIO_DIRECT_MODE;
 
-       platform_set_drvdata(pdev, adc);
+       platform_set_drvdata(pdev, iio);
 
        ret = of_property_read_u32(dev->of_node, "reg", &adc->fl_id);
        if (ret != 0 || adc->fl_id >= adc->dfsdm->num_fls) {
@@ -1604,7 +1574,7 @@ static int stm32_dfsdm_adc_probe(struct platform_device *pdev)
                return irq;
 
        ret = devm_request_irq(dev, irq, stm32_dfsdm_irq,
-                              0, pdev->name, adc);
+                              0, pdev->name, iio);
        if (ret < 0) {
                dev_err(dev, "Failed to request IRQ\n");
                return ret;
@@ -1651,8 +1621,8 @@ err_cleanup:
 
 static int stm32_dfsdm_adc_remove(struct platform_device *pdev)
 {
-       struct stm32_dfsdm_adc *adc = platform_get_drvdata(pdev);
-       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+       struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+       struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
 
        if (adc->dev_data->type == DFSDM_AUDIO)
                of_platform_depopulate(&pdev->dev);
@@ -1664,19 +1634,18 @@ static int stm32_dfsdm_adc_remove(struct platform_device *pdev)
 
 static int __maybe_unused stm32_dfsdm_adc_suspend(struct device *dev)
 {
-       struct stm32_dfsdm_adc *adc = dev_get_drvdata(dev);
-       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
 
        if (iio_buffer_enabled(indio_dev))
-               __stm32_dfsdm_predisable(indio_dev);
+               stm32_dfsdm_predisable(indio_dev);
 
        return 0;
 }
 
 static int __maybe_unused stm32_dfsdm_adc_resume(struct device *dev)
 {
-       struct stm32_dfsdm_adc *adc = dev_get_drvdata(dev);
-       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
        const struct iio_chan_spec *chan;
        struct stm32_dfsdm_channel *ch;
        int i, ret;
@@ -1691,7 +1660,7 @@ static int __maybe_unused stm32_dfsdm_adc_resume(struct device *dev)
        }
 
        if (iio_buffer_enabled(indio_dev))
-               __stm32_dfsdm_postenable(indio_dev);
+               stm32_dfsdm_postenable(indio_dev);
 
        return 0;
 }
index 0f88048..fba659b 100644 (file)
@@ -297,7 +297,6 @@ static int stmpe_adc_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, indio_dev);
 
        indio_dev->name         = dev_name(&pdev->dev);
-       indio_dev->dev.parent   = &pdev->dev;
        indio_dev->info         = &stmpe_adc_iio_info;
        indio_dev->modes        = INDIO_DIRECT_MODE;
 
index f87bbc7..55bd2dc 100644 (file)
@@ -319,7 +319,6 @@ static int stx104_probe(struct device *dev, unsigned int id)
        }
 
        indio_dev->name = dev_name(dev);
-       indio_dev->dev.parent = dev;
 
        priv = iio_priv(indio_dev);
        priv->base = base[id];
index 0f2c173..99b43f2 100644 (file)
@@ -619,8 +619,6 @@ static int sun4i_gpadc_probe(struct platform_device *pdev)
        info->indio_dev = indio_dev;
        init_completion(&info->completion);
        indio_dev->name = dev_name(&pdev->dev);
-       indio_dev->dev.parent = &pdev->dev;
-       indio_dev->dev.of_node = pdev->dev.of_node;
        indio_dev->info = &sun4i_gpadc_iio_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
index 0235863..9426f70 100644 (file)
@@ -6,9 +6,9 @@
  * Copyright (C) 2016 Intel
  *
  * Datasheets:
- *     http://www.ti.com/lit/ds/symlink/adc081c021.pdf
- *     http://www.ti.com/lit/ds/symlink/adc101c021.pdf
- *     http://www.ti.com/lit/ds/symlink/adc121c021.pdf
+ *     https://www.ti.com/lit/ds/symlink/adc081c021.pdf
+ *     https://www.ti.com/lit/ds/symlink/adc101c021.pdf
+ *     https://www.ti.com/lit/ds/symlink/adc121c021.pdf
  *
  * The devices have a very similar interface and differ mostly in the number of
  * bits handled. For the 8-bit and 10-bit models the least-significant 4 or 2
@@ -18,7 +18,7 @@
 #include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
-#include <linux/of.h>
+#include <linux/mod_devicetable.h>
 #include <linux/acpi.h>
 
 #include <linux/iio/iio.h>
@@ -181,8 +181,6 @@ static int adc081c_probe(struct i2c_client *client,
        if (err < 0)
                return err;
 
-       iio->dev.parent = &client->dev;
-       iio->dev.of_node = client->dev.of_node;
        iio->name = dev_name(&client->dev);
        iio->modes = INDIO_DIRECT_MODE;
        iio->info = &adc081c_info;
@@ -232,7 +230,6 @@ static const struct i2c_device_id adc081c_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, adc081c_id);
 
-#ifdef CONFIG_OF
 static const struct of_device_id adc081c_of_match[] = {
        { .compatible = "ti,adc081c" },
        { .compatible = "ti,adc101c" },
@@ -240,7 +237,6 @@ static const struct of_device_id adc081c_of_match[] = {
        { }
 };
 MODULE_DEVICE_TABLE(of, adc081c_of_match);
-#endif
 
 #ifdef CONFIG_ACPI
 static const struct acpi_device_id adc081c_acpi_match[] = {
@@ -255,7 +251,7 @@ MODULE_DEVICE_TABLE(acpi, adc081c_acpi_match);
 static struct i2c_driver adc081c_driver = {
        .driver = {
                .name = "adc081c",
-               .of_match_table = of_match_ptr(adc081c_of_match),
+               .of_match_table = adc081c_of_match,
                .acpi_match_table = ACPI_PTR(adc081c_acpi_match),
        },
        .probe = adc081c_probe,
index 6ea39f4..c7a085d 100644 (file)
@@ -4,10 +4,11 @@
  *
  * Copyright (c) 2016 Akinobu Mita <akinobu.mita@gmail.com>
  *
- * Datasheet: http://www.ti.com/lit/ds/symlink/adc0832-n.pdf
+ * Datasheet: https://www.ti.com/lit/ds/symlink/adc0832-n.pdf
  */
 
 #include <linux/module.h>
+#include <linux/mod_devicetable.h>
 #include <linux/spi/spi.h>
 #include <linux/iio/iio.h>
 #include <linux/regulator/consumer.h>
@@ -245,8 +246,6 @@ static int adc0832_probe(struct spi_device *spi)
        mutex_init(&adc->lock);
 
        indio_dev->name = spi_get_device_id(spi)->name;
-       indio_dev->dev.parent = &spi->dev;
-       indio_dev->dev.of_node = spi->dev.of_node;
        indio_dev->info = &adc0832_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
@@ -315,8 +314,6 @@ static int adc0832_remove(struct spi_device *spi)
        return 0;
 }
 
-#ifdef CONFIG_OF
-
 static const struct of_device_id adc0832_dt_ids[] = {
        { .compatible = "ti,adc0831", },
        { .compatible = "ti,adc0832", },
@@ -326,8 +323,6 @@ static const struct of_device_id adc0832_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, adc0832_dt_ids);
 
-#endif
-
 static const struct spi_device_id adc0832_id[] = {
        { "adc0831", adc0831 },
        { "adc0832", adc0832 },
@@ -340,7 +335,7 @@ MODULE_DEVICE_TABLE(spi, adc0832_id);
 static struct spi_driver adc0832_driver = {
        .driver = {
                .name = "adc0832",
-               .of_match_table = of_match_ptr(adc0832_dt_ids),
+               .of_match_table = adc0832_dt_ids,
        },
        .probe = adc0832_probe,
        .remove = adc0832_remove,
index bdedf45..9017e1e 100644 (file)
@@ -4,12 +4,13 @@
  *
  * Driver for Texas Instruments' ADC084S021 ADC chip.
  * Datasheets can be found here:
- * http://www.ti.com/lit/ds/symlink/adc084s021.pdf
+ * https://www.ti.com/lit/ds/symlink/adc084s021.pdf
  */
 
 #include <linux/err.h>
 #include <linux/spi/spi.h>
 #include <linux/module.h>
+#include <linux/mod_devicetable.h>
 #include <linux/interrupt.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/buffer.h>
@@ -187,8 +188,6 @@ static const struct iio_info adc084s021_info = {
 
 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,
 };
 
@@ -211,8 +210,6 @@ static int adc084s021_probe(struct spi_device *spi)
        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;
@@ -258,7 +255,7 @@ 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),
+               .of_match_table = adc084s021_of_match,
        },
        .probe = adc084s021_probe,
        .id_table = adc084s021_id,
index de9aaeb..9b9b274 100644 (file)
@@ -252,7 +252,6 @@ static int adc108s102_probe(struct spi_device *spi)
        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);
index 68a9dcb..e485719 100644 (file)
@@ -407,7 +407,6 @@ static int adc12138_probe(struct spi_device *spi)
        init_completion(&adc->complete);
 
        indio_dev->name = spi_get_device_id(spi)->name;
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &adc12138_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
index 1e5a936..e86f55c 100644 (file)
@@ -4,9 +4,9 @@
  *
  * Driver for Texas Instruments' ADC128S052, ADC122S021 and ADC124S021 ADC chip.
  * Datasheets can be found here:
- * http://www.ti.com/lit/ds/symlink/adc128s052.pdf
- * http://www.ti.com/lit/ds/symlink/adc122s021.pdf
- * http://www.ti.com/lit/ds/symlink/adc124s021.pdf
+ * https://www.ti.com/lit/ds/symlink/adc128s052.pdf
+ * https://www.ti.com/lit/ds/symlink/adc122s021.pdf
+ * https://www.ti.com/lit/ds/symlink/adc124s021.pdf
  */
 
 #include <linux/acpi.h>
@@ -152,8 +152,6 @@ static int adc128_probe(struct spi_device *spi)
 
        spi_set_drvdata(spi, indio_dev);
 
-       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 = &adc128_info;
index 3bbc9b9..607791f 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/mod_devicetable.h>
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/spi/spi.h>
@@ -179,8 +180,6 @@ static int ti_adc_probe(struct spi_device *spi)
                return -ENOMEM;
 
        indio_dev->info = &ti_adc_info;
-       indio_dev->dev.parent = &spi->dev;
-       indio_dev->dev.of_node = spi->dev.of_node;
        indio_dev->name = TI_ADC_DRV_NAME;
        indio_dev->modes = INDIO_DIRECT_MODE;
        spi_set_drvdata(spi, indio_dev);
@@ -259,7 +258,7 @@ MODULE_DEVICE_TABLE(spi, ti_adc_id);
 static struct spi_driver ti_adc_driver = {
        .driver = {
                .name   = TI_ADC_DRV_NAME,
-               .of_match_table = of_match_ptr(ti_adc_dt_ids),
+               .of_match_table = ti_adc_dt_ids,
        },
        .probe          = ti_adc_probe,
        .remove         = ti_adc_remove,
index 5ea4f45..f42ab11 100644 (file)
@@ -788,8 +788,6 @@ static int ads1015_buffer_postdisable(struct iio_dev *indio_dev)
 
 static const struct iio_buffer_setup_ops ads1015_buffer_setup_ops = {
        .preenable      = ads1015_buffer_preenable,
-       .postenable     = iio_triggered_buffer_postenable,
-       .predisable     = iio_triggered_buffer_predisable,
        .postdisable    = ads1015_buffer_postdisable,
        .validate_scan_mask = &iio_validate_scan_mask_onehot,
 };
@@ -939,8 +937,6 @@ static int ads1015_probe(struct i2c_client *client,
 
        mutex_init(&data->lock);
 
-       indio_dev->dev.parent = &client->dev;
-       indio_dev->dev.of_node = client->dev.of_node;
        indio_dev->name = ADS1015_DRV_NAME;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
index f1ee3b1..4b4fbe3 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /* TI ADS124S0X chip family driver
- * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com/
  */
 
 #include <linux/err.h>
@@ -325,8 +325,6 @@ static int ads124s_probe(struct spi_device *spi)
        ads124s_priv->spi = spi;
 
        indio_dev->name = spi_id->name;
-       indio_dev->dev.parent = &spi->dev;
-       indio_dev->dev.of_node = spi->dev.of_node;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = ads124s_priv->chip_info->channels;
        indio_dev->num_channels = ads124s_priv->chip_info->num_channels;
index f9edc12..2383eac 100644 (file)
@@ -9,7 +9,7 @@
  * Copyright 2012 CS Systemes d'Information
  *
  * And also on hwmon/ads79xx.c
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2013 Texas Instruments Incorporated - https://www.ti.com/
  *     Nishanth Menon
  */
 
@@ -557,7 +557,6 @@ static int ti_ads7950_probe(struct spi_device *spi)
        info = &ti_ads7950_chip_info[spi_get_device_id(spi)->driver_data];
 
        indio_dev->name = spi_get_device_id(spi)->name;
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = info->channels;
        indio_dev->num_channels = info->num_channels;
index 8a87920..a345a30 100644 (file)
@@ -4,7 +4,7 @@
  *
  * Author: Gregory CLEMENT <gregory.clement@bootlin.com>
  *
- * Datasheet: http://www.ti.com/lit/ds/symlink/ads8344.pdf
+ * Datasheet: https://www.ti.com/lit/ds/symlink/ads8344.pdf
  */
 
 #include <linux/delay.h>
@@ -148,8 +148,6 @@ static int ads8344_probe(struct spi_device *spi)
        mutex_init(&adc->lock);
 
        indio_dev->name = dev_name(&spi->dev);
-       indio_dev->dev.parent = &spi->dev;
-       indio_dev->dev.of_node = spi->dev.of_node;
        indio_dev->info = &ads8344_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = ads8344_channels;
index 14fe7c3..16bcb37 100644 (file)
@@ -449,8 +449,6 @@ static int ads8688_probe(struct spi_device *spi)
        st->spi = spi;
 
        indio_dev->name = spi_get_device_id(spi)->name;
-       indio_dev->dev.parent = &spi->dev;
-       indio_dev->dev.of_node = spi->dev.of_node;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = st->chip_info->channels;
        indio_dev->num_channels = st->chip_info->num_channels;
index 7762035..403b787 100644 (file)
@@ -5,8 +5,8 @@
  * Copyright (C) 2017 Phil Reid
  *
  * Datasheets can be found here:
- * http://www.ti.com/lit/gpn/tlc3541
- * http://www.ti.com/lit/gpn/tlc4541
+ * https://www.ti.com/lit/gpn/tlc3541
+ * https://www.ti.com/lit/gpn/tlc4541
  *
  * The tlc4541 requires 24 clock cycles to start a transfer.
  * Conversion then takes 2.94us to complete before data is ready
@@ -24,6 +24,7 @@
 #include <linux/iio/triggered_buffer.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/mod_devicetable.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/spi/spi.h>
@@ -177,7 +178,6 @@ static int tlc4541_probe(struct spi_device *spi)
        info = &tlc4541_chip_info[spi_get_device_id(spi)->driver_data];
 
        indio_dev->name = spi_get_device_id(spi)->name;
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = info->channels;
        indio_dev->num_channels = info->num_channels;
@@ -236,14 +236,12 @@ static int tlc4541_remove(struct spi_device *spi)
        return 0;
 }
 
-#ifdef CONFIG_OF
 static const struct of_device_id tlc4541_dt_ids[] = {
        { .compatible = "ti,tlc3541", },
        { .compatible = "ti,tlc4541", },
        {}
 };
 MODULE_DEVICE_TABLE(of, tlc4541_dt_ids);
-#endif
 
 static const struct spi_device_id tlc4541_id[] = {
        {"tlc3541", TLC3541},
@@ -255,7 +253,7 @@ MODULE_DEVICE_TABLE(spi, tlc4541_id);
 static struct spi_driver tlc4541_driver = {
        .driver = {
                .name   = "tlc4541",
-               .of_match_table = of_match_ptr(tlc4541_dt_ids),
+               .of_match_table = tlc4541_dt_ids,
        },
        .probe          = tlc4541_probe,
        .remove         = tlc4541_remove,
index 9d984f2..93ea32b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * TI ADC MFD driver
  *
- * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -377,7 +377,8 @@ static const struct iio_buffer_setup_ops tiadc_buffer_setup_ops = {
        .postdisable = &tiadc_buffer_postdisable,
 };
 
-static int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev,
+static int tiadc_iio_buffered_hardware_setup(struct device *dev,
+       struct iio_dev *indio_dev,
        irqreturn_t (*pollfunc_bh)(int irq, void *p),
        irqreturn_t (*pollfunc_th)(int irq, void *p),
        int irq,
@@ -387,13 +388,13 @@ static int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev,
        struct iio_buffer *buffer;
        int ret;
 
-       buffer = iio_kfifo_allocate();
+       buffer = devm_iio_kfifo_allocate(dev);
        if (!buffer)
                return -ENOMEM;
 
        iio_device_attach_buffer(indio_dev, buffer);
 
-       ret = request_threaded_irq(irq, pollfunc_th, pollfunc_bh,
+       ret = devm_request_threaded_irq(dev, irq, pollfunc_th, pollfunc_bh,
                                flags, indio_dev->name, indio_dev);
        if (ret)
                goto error_kfifo_free;
@@ -408,15 +409,6 @@ error_kfifo_free:
        return ret;
 }
 
-static void tiadc_iio_buffered_hardware_remove(struct iio_dev *indio_dev)
-{
-       struct tiadc_device *adc_dev = iio_priv(indio_dev);
-
-       free_irq(adc_dev->mfd_tscadc->irq, indio_dev);
-       iio_kfifo_free(indio_dev->buffer);
-}
-
-
 static const char * const chan_name_ain[] = {
        "AIN0",
        "AIN1",
@@ -428,7 +420,8 @@ static const char * const chan_name_ain[] = {
        "AIN7",
 };
 
-static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
+static int tiadc_channel_init(struct device *dev, struct iio_dev *indio_dev,
+                             int channels)
 {
        struct tiadc_device *adc_dev = iio_priv(indio_dev);
        struct iio_chan_spec *chan_array;
@@ -436,7 +429,8 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
        int i;
 
        indio_dev->num_channels = channels;
-       chan_array = kcalloc(channels, sizeof(*chan_array), GFP_KERNEL);
+       chan_array = devm_kcalloc(dev, channels, sizeof(*chan_array),
+                                 GFP_KERNEL);
        if (chan_array == NULL)
                return -ENOMEM;
 
@@ -459,11 +453,6 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
        return 0;
 }
 
-static void tiadc_channels_remove(struct iio_dev *indio_dev)
-{
-       kfree(indio_dev->channels);
-}
-
 static int tiadc_read_raw(struct iio_dev *indio_dev,
                struct iio_chan_spec const *chan,
                int *val, int *val2, long mask)
@@ -626,7 +615,6 @@ static int tiadc_probe(struct platform_device *pdev)
        adc_dev->mfd_tscadc = ti_tscadc_dev_get(pdev);
        tiadc_parse_dt(pdev, adc_dev);
 
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->name = dev_name(&pdev->dev);
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &tiadc_info;
@@ -635,11 +623,11 @@ static int tiadc_probe(struct platform_device *pdev)
        tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD);
        mutex_init(&adc_dev->fifo1_lock);
 
-       err = tiadc_channel_init(indio_dev, adc_dev->channels);
+       err = tiadc_channel_init(&pdev->dev, indio_dev, adc_dev->channels);
        if (err < 0)
                return err;
 
-       err = tiadc_iio_buffered_hardware_setup(indio_dev,
+       err = tiadc_iio_buffered_hardware_setup(&pdev->dev, indio_dev,
                &tiadc_worker_h,
                &tiadc_irq_h,
                adc_dev->mfd_tscadc->irq,
@@ -664,9 +652,7 @@ static int tiadc_probe(struct platform_device *pdev)
 err_dma:
        iio_device_unregister(indio_dev);
 err_buffer_unregister:
-       tiadc_iio_buffered_hardware_remove(indio_dev);
 err_free_channels:
-       tiadc_channels_remove(indio_dev);
        return err;
 }
 
@@ -683,8 +669,6 @@ static int tiadc_remove(struct platform_device *pdev)
                dma_release_channel(dma->chan);
        }
        iio_device_unregister(indio_dev);
-       tiadc_iio_buffered_hardware_remove(indio_dev);
-       tiadc_channels_remove(indio_dev);
 
        step_en = get_adc_step_mask(adc_dev);
        am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
index 472b08f..463634d 100644 (file)
@@ -5,7 +5,7 @@
  * conversion of analog signals like battery temperature,
  * battery type, battery level etc.
  *
- * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2011 Texas Instruments Incorporated - https://www.ti.com/
  * J Keerthy <j-keerthy@ti.com>
  *
  * Based on twl4030-madc.c
@@ -772,8 +772,6 @@ static int twl4030_madc_probe(struct platform_device *pdev)
        madc->dev = &pdev->dev;
 
        iio_dev->name = dev_name(&pdev->dev);
-       iio_dev->dev.parent = &pdev->dev;
-       iio_dev->dev.of_node = pdev->dev.of_node;
        iio_dev->info = &twl4030_madc_iio_info;
        iio_dev->modes = INDIO_DIRECT_MODE;
        iio_dev->channels = twl4030_madc_iio_channels;
index f24148b..bd501a0 100644 (file)
@@ -926,7 +926,6 @@ static int twl6030_gpadc_probe(struct platform_device *pdev)
        }
 
        indio_dev->name = DRIVER_NAME;
-       indio_dev->dev.parent = dev;
        indio_dev->info = &twl6030_gpadc_iio_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = pdata->iio_channels;
index cb7380b..1d794cf 100644 (file)
@@ -724,13 +724,8 @@ static int vf610_adc_buffer_postenable(struct iio_dev *indio_dev)
 {
        struct vf610_adc *info = iio_priv(indio_dev);
        unsigned int channel;
-       int ret;
        int val;
 
-       ret = iio_triggered_buffer_postenable(indio_dev);
-       if (ret)
-               return ret;
-
        val = readl(info->regs + VF610_REG_ADC_GC);
        val |= VF610_ADC_ADCON;
        writel(val, info->regs + VF610_REG_ADC_GC);
@@ -761,7 +756,7 @@ static int vf610_adc_buffer_predisable(struct iio_dev *indio_dev)
 
        writel(hc_cfg, info->regs + VF610_REG_ADC_HC0);
 
-       return iio_triggered_buffer_predisable(indio_dev);
+       return 0;
 }
 
 static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
@@ -860,8 +855,6 @@ static int vf610_adc_probe(struct platform_device *pdev)
        init_completion(&info->completion);
 
        indio_dev->name = dev_name(&pdev->dev);
-       indio_dev->dev.parent = &pdev->dev;
-       indio_dev->dev.of_node = pdev->dev.of_node;
        indio_dev->info = &vf610_adc_iio_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = vf610_adc_iio_channels;
index 1d2aeb0..1028b10 100644 (file)
@@ -121,7 +121,6 @@ static int vprbrd_adc_probe(struct platform_device *pdev)
        adc = iio_priv(indio_dev);
        adc->vb = vb;
        indio_dev->name = "viperboard adc";
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->info = &vprbrd_adc_iio_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = vprbrd_adc_iio_channels;
index d7fecab..d0b7ef2 100644 (file)
@@ -839,8 +839,6 @@ err:
 
 static const struct iio_buffer_setup_ops xadc_buffer_ops = {
        .preenable = &xadc_preenable,
-       .postenable = &iio_triggered_buffer_postenable,
-       .predisable = &iio_triggered_buffer_predisable,
        .postdisable = &xadc_postdisable,
 };
 
@@ -1221,8 +1219,6 @@ static int xadc_probe(struct platform_device *pdev)
        if (IS_ERR(xadc->base))
                return PTR_ERR(xadc->base);
 
-       indio_dev->dev.parent = &pdev->dev;
-       indio_dev->dev.of_node = pdev->dev.of_node;
        indio_dev->name = "xadc";
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &xadc_info;
index e9ceee6..69c0f27 100644 (file)
@@ -314,7 +314,6 @@ static int rescale_probe(struct platform_device *pdev)
        rescale->source = source;
 
        indio_dev->name = dev_name(dev);
-       indio_dev->dev.parent = dev;
        indio_dev->info = &rescale_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = &rescale->chan;
index 62167b8..cfcf18a 100644 (file)
@@ -262,8 +262,11 @@ static int ad8366_probe(struct spi_device *spi)
        case ID_ADA4961:
        case ID_ADL5240:
        case ID_HMC1119:
-               st->reset_gpio = devm_gpiod_get(&spi->dev, "reset",
-                       GPIOD_OUT_HIGH);
+               st->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset", GPIOD_OUT_HIGH);
+               if (IS_ERR(st->reset_gpio)) {
+                       ret = PTR_ERR(st->reset_gpio);
+                       goto error_disable_reg;
+               }
                indio_dev->channels = ada4961_channels;
                indio_dev->num_channels = ARRAY_SIZE(ada4961_channels);
                break;
@@ -274,7 +277,6 @@ static int ad8366_probe(struct spi_device *spi)
        }
 
        st->info = &ad8366_infos[st->type];
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->info = &ad8366_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index d9e6e96..5827089 100644 (file)
@@ -227,7 +227,6 @@ static int hmc425a_probe(struct platform_device *pdev)
 
        mutex_init(&st->lock);
 
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->info = &hmc425a_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
index e8046c1..6c20a83 100644 (file)
 #include <linux/iio/triggered_buffer.h>
 #include <linux/iio/trigger_consumer.h>
 
-static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
-       .postenable = &iio_triggered_buffer_postenable,
-       .predisable = &iio_triggered_buffer_predisable,
-};
-
 /**
  * iio_triggered_buffer_setup() - Setup triggered buffer and pollfunc
  * @indio_dev:         IIO device structure
@@ -67,10 +62,7 @@ int iio_triggered_buffer_setup(struct iio_dev *indio_dev,
        }
 
        /* Ring buffer functions - here trigger setup related */
-       if (setup_ops)
-               indio_dev->setup_ops = setup_ops;
-       else
-               indio_dev->setup_ops = &iio_triggered_buffer_setup_ops;
+       indio_dev->setup_ops = setup_ops;
 
        /* Flag that polled ring buffering is possible */
        indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
index 7f21afd..10bb431 100644 (file)
@@ -85,6 +85,39 @@ config PMS7003
          To compile this driver as a module, choose M here: the module will
          be called pms7003.
 
+config SCD30_CORE
+       tristate "SCD30 carbon dioxide sensor driver"
+       select IIO_BUFFER
+       select IIO_TRIGGERED_BUFFER
+       help
+         Say Y here to build support for the Sensirion SCD30 sensor with carbon
+         dioxide, relative humidity and temperature sensing capabilities.
+
+         To compile this driver as a module, choose M here: the module will
+         be called scd30_core.
+
+config SCD30_I2C
+       tristate "SCD30 carbon dioxide sensor I2C driver"
+       depends on SCD30_CORE && I2C
+       select CRC8
+       help
+         Say Y here to build support for the Sensirion SCD30 I2C interface
+         driver.
+
+         To compile this driver as a module, choose M here: the module will
+         be called scd30_i2c.
+
+config SCD30_SERIAL
+       tristate "SCD30 carbon dioxide sensor serial driver"
+       depends on SCD30_CORE && SERIAL_DEV_BUS
+       select CRC16
+       help
+         Say Y here to build support for the Sensirion SCD30 serial interface
+         driver.
+
+         To compile this driver as a module, choose M here: the module will
+         be called scd30_serial.
+
 config SENSIRION_SGP30
        tristate "Sensirion SGPxx gas sensors"
        depends on I2C
index aba4167..fef63dd 100644 (file)
@@ -12,6 +12,9 @@ obj-$(CONFIG_BME680_SPI) += bme680_spi.o
 obj-$(CONFIG_CCS811)           += ccs811.o
 obj-$(CONFIG_IAQCORE)          += ams-iaq-core.o
 obj-$(CONFIG_PMS7003) += pms7003.o
+obj-$(CONFIG_SCD30_CORE) += scd30_core.o
+obj-$(CONFIG_SCD30_I2C) += scd30_i2c.o
+obj-$(CONFIG_SCD30_SERIAL) += scd30_serial.o
 obj-$(CONFIG_SENSIRION_SGP30)  += sgp30.o
 obj-$(CONFIG_SPS30) += sps30.o
 obj-$(CONFIG_VZ89X)            += vz89x.o
index a0646ba..8c1b64f 100644 (file)
@@ -152,7 +152,6 @@ static int ams_iaqcore_probe(struct i2c_client *client,
        data->last_update = jiffies - HZ;
        mutex_init(&data->lock);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &ams_iaqcore_info;
        indio_dev->name = dev_name(&client->dev);
        indio_dev->modes = INDIO_DIRECT_MODE;
index f5a6d8e..8b72bb0 100644 (file)
@@ -69,13 +69,13 @@ static int atlas_ezo_read_raw(struct iio_dev *indio_dev,
 {
        struct atlas_ezo_data *data = iio_priv(indio_dev);
        struct i2c_client *client = data->client;
-       int ret = 0;
 
        if (chan->type != IIO_CONCENTRATION)
                return -EINVAL;
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW: {
+               int ret;
                long tmp;
 
                mutex_lock(&data->lock);
@@ -110,7 +110,7 @@ static int atlas_ezo_read_raw(struct iio_dev *indio_dev,
                return IIO_VAL_INT_PLUS_MICRO;
        }
 
-       return ret;
+       return 0;
 }
 
 static const struct iio_info atlas_info = {
@@ -152,7 +152,6 @@ static int atlas_ezo_probe(struct i2c_client *client,
        indio_dev->channels = chip->channels;
        indio_dev->num_channels = chip->num_channels;
        indio_dev->modes = INDIO_DIRECT_MODE;
-       indio_dev->dev.parent = &client->dev;
 
        data = iio_priv(indio_dev);
        data->client = client;
index 78a27e3..4306963 100644 (file)
@@ -410,10 +410,6 @@ static int atlas_buffer_postenable(struct iio_dev *indio_dev)
        struct atlas_data *data = iio_priv(indio_dev);
        int ret;
 
-       ret = iio_triggered_buffer_postenable(indio_dev);
-       if (ret)
-               return ret;
-
        ret = pm_runtime_get_sync(&data->client->dev);
        if (ret < 0) {
                pm_runtime_put_noidle(&data->client->dev);
@@ -437,7 +433,7 @@ static int atlas_buffer_predisable(struct iio_dev *indio_dev)
        if (ret)
                return ret;
 
-       return iio_triggered_buffer_predisable(indio_dev);
+       return 0;
 }
 
 static const struct iio_trigger_ops atlas_interrupt_trigger_ops = {
@@ -644,7 +640,6 @@ static int atlas_probe(struct i2c_client *client,
        indio_dev->channels = chip->channels;
        indio_dev->num_channels = chip->num_channels;
        indio_dev->modes = INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE;
-       indio_dev->dev.parent = &client->dev;
 
        trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d",
                                      indio_dev->name, indio_dev->id);
index 13773e0..6ea99e4 100644 (file)
@@ -923,7 +923,6 @@ int bme680_core_probe(struct device *dev, struct regmap *regmap,
        data = iio_priv(indio_dev);
        dev_set_drvdata(dev, indio_dev);
        data->regmap = regmap;
-       indio_dev->dev.parent = dev;
        indio_dev->name = name;
        indio_dev->channels = bme680_channels;
        indio_dev->num_channels = ARRAY_SIZE(bme680_channels);
index 3ecd633..2b007e7 100644 (file)
@@ -464,7 +464,6 @@ static int ccs811_probe(struct i2c_client *client,
 
        mutex_init(&data->lock);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->name = id->name;
        indio_dev->info = &ccs811_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 07bb90d..e9d4405 100644 (file)
@@ -280,7 +280,6 @@ static int pms7003_probe(struct serdev_device *serdev)
        state = iio_priv(indio_dev);
        serdev_device_set_drvdata(serdev, indio_dev);
        state->serdev = serdev;
-       indio_dev->dev.parent = &serdev->dev;
        indio_dev->info = &pms7003_info;
        indio_dev->name = PMS7003_DRIVER_NAME;
        indio_dev->channels = pms7003_channels,
diff --git a/drivers/iio/chemical/scd30.h b/drivers/iio/chemical/scd30.h
new file mode 100644 (file)
index 0000000..f60127b
--- /dev/null
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SCD30_H
+#define _SCD30_H
+
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/pm.h>
+#include <linux/regulator/consumer.h>
+#include <linux/types.h>
+
+struct scd30_state;
+
+enum scd30_cmd {
+       /* start continuous measurement with pressure compensation */
+       CMD_START_MEAS,
+       /* stop continuous measurement */
+       CMD_STOP_MEAS,
+       /* set/get measurement interval */
+       CMD_MEAS_INTERVAL,
+       /* check whether new measurement is ready */
+       CMD_MEAS_READY,
+       /* get measurement */
+       CMD_READ_MEAS,
+       /* turn on/off automatic self calibration */
+       CMD_ASC,
+       /* set/get forced recalibration value */
+       CMD_FRC,
+       /* set/get temperature offset */
+       CMD_TEMP_OFFSET,
+       /* get firmware version */
+       CMD_FW_VERSION,
+       /* reset sensor */
+       CMD_RESET,
+       /*
+        * Command for altitude compensation was omitted intentionally because
+        * the same can be achieved by means of CMD_START_MEAS which takes
+        * pressure above the sea level as an argument.
+        */
+};
+
+#define SCD30_MEAS_COUNT 3
+
+typedef int (*scd30_command_t)(struct scd30_state *state, enum scd30_cmd cmd, u16 arg,
+                              void *response, int size);
+
+struct scd30_state {
+       /* serialize access to the device */
+       struct mutex lock;
+       struct device *dev;
+       struct regulator *vdd;
+       struct completion meas_ready;
+       /*
+        * priv pointer is solely for serdev driver private data. We keep it
+        * here because driver_data inside dev has been already used for iio and
+        * struct serdev_device doesn't have one.
+        */
+       void *priv;
+       int irq;
+       /*
+        * no way to retrieve current ambient pressure compensation value from
+        * the sensor so keep one around
+        */
+       u16 pressure_comp;
+       u16 meas_interval;
+       int meas[SCD30_MEAS_COUNT];
+
+       scd30_command_t command;
+};
+
+int scd30_suspend(struct device *dev);
+int scd30_resume(struct device *dev);
+
+static __maybe_unused SIMPLE_DEV_PM_OPS(scd30_pm_ops, scd30_suspend, scd30_resume);
+
+int scd30_probe(struct device *dev, int irq, const char *name, void *priv, scd30_command_t command);
+
+#endif
diff --git a/drivers/iio/chemical/scd30_core.c b/drivers/iio/chemical/scd30_core.c
new file mode 100644 (file)
index 0000000..eac7697
--- /dev/null
@@ -0,0 +1,771 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Sensirion SCD30 carbon dioxide sensor core driver
+ *
+ * Copyright (c) 2020 Tomasz Duszynski <tomasz.duszynski@octakon.com>
+ */
+#include <linux/bits.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/types.h>
+#include <linux/interrupt.h>
+#include <linux/irqreturn.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/regulator/consumer.h>
+#include <linux/string.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+#include "scd30.h"
+
+#define SCD30_PRESSURE_COMP_MIN_MBAR 700
+#define SCD30_PRESSURE_COMP_MAX_MBAR 1400
+#define SCD30_PRESSURE_COMP_DEFAULT 1013
+#define SCD30_MEAS_INTERVAL_MIN_S 2
+#define SCD30_MEAS_INTERVAL_MAX_S 1800
+#define SCD30_MEAS_INTERVAL_DEFAULT SCD30_MEAS_INTERVAL_MIN_S
+#define SCD30_FRC_MIN_PPM 400
+#define SCD30_FRC_MAX_PPM 2000
+#define SCD30_TEMP_OFFSET_MAX 655360
+#define SCD30_EXTRA_TIMEOUT_PER_S 250
+
+enum {
+       SCD30_CONC,
+       SCD30_TEMP,
+       SCD30_HR,
+};
+
+static int scd30_command_write(struct scd30_state *state, enum scd30_cmd cmd, u16 arg)
+{
+       return state->command(state, cmd, arg, NULL, 0);
+}
+
+static int scd30_command_read(struct scd30_state *state, enum scd30_cmd cmd, u16 *val)
+{
+       __be16 tmp;
+       int ret;
+
+       ret = state->command(state, cmd, 0, &tmp, sizeof(tmp));
+       *val = be16_to_cpup(&tmp);
+
+       return ret;
+}
+
+static int scd30_reset(struct scd30_state *state)
+{
+       int ret;
+       u16 val;
+
+       ret = scd30_command_write(state, CMD_RESET, 0);
+       if (ret)
+               return ret;
+
+       /* sensor boots up within 2 secs */
+       msleep(2000);
+       /*
+        * Power-on-reset causes sensor to produce some glitch on i2c bus and
+        * some controllers end up in error state. Try to recover by placing
+        * any data on the bus.
+        */
+       scd30_command_read(state, CMD_MEAS_READY, &val);
+
+       return 0;
+}
+
+/* simplified float to fixed point conversion with a scaling factor of 0.01 */
+static int scd30_float_to_fp(int float32)
+{
+       int fraction, shift,
+           mantissa = float32 & GENMASK(22, 0),
+           sign = (float32 & BIT(31)) ? -1 : 1,
+           exp = (float32 & ~BIT(31)) >> 23;
+
+       /* special case 0 */
+       if (!exp && !mantissa)
+               return 0;
+
+       exp -= 127;
+       if (exp < 0) {
+               exp = -exp;
+               /* return values ranging from 1 to 99 */
+               return sign * ((((BIT(23) + mantissa) * 100) >> 23) >> exp);
+       }
+
+       /* return values starting at 100 */
+       shift = 23 - exp;
+       float32 = BIT(exp) + (mantissa >> shift);
+       fraction = mantissa & GENMASK(shift - 1, 0);
+
+       return sign * (float32 * 100 + ((fraction * 100) >> shift));
+}
+
+static int scd30_read_meas(struct scd30_state *state)
+{
+       int i, ret;
+
+       ret = state->command(state, CMD_READ_MEAS, 0, state->meas, sizeof(state->meas));
+       if (ret)
+               return ret;
+
+       be32_to_cpu_array(state->meas, (__be32 *)state->meas, ARRAY_SIZE(state->meas));
+
+       for (i = 0; i < ARRAY_SIZE(state->meas); i++)
+               state->meas[i] = scd30_float_to_fp(state->meas[i]);
+
+       /*
+        * co2 is left unprocessed while temperature and humidity are scaled
+        * to milli deg C and milli percent respectively.
+        */
+       state->meas[SCD30_TEMP] *= 10;
+       state->meas[SCD30_HR] *= 10;
+
+       return 0;
+}
+
+static int scd30_wait_meas_irq(struct scd30_state *state)
+{
+       int ret, timeout;
+
+       reinit_completion(&state->meas_ready);
+       enable_irq(state->irq);
+       timeout = msecs_to_jiffies(state->meas_interval * (1000 + SCD30_EXTRA_TIMEOUT_PER_S));
+       ret = wait_for_completion_interruptible_timeout(&state->meas_ready, timeout);
+       if (ret > 0)
+               ret = 0;
+       else if (!ret)
+               ret = -ETIMEDOUT;
+
+       disable_irq(state->irq);
+
+       return ret;
+}
+
+static int scd30_wait_meas_poll(struct scd30_state *state)
+{
+       int timeout = state->meas_interval * SCD30_EXTRA_TIMEOUT_PER_S, tries = 5;
+
+       do {
+               int ret;
+               u16 val;
+
+               ret = scd30_command_read(state, CMD_MEAS_READY, &val);
+               if (ret)
+                       return -EIO;
+
+               /* new measurement available */
+               if (val)
+                       break;
+
+               msleep_interruptible(timeout);
+       } while (--tries);
+
+       return tries ? 0 : -ETIMEDOUT;
+}
+
+static int scd30_read_poll(struct scd30_state *state)
+{
+       int ret;
+
+       ret = scd30_wait_meas_poll(state);
+       if (ret)
+               return ret;
+
+       return scd30_read_meas(state);
+}
+
+static int scd30_read(struct scd30_state *state)
+{
+       if (state->irq > 0)
+               return scd30_wait_meas_irq(state);
+
+       return scd30_read_poll(state);
+}
+
+static int scd30_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
+                         int *val, int *val2, long mask)
+{
+       struct scd30_state *state = iio_priv(indio_dev);
+       int ret = -EINVAL;
+       u16 tmp;
+
+       mutex_lock(&state->lock);
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+       case IIO_CHAN_INFO_PROCESSED:
+               if (chan->output) {
+                       *val = state->pressure_comp;
+                       ret = IIO_VAL_INT;
+                       break;
+               }
+
+               ret = iio_device_claim_direct_mode(indio_dev);
+               if (ret)
+                       break;
+
+               ret = scd30_read(state);
+               if (ret) {
+                       iio_device_release_direct_mode(indio_dev);
+                       break;
+               }
+
+               *val = state->meas[chan->address];
+               iio_device_release_direct_mode(indio_dev);
+               ret = IIO_VAL_INT;
+               break;
+       case IIO_CHAN_INFO_SCALE:
+               *val = 0;
+               *val2 = 1;
+               ret = IIO_VAL_INT_PLUS_MICRO;
+               break;
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               ret = scd30_command_read(state, CMD_MEAS_INTERVAL, &tmp);
+               if (ret)
+                       break;
+
+               *val = 0;
+               *val2 = 1000000000 / tmp;
+               ret = IIO_VAL_INT_PLUS_NANO;
+               break;
+       case IIO_CHAN_INFO_CALIBBIAS:
+               ret = scd30_command_read(state, CMD_TEMP_OFFSET, &tmp);
+               if (ret)
+                       break;
+
+               *val = tmp;
+               ret = IIO_VAL_INT;
+               break;
+       }
+       mutex_unlock(&state->lock);
+
+       return ret;
+}
+
+static int scd30_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
+                          int val, int val2, long mask)
+{
+       struct scd30_state *state = iio_priv(indio_dev);
+       int ret = -EINVAL;
+
+       mutex_lock(&state->lock);
+       switch (mask) {
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               if (val)
+                       break;
+
+               val = 1000000000 / val2;
+               if (val < SCD30_MEAS_INTERVAL_MIN_S || val > SCD30_MEAS_INTERVAL_MAX_S)
+                       break;
+
+               ret = scd30_command_write(state, CMD_MEAS_INTERVAL, val);
+               if (ret)
+                       break;
+
+               state->meas_interval = val;
+               break;
+       case IIO_CHAN_INFO_RAW:
+               switch (chan->type) {
+               case IIO_PRESSURE:
+                       if (val < SCD30_PRESSURE_COMP_MIN_MBAR ||
+                           val > SCD30_PRESSURE_COMP_MAX_MBAR)
+                               break;
+
+                       ret = scd30_command_write(state, CMD_START_MEAS, val);
+                       if (ret)
+                               break;
+
+                       state->pressure_comp = val;
+                       break;
+               default:
+                       break;
+               }
+               break;
+       case IIO_CHAN_INFO_CALIBBIAS:
+               if (val < 0 || val > SCD30_TEMP_OFFSET_MAX)
+                       break;
+               /*
+                * Manufacturer does not explicitly specify min/max sensible
+                * values hence check is omitted for simplicity.
+                */
+               ret = scd30_command_write(state, CMD_TEMP_OFFSET / 10, val);
+       }
+       mutex_unlock(&state->lock);
+
+       return ret;
+}
+
+static int scd30_write_raw_get_fmt(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
+                                  long mask)
+{
+       switch (mask) {
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               return IIO_VAL_INT_PLUS_NANO;
+       case IIO_CHAN_INFO_RAW:
+       case IIO_CHAN_INFO_CALIBBIAS:
+               return IIO_VAL_INT;
+       }
+
+       return -EINVAL;
+}
+
+static const int scd30_pressure_raw_available[] = {
+       SCD30_PRESSURE_COMP_MIN_MBAR, 1, SCD30_PRESSURE_COMP_MAX_MBAR,
+};
+
+static const int scd30_temp_calibbias_available[] = {
+       0, 10, SCD30_TEMP_OFFSET_MAX,
+};
+
+static int scd30_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
+                           const int **vals, int *type, int *length, long mask)
+{
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               *vals = scd30_pressure_raw_available;
+               *type = IIO_VAL_INT;
+
+               return IIO_AVAIL_RANGE;
+       case IIO_CHAN_INFO_CALIBBIAS:
+               *vals = scd30_temp_calibbias_available;
+               *type = IIO_VAL_INT;
+
+               return IIO_AVAIL_RANGE;
+       }
+
+       return -EINVAL;
+}
+
+static ssize_t sampling_frequency_available_show(struct device *dev, struct device_attribute *attr,
+                                                char *buf)
+{
+       int i = SCD30_MEAS_INTERVAL_MIN_S;
+       ssize_t len = 0;
+
+       do {
+               len += scnprintf(buf + len, PAGE_SIZE - len, "0.%09u ", 1000000000 / i);
+               /*
+                * Not all values fit PAGE_SIZE buffer hence print every 6th
+                * (each frequency differs by 6s in time domain from the
+                * adjacent). Unlisted but valid ones are still accepted.
+                */
+               i += 6;
+       } while (i <= SCD30_MEAS_INTERVAL_MAX_S);
+
+       buf[len - 1] = '\n';
+
+       return len;
+}
+
+static ssize_t calibration_auto_enable_show(struct device *dev, struct device_attribute *attr,
+                                           char *buf)
+{
+       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct scd30_state *state = iio_priv(indio_dev);
+       int ret;
+       u16 val;
+
+       mutex_lock(&state->lock);
+       ret = scd30_command_read(state, CMD_ASC, &val);
+       mutex_unlock(&state->lock);
+
+       return ret ?: sprintf(buf, "%d\n", val);
+}
+
+static ssize_t calibration_auto_enable_store(struct device *dev, struct device_attribute *attr,
+                                            const char *buf, size_t len)
+{
+       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct scd30_state *state = iio_priv(indio_dev);
+       bool val;
+       int ret;
+
+       ret = kstrtobool(buf, &val);
+       if (ret)
+               return ret;
+
+       mutex_lock(&state->lock);
+       ret = scd30_command_write(state, CMD_ASC, val);
+       mutex_unlock(&state->lock);
+
+       return ret ?: len;
+}
+
+static ssize_t calibration_forced_value_show(struct device *dev, struct device_attribute *attr,
+                                            char *buf)
+{
+       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct scd30_state *state = iio_priv(indio_dev);
+       int ret;
+       u16 val;
+
+       mutex_lock(&state->lock);
+       ret = scd30_command_read(state, CMD_FRC, &val);
+       mutex_unlock(&state->lock);
+
+       return ret ?: sprintf(buf, "%d\n", val);
+}
+
+static ssize_t calibration_forced_value_store(struct device *dev, struct device_attribute *attr,
+                                             const char *buf, size_t len)
+{
+       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct scd30_state *state = iio_priv(indio_dev);
+       int ret;
+       u16 val;
+
+       ret = kstrtou16(buf, 0, &val);
+       if (ret)
+               return ret;
+
+       if (val < SCD30_FRC_MIN_PPM || val > SCD30_FRC_MAX_PPM)
+               return -EINVAL;
+
+       mutex_lock(&state->lock);
+       ret = scd30_command_write(state, CMD_FRC, val);
+       mutex_unlock(&state->lock);
+
+       return ret ?: len;
+}
+
+static IIO_DEVICE_ATTR_RO(sampling_frequency_available, 0);
+static IIO_DEVICE_ATTR_RW(calibration_auto_enable, 0);
+static IIO_DEVICE_ATTR_RW(calibration_forced_value, 0);
+
+static struct attribute *scd30_attrs[] = {
+       &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+       &iio_dev_attr_calibration_auto_enable.dev_attr.attr,
+       &iio_dev_attr_calibration_forced_value.dev_attr.attr,
+       NULL
+};
+
+static const struct attribute_group scd30_attr_group = {
+       .attrs = scd30_attrs,
+};
+
+static const struct iio_info scd30_info = {
+       .attrs = &scd30_attr_group,
+       .read_raw = scd30_read_raw,
+       .write_raw = scd30_write_raw,
+       .write_raw_get_fmt = scd30_write_raw_get_fmt,
+       .read_avail = scd30_read_avail,
+};
+
+#define SCD30_CHAN_SCAN_TYPE(_sign, _realbits) .scan_type = { \
+       .sign = _sign, \
+       .realbits = _realbits, \
+       .storagebits = 32, \
+       .endianness = IIO_CPU, \
+}
+
+static const struct iio_chan_spec scd30_channels[] = {
+       {
+               /*
+                * this channel is special in a sense we are pretending that
+                * sensor is able to change measurement chamber pressure but in
+                * fact we're just setting pressure compensation value
+                */
+               .type = IIO_PRESSURE,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+               .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW),
+               .output = 1,
+               .scan_index = -1,
+       },
+       {
+               .type = IIO_CONCENTRATION,
+               .channel2 = IIO_MOD_CO2,
+               .address = SCD30_CONC,
+               .scan_index = SCD30_CONC,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+                                     BIT(IIO_CHAN_INFO_SCALE),
+               .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+               .modified = 1,
+
+               SCD30_CHAN_SCAN_TYPE('u', 20),
+       },
+       {
+               .type = IIO_TEMP,
+               .address = SCD30_TEMP,
+               .scan_index = SCD30_TEMP,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+                                     BIT(IIO_CHAN_INFO_CALIBBIAS),
+               .info_mask_separate_available = BIT(IIO_CHAN_INFO_CALIBBIAS),
+               .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+
+               SCD30_CHAN_SCAN_TYPE('s', 18),
+       },
+       {
+               .type = IIO_HUMIDITYRELATIVE,
+               .address = SCD30_HR,
+               .scan_index = SCD30_HR,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+               .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+
+               SCD30_CHAN_SCAN_TYPE('u', 17),
+       },
+       IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+int __maybe_unused scd30_suspend(struct device *dev)
+{
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct scd30_state *state  = iio_priv(indio_dev);
+       int ret;
+
+       ret = scd30_command_write(state, CMD_STOP_MEAS, 0);
+       if (ret)
+               return ret;
+
+       return regulator_disable(state->vdd);
+}
+EXPORT_SYMBOL(scd30_suspend);
+
+int __maybe_unused scd30_resume(struct device *dev)
+{
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct scd30_state *state = iio_priv(indio_dev);
+       int ret;
+
+       ret = regulator_enable(state->vdd);
+       if (ret)
+               return ret;
+
+       return scd30_command_write(state, CMD_START_MEAS, state->pressure_comp);
+}
+EXPORT_SYMBOL(scd30_resume);
+
+static void scd30_stop_meas(void *data)
+{
+       struct scd30_state *state = data;
+
+       scd30_command_write(state, CMD_STOP_MEAS, 0);
+}
+
+static void scd30_disable_regulator(void *data)
+{
+       struct scd30_state *state = data;
+
+       regulator_disable(state->vdd);
+}
+
+static irqreturn_t scd30_irq_handler(int irq, void *priv)
+{
+       struct iio_dev *indio_dev = priv;
+
+       if (iio_buffer_enabled(indio_dev)) {
+               iio_trigger_poll(indio_dev->trig);
+
+               return IRQ_HANDLED;
+       }
+
+       return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t scd30_irq_thread_handler(int irq, void *priv)
+{
+       struct iio_dev *indio_dev = priv;
+       struct scd30_state *state = iio_priv(indio_dev);
+       int ret;
+
+       ret = scd30_read_meas(state);
+       if (ret)
+               goto out;
+
+       complete_all(&state->meas_ready);
+out:
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t scd30_trigger_handler(int irq, void *p)
+{
+       struct iio_poll_func *pf = p;
+       struct iio_dev *indio_dev = pf->indio_dev;
+       struct scd30_state *state = iio_priv(indio_dev);
+       struct {
+               int data[SCD30_MEAS_COUNT];
+               s64 ts __aligned(8);
+       } scan;
+       int ret;
+
+       mutex_lock(&state->lock);
+       if (!iio_trigger_using_own(indio_dev))
+               ret = scd30_read_poll(state);
+       else
+               ret = scd30_read_meas(state);
+       memset(&scan, 0, sizeof(scan));
+       memcpy(scan.data, state->meas, sizeof(state->meas));
+       mutex_unlock(&state->lock);
+       if (ret)
+               goto out;
+
+       iio_push_to_buffers_with_timestamp(indio_dev, &scan, iio_get_time_ns(indio_dev));
+out:
+       iio_trigger_notify_done(indio_dev->trig);
+       return IRQ_HANDLED;
+}
+
+static int scd30_set_trigger_state(struct iio_trigger *trig, bool state)
+{
+       struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+       struct scd30_state *st = iio_priv(indio_dev);
+
+       if (state)
+               enable_irq(st->irq);
+       else
+               disable_irq(st->irq);
+
+       return 0;
+}
+
+static const struct iio_trigger_ops scd30_trigger_ops = {
+       .set_trigger_state = scd30_set_trigger_state,
+       .validate_device = iio_trigger_validate_own_device,
+};
+
+static int scd30_setup_trigger(struct iio_dev *indio_dev)
+{
+       struct scd30_state *state = iio_priv(indio_dev);
+       struct device *dev = indio_dev->dev.parent;
+       struct iio_trigger *trig;
+       int ret;
+
+       trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, indio_dev->id);
+       if (!trig) {
+               dev_err(dev, "failed to allocate trigger\n");
+               return -ENOMEM;
+       }
+
+       trig->dev.parent = dev;
+       trig->ops = &scd30_trigger_ops;
+       iio_trigger_set_drvdata(trig, indio_dev);
+
+       ret = devm_iio_trigger_register(dev, trig);
+       if (ret)
+               return ret;
+
+       indio_dev->trig = iio_trigger_get(trig);
+
+       ret = devm_request_threaded_irq(dev, state->irq, scd30_irq_handler,
+                                       scd30_irq_thread_handler, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+                                       indio_dev->name, indio_dev);
+       if (ret)
+               dev_err(dev, "failed to request irq\n");
+
+       /*
+        * Interrupt is enabled just before taking a fresh measurement
+        * and disabled afterwards. This means we need to disable it here
+        * to keep calls to enable/disable balanced.
+        */
+       disable_irq(state->irq);
+
+       return ret;
+}
+
+int scd30_probe(struct device *dev, int irq, const char *name, void *priv,
+               scd30_command_t command)
+{
+       static const unsigned long scd30_scan_masks[] = { 0x07, 0x00 };
+       struct scd30_state *state;
+       struct iio_dev *indio_dev;
+       int ret;
+       u16 val;
+
+       indio_dev = devm_iio_device_alloc(dev, sizeof(*state));
+       if (!indio_dev)
+               return -ENOMEM;
+
+       state = iio_priv(indio_dev);
+       state->dev = dev;
+       state->priv = priv;
+       state->irq = irq;
+       state->pressure_comp = SCD30_PRESSURE_COMP_DEFAULT;
+       state->meas_interval = SCD30_MEAS_INTERVAL_DEFAULT;
+       state->command = command;
+       mutex_init(&state->lock);
+       init_completion(&state->meas_ready);
+
+       dev_set_drvdata(dev, indio_dev);
+
+       indio_dev->info = &scd30_info;
+       indio_dev->name = name;
+       indio_dev->channels = scd30_channels;
+       indio_dev->num_channels = ARRAY_SIZE(scd30_channels);
+       indio_dev->modes = INDIO_DIRECT_MODE;
+       indio_dev->available_scan_masks = scd30_scan_masks;
+
+       state->vdd = devm_regulator_get(dev, "vdd");
+       if (IS_ERR(state->vdd)) {
+               if (PTR_ERR(state->vdd) == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
+
+               dev_err(dev, "failed to get regulator\n");
+               return PTR_ERR(state->vdd);
+       }
+
+       ret = regulator_enable(state->vdd);
+       if (ret)
+               return ret;
+
+       ret = devm_add_action_or_reset(dev, scd30_disable_regulator, state);
+       if (ret)
+               return ret;
+
+       ret = scd30_reset(state);
+       if (ret) {
+               dev_err(dev, "failed to reset device: %d\n", ret);
+               return ret;
+       }
+
+       if (state->irq > 0) {
+               ret = scd30_setup_trigger(indio_dev);
+               if (ret) {
+                       dev_err(dev, "failed to setup trigger: %d\n", ret);
+                       return ret;
+               }
+       }
+
+       ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, scd30_trigger_handler, NULL);
+       if (ret)
+               return ret;
+
+       ret = scd30_command_read(state, CMD_FW_VERSION, &val);
+       if (ret) {
+               dev_err(dev, "failed to read firmware version: %d\n", ret);
+               return ret;
+       }
+       dev_info(dev, "firmware version: %d.%d\n", val >> 8, (char)val);
+
+       ret = scd30_command_write(state, CMD_MEAS_INTERVAL, state->meas_interval);
+       if (ret) {
+               dev_err(dev, "failed to set measurement interval: %d\n", ret);
+               return ret;
+       }
+
+       ret = scd30_command_write(state, CMD_START_MEAS, state->pressure_comp);
+       if (ret) {
+               dev_err(dev, "failed to start measurement: %d\n", ret);
+               return ret;
+       }
+
+       ret = devm_add_action_or_reset(dev, scd30_stop_meas, state);
+       if (ret)
+               return ret;
+
+       return devm_iio_device_register(dev, indio_dev);
+}
+EXPORT_SYMBOL(scd30_probe);
+
+MODULE_AUTHOR("Tomasz Duszynski <tomasz.duszynski@octakon.com>");
+MODULE_DESCRIPTION("Sensirion SCD30 carbon dioxide sensor core driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/chemical/scd30_i2c.c b/drivers/iio/chemical/scd30_i2c.c
new file mode 100644 (file)
index 0000000..875892a
--- /dev/null
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Sensirion SCD30 carbon dioxide sensor i2c driver
+ *
+ * Copyright (c) 2020 Tomasz Duszynski <tomasz.duszynski@octakon.com>
+ *
+ * I2C slave address: 0x61
+ */
+#include <linux/crc8.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <asm/unaligned.h>
+
+#include "scd30.h"
+
+#define SCD30_I2C_MAX_BUF_SIZE 18
+#define SCD30_I2C_CRC8_POLYNOMIAL 0x31
+
+static u16 scd30_i2c_cmd_lookup_tbl[] = {
+       [CMD_START_MEAS] = 0x0010,
+       [CMD_STOP_MEAS] = 0x0104,
+       [CMD_MEAS_INTERVAL] = 0x4600,
+       [CMD_MEAS_READY] = 0x0202,
+       [CMD_READ_MEAS] = 0x0300,
+       [CMD_ASC] = 0x5306,
+       [CMD_FRC] = 0x5204,
+       [CMD_TEMP_OFFSET] = 0x5403,
+       [CMD_FW_VERSION] = 0xd100,
+       [CMD_RESET] = 0xd304,
+};
+
+DECLARE_CRC8_TABLE(scd30_i2c_crc8_tbl);
+
+static int scd30_i2c_xfer(struct scd30_state *state, char *txbuf, int txsize,
+                         char *rxbuf, int rxsize)
+{
+       struct i2c_client *client = to_i2c_client(state->dev);
+       int ret;
+
+       /*
+        * repeated start is not supported hence instead of sending two i2c
+        * messages in a row we send one by one
+        */
+       ret = i2c_master_send(client, txbuf, txsize);
+       if (ret < 0)
+               return ret;
+       if (ret != txsize)
+               return -EIO;
+
+       if (!rxbuf)
+               return 0;
+
+       ret = i2c_master_recv(client, rxbuf, rxsize);
+       if (ret < 0)
+               return ret;
+       if (ret != rxsize)
+               return -EIO;
+
+       return 0;
+}
+
+static int scd30_i2c_command(struct scd30_state *state, enum scd30_cmd cmd, u16 arg,
+                            void *response, int size)
+{
+       char buf[SCD30_I2C_MAX_BUF_SIZE];
+       char *rsp = response;
+       int i, ret;
+       char crc;
+
+       put_unaligned_be16(scd30_i2c_cmd_lookup_tbl[cmd], buf);
+       i = 2;
+
+       if (rsp) {
+               /* each two bytes are followed by a crc8 */
+               size += size / 2;
+       } else {
+               put_unaligned_be16(arg, buf + i);
+               crc = crc8(scd30_i2c_crc8_tbl, buf + i, 2, CRC8_INIT_VALUE);
+               i += 2;
+               buf[i] = crc;
+               i += 1;
+
+               /* commands below don't take an argument */
+               if ((cmd == CMD_STOP_MEAS) || (cmd == CMD_RESET))
+                       i -= 3;
+       }
+
+       ret = scd30_i2c_xfer(state, buf, i, buf, size);
+       if (ret)
+               return ret;
+
+       /* validate received data and strip off crc bytes */
+       for (i = 0; i < size; i += 3) {
+               crc = crc8(scd30_i2c_crc8_tbl, buf + i, 2, CRC8_INIT_VALUE);
+               if (crc != buf[i + 2]) {
+                       dev_err(state->dev, "data integrity check failed\n");
+                       return -EIO;
+               }
+
+               *rsp++ = buf[i];
+               *rsp++ = buf[i + 1];
+       }
+
+       return 0;
+}
+
+static int scd30_i2c_probe(struct i2c_client *client)
+{
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+               return -EOPNOTSUPP;
+
+       crc8_populate_msb(scd30_i2c_crc8_tbl, SCD30_I2C_CRC8_POLYNOMIAL);
+
+       return scd30_probe(&client->dev, client->irq, client->name, NULL, scd30_i2c_command);
+}
+
+static const struct of_device_id scd30_i2c_of_match[] = {
+       { .compatible = "sensirion,scd30" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, scd30_i2c_of_match);
+
+static struct i2c_driver scd30_i2c_driver = {
+       .driver = {
+               .name = KBUILD_MODNAME,
+               .of_match_table = scd30_i2c_of_match,
+               .pm = &scd30_pm_ops,
+       },
+       .probe_new = scd30_i2c_probe,
+};
+module_i2c_driver(scd30_i2c_driver);
+
+MODULE_AUTHOR("Tomasz Duszynski <tomasz.duszynski@octakon.com>");
+MODULE_DESCRIPTION("Sensirion SCD30 carbon dioxide sensor i2c driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/chemical/scd30_serial.c b/drivers/iio/chemical/scd30_serial.c
new file mode 100644 (file)
index 0000000..06f85eb
--- /dev/null
@@ -0,0 +1,263 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Sensirion SCD30 carbon dioxide sensor serial driver
+ *
+ * Copyright (c) 2020 Tomasz Duszynski <tomasz.duszynski@octakon.com>
+ */
+#include <linux/crc16.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/iio/iio.h>
+#include <linux/jiffies.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/serdev.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <asm/unaligned.h>
+
+#include "scd30.h"
+
+#define SCD30_SERDEV_ADDR 0x61
+#define SCD30_SERDEV_WRITE 0x06
+#define SCD30_SERDEV_READ 0x03
+#define SCD30_SERDEV_MAX_BUF_SIZE 17
+#define SCD30_SERDEV_RX_HEADER_SIZE 3
+#define SCD30_SERDEV_CRC_SIZE 2
+#define SCD30_SERDEV_TIMEOUT msecs_to_jiffies(200)
+
+struct scd30_serdev_priv {
+       struct completion meas_ready;
+       char *buf;
+       int num_expected;
+       int num;
+};
+
+static u16 scd30_serdev_cmd_lookup_tbl[] = {
+       [CMD_START_MEAS] = 0x0036,
+       [CMD_STOP_MEAS] = 0x0037,
+       [CMD_MEAS_INTERVAL] = 0x0025,
+       [CMD_MEAS_READY] = 0x0027,
+       [CMD_READ_MEAS] = 0x0028,
+       [CMD_ASC] = 0x003a,
+       [CMD_FRC] = 0x0039,
+       [CMD_TEMP_OFFSET] = 0x003b,
+       [CMD_FW_VERSION] = 0x0020,
+       [CMD_RESET] = 0x0034,
+};
+
+static u16 scd30_serdev_calc_crc(const char *buf, int size)
+{
+       return crc16(0xffff, buf, size);
+}
+
+static int scd30_serdev_xfer(struct scd30_state *state, char *txbuf, int txsize,
+                            char *rxbuf, int rxsize)
+{
+       struct serdev_device *serdev = to_serdev_device(state->dev);
+       struct scd30_serdev_priv *priv = state->priv;
+       int ret;
+
+       priv->buf = rxbuf;
+       priv->num_expected = rxsize;
+       priv->num = 0;
+
+       ret = serdev_device_write(serdev, txbuf, txsize, SCD30_SERDEV_TIMEOUT);
+       if (ret < 0)
+               return ret;
+       if (ret != txsize)
+               return -EIO;
+
+       ret = wait_for_completion_interruptible_timeout(&priv->meas_ready, SCD30_SERDEV_TIMEOUT);
+       if (ret < 0)
+               return ret;
+       if (!ret)
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+static int scd30_serdev_command(struct scd30_state *state, enum scd30_cmd cmd, u16 arg,
+                               void *response, int size)
+{
+       /*
+        * Communication over serial line is based on modbus protocol (or rather
+        * its variation called modbus over serial to be precise). Upon
+        * receiving a request device should reply with response.
+        *
+        * Frame below represents a request message. Each field takes
+        * exactly one byte.
+        *
+        * +------+------+-----+-----+-------+-------+-----+-----+
+        * | dev  | op   | reg | reg | byte1 | byte0 | crc | crc |
+        * | addr | code | msb | lsb |       |       | lsb | msb |
+        * +------+------+-----+-----+-------+-------+-----+-----+
+        *
+        * The message device replies with depends on the 'op code' field from
+        * the request. In case it was set to SCD30_SERDEV_WRITE sensor should
+        * reply with unchanged request. Otherwise 'op code' was set to
+        * SCD30_SERDEV_READ and response looks like the one below. As with
+        * request, each field takes one byte.
+        *
+        * +------+------+--------+-------+-----+-------+-----+-----+
+        * | dev  | op   | num of | byte0 | ... | byteN | crc | crc |
+        * | addr | code | bytes  |       |     |       | lsb | msb |
+        * +------+------+--------+-------+-----+-------+-----+-----+
+        */
+       char txbuf[SCD30_SERDEV_MAX_BUF_SIZE] = { SCD30_SERDEV_ADDR },
+            rxbuf[SCD30_SERDEV_MAX_BUF_SIZE];
+       int ret, rxsize, txsize = 2;
+       char *rsp = response;
+       u16 crc;
+
+       put_unaligned_be16(scd30_serdev_cmd_lookup_tbl[cmd], txbuf + txsize);
+       txsize += 2;
+
+       if (rsp) {
+               txbuf[1] = SCD30_SERDEV_READ;
+               if (cmd == CMD_READ_MEAS)
+                       /* number of u16 words to read */
+                       put_unaligned_be16(size / 2, txbuf + txsize);
+               else
+                       put_unaligned_be16(0x0001, txbuf + txsize);
+               txsize += 2;
+               crc = scd30_serdev_calc_crc(txbuf, txsize);
+               put_unaligned_le16(crc, txbuf + txsize);
+               txsize += 2;
+               rxsize = SCD30_SERDEV_RX_HEADER_SIZE + size + SCD30_SERDEV_CRC_SIZE;
+       } else {
+               if ((cmd == CMD_STOP_MEAS) || (cmd == CMD_RESET))
+                       arg = 0x0001;
+
+               txbuf[1] = SCD30_SERDEV_WRITE;
+               put_unaligned_be16(arg, txbuf + txsize);
+               txsize += 2;
+               crc = scd30_serdev_calc_crc(txbuf, txsize);
+               put_unaligned_le16(crc, txbuf + txsize);
+               txsize += 2;
+               rxsize = txsize;
+       }
+
+       ret = scd30_serdev_xfer(state, txbuf, txsize, rxbuf, rxsize);
+       if (ret)
+               return ret;
+
+       switch (txbuf[1]) {
+       case SCD30_SERDEV_WRITE:
+               if (memcmp(txbuf, rxbuf, txsize)) {
+                       dev_err(state->dev, "wrong message received\n");
+                       return -EIO;
+               }
+               break;
+       case SCD30_SERDEV_READ:
+               if (rxbuf[2] != (rxsize - SCD30_SERDEV_RX_HEADER_SIZE - SCD30_SERDEV_CRC_SIZE)) {
+                       dev_err(state->dev, "received data size does not match header\n");
+                       return -EIO;
+               }
+
+               rxsize -= SCD30_SERDEV_CRC_SIZE;
+               crc = get_unaligned_le16(rxbuf + rxsize);
+               if (crc != scd30_serdev_calc_crc(rxbuf, rxsize)) {
+                       dev_err(state->dev, "data integrity check failed\n");
+                       return -EIO;
+               }
+
+               rxsize -= SCD30_SERDEV_RX_HEADER_SIZE;
+               memcpy(rsp, rxbuf + SCD30_SERDEV_RX_HEADER_SIZE, rxsize);
+               break;
+       default:
+               dev_err(state->dev, "received unknown op code\n");
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int scd30_serdev_receive_buf(struct serdev_device *serdev,
+                                   const unsigned char *buf, size_t size)
+{
+       struct iio_dev *indio_dev = dev_get_drvdata(&serdev->dev);
+       struct scd30_serdev_priv *priv;
+       struct scd30_state *state;
+       int num;
+
+       if (!indio_dev)
+               return 0;
+
+       state = iio_priv(indio_dev);
+       priv = state->priv;
+
+       /* just in case sensor puts some unexpected bytes on the bus */
+       if (!priv->buf)
+               return 0;
+
+       if (priv->num + size >= priv->num_expected)
+               num = priv->num_expected - priv->num;
+       else
+               num = size;
+
+       memcpy(priv->buf + priv->num, buf, num);
+       priv->num += num;
+
+       if (priv->num == priv->num_expected) {
+               priv->buf = NULL;
+               complete(&priv->meas_ready);
+       }
+
+       return num;
+}
+
+static const struct serdev_device_ops scd30_serdev_ops = {
+       .receive_buf = scd30_serdev_receive_buf,
+       .write_wakeup = serdev_device_write_wakeup,
+};
+
+static int scd30_serdev_probe(struct serdev_device *serdev)
+{
+       struct device *dev = &serdev->dev;
+       struct scd30_serdev_priv *priv;
+       int irq, ret;
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       init_completion(&priv->meas_ready);
+       serdev_device_set_client_ops(serdev, &scd30_serdev_ops);
+
+       ret = devm_serdev_device_open(dev, serdev);
+       if (ret)
+               return ret;
+
+       serdev_device_set_baudrate(serdev, 19200);
+       serdev_device_set_flow_control(serdev, false);
+
+       ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE);
+       if (ret)
+               return ret;
+
+       irq = fwnode_irq_get(dev_fwnode(dev), 0);
+
+       return scd30_probe(dev, irq, KBUILD_MODNAME, priv, scd30_serdev_command);
+}
+
+static const struct of_device_id scd30_serdev_of_match[] = {
+       { .compatible = "sensirion,scd30" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, scd30_serdev_of_match);
+
+static struct serdev_device_driver scd30_serdev_driver = {
+       .driver = {
+               .name = KBUILD_MODNAME,
+               .of_match_table = scd30_serdev_of_match,
+               .pm = &scd30_pm_ops,
+       },
+       .probe = scd30_serdev_probe,
+};
+module_serdev_device_driver(scd30_serdev_driver);
+
+MODULE_AUTHOR("Tomasz Duszynski <tomasz.duszynski@octakon.com>");
+MODULE_DESCRIPTION("Sensirion SCD30 carbon dioxide sensor serial driver");
+MODULE_LICENSE("GPL v2");
index 403e880..2c4086c 100644 (file)
@@ -533,7 +533,6 @@ static int sgp_probe(struct i2c_client *client,
        if (ret)
                return ret;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &sgp_info;
        indio_dev->name = id->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
index a88c1fb..5a29e32 100644 (file)
@@ -487,7 +487,6 @@ static int sps30_probe(struct i2c_client *client)
        i2c_set_clientdata(client, indio_dev);
        state->client = client;
        state->state = RESET;
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &sps30_info;
        indio_dev->name = client->name;
        indio_dev->channels = sps30_channels;
index 415b393..5586eb8 100644 (file)
@@ -382,7 +382,6 @@ static int vz89x_probe(struct i2c_client *client,
        data->last_update = jiffies - HZ;
        mutex_init(&data->lock);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &vz89x_info;
        indio_dev->name = dev_name(&client->dev);
        indio_dev->modes = INDIO_DIRECT_MODE;
index a66941f..130ab8c 100644 (file)
@@ -200,6 +200,10 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev,
                st->core.param.sensor_range.roundup = 1;
 
                ret = cros_ec_motion_send_host_cmd(&st->core, 0);
+               if (ret == 0) {
+                       st->core.range_updated = true;
+                       st->core.curr_range = val;
+               }
                break;
        default:
                ret = cros_ec_sensors_core_write(
@@ -315,6 +319,7 @@ MODULE_DEVICE_TABLE(platform, cros_ec_sensors_ids);
 static struct platform_driver cros_ec_sensors_platform_driver = {
        .driver = {
                .name   = "cros-ec-sensors",
+               .pm     = &cros_ec_sensors_pm_ops,
        },
        .probe          = cros_ec_sensors_probe,
        .id_table       = cros_ec_sensors_ids,
index c831915..ea480c1 100644 (file)
@@ -281,7 +281,6 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
        state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
        state->msg->outsize = sizeof(struct ec_params_motion_sense);
 
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->name = pdev->name;
 
        if (physical_device) {
@@ -352,7 +351,7 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
                } else {
                        /*
                         * The only way to get samples in buffer is to set a
-                        * software tigger (systrig, hrtimer).
+                        * software trigger (systrig, hrtimer).
                         */
                        ret = devm_iio_triggered_buffer_setup(
                                        dev, indio_dev, NULL, trigger_capture,
@@ -824,5 +823,26 @@ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st,
 }
 EXPORT_SYMBOL_GPL(cros_ec_sensors_core_write);
 
+static int __maybe_unused cros_ec_sensors_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+       struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+       int ret = 0;
+
+       if (st->range_updated) {
+               mutex_lock(&st->cmd_lock);
+               st->param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
+               st->param.sensor_range.data = st->curr_range;
+               st->param.sensor_range.roundup = 1;
+               ret = cros_ec_motion_send_host_cmd(st, 0);
+               mutex_unlock(&st->cmd_lock);
+       }
+       return ret;
+}
+
+SIMPLE_DEV_PM_OPS(cros_ec_sensors_pm_ops, NULL, cros_ec_sensors_resume);
+EXPORT_SYMBOL_GPL(cros_ec_sensors_pm_ops);
+
 MODULE_DESCRIPTION("ChromeOS EC sensor hub core functions");
 MODULE_LICENSE("GPL v2");
index b400560..b9e59ad 100644 (file)
@@ -56,7 +56,6 @@ int st_sensors_i2c_configure(struct iio_dev *indio_dev,
 
        i2c_set_clientdata(client, indio_dev);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->name = client->name;
 
        sdata->dev = &client->dev;
index ee70515..48fc41d 100644 (file)
@@ -108,7 +108,6 @@ int st_sensors_spi_configure(struct iio_dev *indio_dev,
 
        spi_set_drvdata(spi, indio_dev);
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = spi->modalias;
 
        sdata->dev = &spi->dev;
index d33642d..db36365 100644 (file)
@@ -874,7 +874,6 @@ static int ad5064_probe(struct device *dev, enum ad5064_type type,
                        return ret;
        }
 
-       indio_dev->dev.parent = dev;
        indio_dev->name = name;
        indio_dev->info = &ad5064_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 3e0c9e8..f5d19d1 100644 (file)
@@ -476,7 +476,6 @@ static int ad5360_probe(struct spi_device *spi)
        st->chip_info = &ad5360_chip_info_tbl[type];
        st->spi = spi;
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->info = &ad5360_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index b37e567..224ffc4 100644 (file)
@@ -240,7 +240,7 @@ static const struct iio_info ad5380_info = {
        .write_raw = ad5380_write_raw,
 };
 
-static struct iio_chan_spec_ext_info ad5380_ext_info[] = {
+static const struct iio_chan_spec_ext_info ad5380_ext_info[] = {
        {
                .name = "powerdown",
                .read = ad5380_read_dac_powerdown,
@@ -386,7 +386,6 @@ static int ad5380_probe(struct device *dev, struct regmap *regmap,
        st->chip_info = &ad5380_chip_info_tbl[type];
        st->regmap = regmap;
 
-       indio_dev->dev.parent = dev;
        indio_dev->name = name;
        indio_dev->info = &ad5380_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index fec2776..4158c81 100644 (file)
@@ -487,7 +487,6 @@ static int ad5421_probe(struct spi_device *spi)
 
        st->spi = spi;
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = "ad5421";
        indio_dev->info = &ad5421_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 8f8afc8..5931bd6 100644 (file)
@@ -250,8 +250,6 @@ static int ad5446_probe(struct device *dev, const char *name,
        st->reg = reg;
        st->dev = dev;
 
-       /* Establish that the iio_dev is a child of the device */
-       indio_dev->dev.parent = dev;
        indio_dev->name = name;
        indio_dev->info = &ad5446_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index d739b10..447ba9f 100644 (file)
@@ -297,7 +297,6 @@ static int ad5449_spi_probe(struct spi_device *spi)
        if (ret)
                return ret;
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = id->name;
        indio_dev->info = &ad5449_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index c64e689..6f18ac2 100644 (file)
@@ -304,7 +304,6 @@ static int ad5504_probe(struct spi_device *spi)
 
        st->reg = reg;
        st->spi = spi;
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = spi_get_device_id(st->spi)->name;
        indio_dev->info = &ad5504_info;
        if (spi_get_device_id(st->spi)->driver_data == ID_AD5501)
index 410e90e..5c4e5ff 100644 (file)
@@ -484,7 +484,7 @@ static ssize_t ad5592r_show_scale_available(struct iio_dev *iio_dev,
                st->scale_avail[1][0], st->scale_avail[1][1]);
 }
 
-static struct iio_chan_spec_ext_info ad5592r_ext_info[] = {
+static const struct iio_chan_spec_ext_info ad5592r_ext_info[] = {
        {
         .name = "scale_available",
         .read = ad5592r_show_scale_available,
@@ -508,11 +508,11 @@ static void ad5592r_setup_channel(struct iio_dev *iio_dev,
        chan->ext_info = ad5592r_ext_info;
 }
 
-static int ad5592r_alloc_channels(struct ad5592r_state *st)
+static int ad5592r_alloc_channels(struct iio_dev *iio_dev)
 {
+       struct ad5592r_state *st = iio_priv(iio_dev);
        unsigned i, curr_channel = 0,
                 num_channels = st->num_channels;
-       struct iio_dev *iio_dev = iio_priv_to_dev(st);
        struct iio_chan_spec *channels;
        struct fwnode_handle *child;
        u32 reg, tmp;
@@ -618,7 +618,6 @@ int ad5592r_probe(struct device *dev, const char *name,
                        return ret;
        }
 
-       iio_dev->dev.parent = dev;
        iio_dev->name = name;
        iio_dev->info = &ad5592r_info;
        iio_dev->modes = INDIO_DIRECT_MODE;
@@ -636,7 +635,7 @@ int ad5592r_probe(struct device *dev, const char *name,
        if (ret)
                goto error_disable_reg;
 
-       ret = ad5592r_alloc_channels(st);
+       ret = ad5592r_alloc_channels(iio_dev);
        if (ret)
                goto error_disable_reg;
 
index 2015a5d..2b2b8ed 100644 (file)
@@ -253,7 +253,6 @@ static int ad5624r_probe(struct spi_device *spi)
 
        st->us = spi;
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->info = &ad5624r_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 8dd67da..56cf934 100644 (file)
@@ -461,7 +461,6 @@ int ad5686_probe(struct device *dev,
        for (i = 0; i < st->chip_info->num_channels; i++)
                st->pwr_down_mode |= (0x01 << (i * 2));
 
-       indio_dev->dev.parent = dev;
        indio_dev->name = name;
        indio_dev->info = &ad5686_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 7723bd3..c8d9c69 100644 (file)
@@ -744,7 +744,6 @@ static int ad5755_probe(struct spi_device *spi)
        st->spi = spi;
        st->pwr_down = 0xf;
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->info = &ad5755_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 475646c..8664914 100644 (file)
@@ -854,7 +854,6 @@ static int ad5758_probe(struct spi_device *spi)
 
        mutex_init(&st->lock);
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->info = &ad5758_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 67c4fa7..89fa586 100644 (file)
@@ -376,7 +376,6 @@ static int ad5761_probe(struct spi_device *spi)
        if (ret)
                goto disable_regulator_err;
 
-       iio_dev->dev.parent = &spi->dev;
        iio_dev->info = &ad5761_info;
        iio_dev->modes = INDIO_DIRECT_MODE;
        iio_dev->channels = &chip_info->channel;
index 5b0f0fe..53e756e 100644 (file)
@@ -290,7 +290,6 @@ static int ad5764_probe(struct spi_device *spi)
        st->spi = spi;
        st->chip_info = &ad5764_chip_infos[type];
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->info = &ad5764_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 2d7623b..84dcf14 100644 (file)
@@ -651,7 +651,6 @@ static int ad5770r_probe(struct spi_device *spi)
                }
        }
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->info = &ad5770r_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 1d11f39..60aa161 100644 (file)
@@ -409,7 +409,6 @@ static int ad5791_probe(struct spi_device *spi)
                goto error_disable_reg_neg;
 
        spi_set_drvdata(spi, indio_dev);
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &ad5791_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels
index 15af8a1..4460aa5 100644 (file)
@@ -238,7 +238,6 @@ static int ad7303_probe(struct spi_device *spi)
                st->config |= AD7303_CFG_EXTERNAL_VREF;
        }
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = id->name;
        indio_dev->info = &ad7303_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 0789c91..6354b7c 100644 (file)
@@ -171,7 +171,6 @@ static int ad8801_probe(struct spi_device *spi)
        }
 
        spi_set_drvdata(spi, indio_dev);
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &ad8801_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = ad8801_channels;
index 8167779..9581356 100644 (file)
@@ -110,7 +110,6 @@ static int cio_dac_probe(struct device *dev, unsigned int id)
        indio_dev->channels = cio_dac_channels;
        indio_dev->num_channels = CIO_DAC_NUM_CHAN;
        indio_dev->name = dev_name(dev);
-       indio_dev->dev.parent = dev;
 
        priv = iio_priv(indio_dev);
        priv->base = base[id];
index 4a6111b..b3835fb 100644 (file)
@@ -177,7 +177,6 @@ static int dpot_dac_probe(struct platform_device *pdev)
        dac = iio_priv(indio_dev);
 
        indio_dev->name = dev_name(dev);
-       indio_dev->dev.parent = dev;
        indio_dev->info = &dpot_dac_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = &dpot_dac_iio_channel;
index 26d2066..79527fb 100644 (file)
@@ -230,8 +230,6 @@ static int ds4424_probe(struct i2c_client *client,
        i2c_set_clientdata(client, indio_dev);
        data->client = client;
        indio_dev->name = id->name;
-       indio_dev->dev.of_node = client->dev.of_node;
-       indio_dev->dev.parent = &client->dev;
 
        data->vcc_reg = devm_regulator_get(&client->dev, "vcc");
        if (IS_ERR(data->vcc_reg)) {
index 0ab357b..9e38607 100644 (file)
@@ -133,7 +133,6 @@ static int lpc18xx_dac_probe(struct platform_device *pdev)
        }
 
        indio_dev->name = dev_name(&pdev->dev);
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->info = &lpc18xx_dac_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = lpc18xx_dac_iio_channels;
index 1086683..dc10188 100644 (file)
@@ -186,7 +186,6 @@ static int ltc1660_probe(struct spi_device *spi)
 
        priv->spi = spi;
        spi_set_drvdata(spi, indio_dev);
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &ltc1660_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = ltc1660_channels[id->driver_data];
index f891311..06bfaaa 100644 (file)
@@ -362,7 +362,6 @@ static int ltc2632_probe(struct spi_device *spi)
                }
        }
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = dev_of_node(&spi->dev) ? dev_of_node(&spi->dev)->name
                                                 : spi_get_device_id(spi)->name;
        indio_dev->info = &ltc2632_info;
index 3205ca9..225b1a3 100644 (file)
@@ -204,9 +204,6 @@ static int m62332_probe(struct i2c_client *client,
        if (IS_ERR(data->vcc))
                return PTR_ERR(data->vcc);
 
-       /* establish that the iio_dev is a child of the i2c device */
-       indio_dev->dev.parent = &client->dev;
-
        indio_dev->num_channels = ARRAY_SIZE(m62332_channels);
        indio_dev->channels = m62332_channels;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 7e01838..daa6038 100644 (file)
@@ -156,9 +156,6 @@ static int max517_probe(struct i2c_client *client,
        i2c_set_clientdata(client, indio_dev);
        data->client = client;
 
-       /* establish that the iio_dev is a child of the i2c device */
-       indio_dev->dev.parent = &client->dev;
-
        switch (id->driver_data) {
        case ID_MAX521:
                indio_dev->num_channels = 8;
index 2da086e..d6bb24d 100644 (file)
@@ -341,7 +341,6 @@ static int max5821_probe(struct i2c_client *client,
        data->vref_mv = ret / 1000;
 
        indio_dev->name = id->name;
-       indio_dev->dev.parent = &client->dev;
        indio_dev->num_channels = ARRAY_SIZE(max5821_channels);
        indio_dev->channels = max5821_channels;
        indio_dev->modes = INDIO_DIRECT_MODE;
index ed455e8..ee174d2 100644 (file)
@@ -453,7 +453,6 @@ static int mcp4725_probe(struct i2c_client *client,
                        goto err_disable_vdd_reg;
        }
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->name = id->name;
        indio_dev->info = &mcp4725_info;
        indio_dev->channels = &mcp472x_channel[id->driver_data];
index f9194b3..c4e430b 100644 (file)
@@ -152,7 +152,6 @@ static int mcp4922_probe(struct spi_device *spi)
 
        spi_set_drvdata(spi, indio_dev);
        id = spi_get_device_id(spi);
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &mcp4922_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = mcp4922_channels[id->driver_data];
index f22c1d9..092c796 100644 (file)
@@ -323,7 +323,6 @@ static int stm32_dac_probe(struct platform_device *pdev)
        dac = iio_priv(indio_dev);
        dac->common = dev_get_drvdata(pdev->dev.parent);
        indio_dev->name = dev_name(&pdev->dev);
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->dev.of_node = pdev->dev.of_node;
        indio_dev->info = &stm32_dac_iio_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 57b498d..86bfb1c 100644 (file)
@@ -4,12 +4,12 @@
  *
  * Copyright (C) 2017 KUNBUS GmbH
  *
- * http://www.ti.com/lit/ds/symlink/dac082s085.pdf
- * http://www.ti.com/lit/ds/symlink/dac102s085.pdf
- * http://www.ti.com/lit/ds/symlink/dac122s085.pdf
- * http://www.ti.com/lit/ds/symlink/dac084s085.pdf
- * http://www.ti.com/lit/ds/symlink/dac104s085.pdf
- * http://www.ti.com/lit/ds/symlink/dac124s085.pdf
+ * https://www.ti.com/lit/ds/symlink/dac082s085.pdf
+ * https://www.ti.com/lit/ds/symlink/dac102s085.pdf
+ * https://www.ti.com/lit/ds/symlink/dac122s085.pdf
+ * https://www.ti.com/lit/ds/symlink/dac084s085.pdf
+ * https://www.ti.com/lit/ds/symlink/dac104s085.pdf
+ * https://www.ti.com/lit/ds/symlink/dac124s085.pdf
  */
 
 #include <linux/iio/iio.h>
@@ -268,7 +268,6 @@ static int ti_dac_probe(struct spi_device *spi)
        if (!indio_dev)
                return -ENOMEM;
 
-       indio_dev->dev.parent = dev;
        indio_dev->info = &ti_dac_info;
        indio_dev->name = spi->modalias;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 3a2bb0e..00fc7db 100644 (file)
@@ -4,15 +4,15 @@
  *
  * Copyright (C) 2018 Prevas A/S
  *
- * http://www.ti.com/lit/ds/symlink/dac5571.pdf
- * http://www.ti.com/lit/ds/symlink/dac6571.pdf
- * http://www.ti.com/lit/ds/symlink/dac7571.pdf
- * http://www.ti.com/lit/ds/symlink/dac5574.pdf
- * http://www.ti.com/lit/ds/symlink/dac6574.pdf
- * http://www.ti.com/lit/ds/symlink/dac7574.pdf
- * http://www.ti.com/lit/ds/symlink/dac5573.pdf
- * http://www.ti.com/lit/ds/symlink/dac6573.pdf
- * http://www.ti.com/lit/ds/symlink/dac7573.pdf
+ * https://www.ti.com/lit/ds/symlink/dac5571.pdf
+ * https://www.ti.com/lit/ds/symlink/dac6571.pdf
+ * https://www.ti.com/lit/ds/symlink/dac7571.pdf
+ * https://www.ti.com/lit/ds/symlink/dac5574.pdf
+ * https://www.ti.com/lit/ds/symlink/dac6574.pdf
+ * https://www.ti.com/lit/ds/symlink/dac7574.pdf
+ * https://www.ti.com/lit/ds/symlink/dac5573.pdf
+ * https://www.ti.com/lit/ds/symlink/dac6573.pdf
+ * https://www.ti.com/lit/ds/symlink/dac7573.pdf
  */
 
 #include <linux/iio/iio.h>
@@ -321,8 +321,6 @@ static int dac5571_probe(struct i2c_client *client,
        i2c_set_clientdata(client, indio_dev);
        data->client = client;
 
-       indio_dev->dev.parent = dev;
-       indio_dev->dev.of_node = client->dev.of_node;
        indio_dev->info = &dac5571_info;
        indio_dev->name = id->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 6f5df1a..63171e4 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2018 CMC NV
  *
- * http://www.ti.com/lit/ds/symlink/dac7311.pdf
+ * https://www.ti.com/lit/ds/symlink/dac7311.pdf
  */
 
 #include <linux/iio/iio.h>
@@ -251,8 +251,6 @@ static int ti_dac_probe(struct spi_device *spi)
        spi->bits_per_word = 16;
        spi_setup(spi);
 
-       indio_dev->dev.parent = dev;
-       indio_dev->dev.of_node = spi->dev.of_node;
        indio_dev->info = &ti_dac_info;
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
index de0c657..07c9f39 100644 (file)
@@ -139,7 +139,6 @@ static int dac7612_probe(struct spi_device *spi)
                return PTR_ERR(priv->loaddacs);
        priv->spi = spi;
        spi_set_drvdata(spi, iio_dev);
-       iio_dev->dev.parent = &spi->dev;
        iio_dev->info = &dac7612_info;
        iio_dev->modes = INDIO_DIRECT_MODE;
        iio_dev->channels = dac7612_channels;
index 9417a4a..636b400 100644 (file)
@@ -199,8 +199,6 @@ static int vf610_dac_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, indio_dev);
 
        indio_dev->name = dev_name(&pdev->dev);
-       indio_dev->dev.parent = &pdev->dev;
-       indio_dev->dev.of_node = pdev->dev.of_node;
        indio_dev->info = &vf610_dac_iio_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = vf610_dac_iio_channels;
index 6cb0229..b35ae7c 100644 (file)
@@ -566,6 +566,13 @@ static struct iio_sw_device *iio_dummy_probe(const char *name)
        struct iio_dev *indio_dev;
        struct iio_dummy_state *st;
        struct iio_sw_device *swd;
+       struct device *parent = NULL;
+
+       /*
+        * With hardware: Set the parent device.
+        * parent = &spi->dev;
+        * parent = &client->dev;
+        */
 
        swd = kzalloc(sizeof(*swd), GFP_KERNEL);
        if (!swd) {
@@ -580,7 +587,7 @@ static struct iio_sw_device *iio_dummy_probe(const char *name)
         * It also has a region (accessed by iio_priv()
         * for chip specific state information.
         */
-       indio_dev = iio_device_alloc(sizeof(*st));
+       indio_dev = iio_device_alloc(parent, sizeof(*st));
        if (!indio_dev) {
                ret = -ENOMEM;
                goto error_ret;
@@ -590,11 +597,6 @@ static struct iio_sw_device *iio_dummy_probe(const char *name)
        mutex_init(&st->lock);
 
        iio_dummy_init_device(indio_dev);
-       /*
-        * With hardware: Set the parent device.
-        * indio_dev->dev.parent = &spi->dev;
-        * indio_dev->dev.parent = &client->dev;
-        */
 
         /*
         * Make the iio_dev struct available to remove function.
index 17606ec..8e13c53 100644 (file)
@@ -99,20 +99,6 @@ done:
 }
 
 static const struct iio_buffer_setup_ops iio_simple_dummy_buffer_setup_ops = {
-       /*
-        * iio_triggered_buffer_postenable:
-        * Generic function that simply attaches the pollfunc to the trigger.
-        * Replace this to mess with hardware state before we attach the
-        * trigger.
-        */
-       .postenable = &iio_triggered_buffer_postenable,
-       /*
-        * iio_triggered_buffer_predisable:
-        * Generic function that simple detaches the pollfunc from the trigger.
-        * Replace this to put hardware state back again after the trigger is
-        * detached but before userspace knows we have disabled the ring.
-        */
-       .predisable = &iio_triggered_buffer_predisable,
 };
 
 int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev)
index a732218..334e1d7 100644 (file)
@@ -1026,7 +1026,6 @@ static int ad9523_probe(struct spi_device *spi)
        st->spi = spi;
        st->pdata = pdata;
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = (pdata->name[0] != 0) ? pdata->name :
                          spi_get_device_id(spi)->name;
        indio_dev->info = &ad9523_info;
index 1c2dc9b..409c9c4 100644 (file)
@@ -531,7 +531,6 @@ static int adf4350_probe(struct spi_device *spi)
        st->spi = spi;
        st->pdata = pdata;
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = (pdata->name[0] != 0) ? pdata->name :
                spi_get_device_id(spi)->name;
 
index ff82863..ecd5e18 100644 (file)
@@ -573,7 +573,6 @@ static int adf4371_probe(struct spi_device *spi)
        mutex_init(&st->lock);
 
        st->chip_info = &adf4371_chip_info[id->driver_data];
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = id->name;
        indio_dev->info = &adf4371_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 1b84b8e..6e5e2d9 100644 (file)
@@ -207,7 +207,6 @@ static int adis16080_probe(struct spi_device *spi)
        indio_dev->name = spi->dev.driver->name;
        indio_dev->channels = adis16080_channels;
        indio_dev->num_channels = ARRAY_SIZE(adis16080_channels);
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &adis16080_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
index 2a9ec08..b9c952e 100644 (file)
@@ -155,7 +155,6 @@ static int adis16130_probe(struct spi_device *spi)
        indio_dev->name = spi->dev.driver->name;
        indio_dev->channels = adis16130_channels;
        indio_dev->num_channels = ARRAY_SIZE(adis16130_channels);
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &adis16130_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
index afdc57a..d8a96f6 100644 (file)
@@ -540,7 +540,6 @@ static int adis16136_probe(struct spi_device *spi)
        adis16136 = iio_priv(indio_dev);
 
        adis16136->chip_info = &adis16136_chip_info[id->driver_data];
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->channels = adis16136_channels;
        indio_dev->num_channels = ARRAY_SIZE(adis16136_channels);
index 9823573..e638d56 100644 (file)
@@ -381,7 +381,6 @@ static int adis16260_probe(struct spi_device *spi)
        adis16260->info = &adis16260_chip_info_table[id->driver_data];
 
        indio_dev->name = id->name;
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &adis16260_info;
        indio_dev->channels = adis16260->info->channels;
        indio_dev->num_channels = adis16260->info->num_channels;
index b00c0eb..04f3500 100644 (file)
@@ -424,7 +424,6 @@ static int adxrs450_probe(struct spi_device *spi)
        /* This is only used for removal purposes */
        spi_set_drvdata(spi, indio_dev);
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &adxrs450_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels =
index 428ddfc..8ddda96 100644 (file)
@@ -1051,8 +1051,6 @@ static int bmg160_buffer_postdisable(struct iio_dev *indio_dev)
 
 static const struct iio_buffer_setup_ops bmg160_buffer_setup_ops = {
        .preenable = bmg160_buffer_preenable,
-       .postenable = iio_triggered_buffer_postenable,
-       .predisable = iio_triggered_buffer_predisable,
        .postdisable = bmg160_buffer_postdisable,
 };
 
@@ -1097,7 +1095,6 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq,
        if (ACPI_HANDLE(dev))
                name = bmg160_match_acpi_device(dev);
 
-       indio_dev->dev.parent = dev;
        indio_dev->channels = bmg160_channels;
        indio_dev->num_channels = ARRAY_SIZE(bmg160_channels);
        indio_dev->name = name;
index 89d2bb2..b5e0e96 100644 (file)
@@ -905,7 +905,6 @@ int fxas21002c_core_probe(struct device *dev, struct regmap *regmap, int irq,
        if (ret < 0)
                return ret;
 
-       indio_dev->dev.parent = dev;
        indio_dev->channels = fxas21002c_channels;
        indio_dev->num_channels = ARRAY_SIZE(fxas21002c_channels);
        indio_dev->name = name;
index 7f382aa..6698f5f 100644 (file)
@@ -319,7 +319,6 @@ static int hid_gyro_3d_probe(struct platform_device *pdev)
        }
 
        indio_dev->num_channels = ARRAY_SIZE(gyro_3d_channels);
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->info = &gyro_3d_info;
        indio_dev->name = name;
        indio_dev->modes = INDIO_DIRECT_MODE;
index b3afa55..e980466 100644 (file)
@@ -316,7 +316,6 @@ static int itg3200_probe(struct i2c_client *client,
        i2c_set_clientdata(client, indio_dev);
        st->i2c = client;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->name = client->dev.driver->name;
        indio_dev->channels = itg3200_channels;
        indio_dev->num_channels = ARRAY_SIZE(itg3200_channels);
index 8e908a7..00e5806 100644 (file)
@@ -662,8 +662,6 @@ static int mpu3050_buffer_postdisable(struct iio_dev *indio_dev)
 
 static const struct iio_buffer_setup_ops mpu3050_buffer_setup_ops = {
        .preenable = mpu3050_buffer_preenable,
-       .postenable = iio_triggered_buffer_postenable,
-       .predisable = iio_triggered_buffer_predisable,
        .postdisable = mpu3050_buffer_postdisable,
 };
 
@@ -1198,7 +1196,6 @@ int mpu3050_common_probe(struct device *dev,
        if (ret)
                goto err_power_down;
 
-       indio_dev->dev.parent = dev;
        indio_dev->channels = mpu3050_channels;
        indio_dev->num_channels = ARRAY_SIZE(mpu3050_channels);
        indio_dev->info = &mpu3050_info;
index 4e4ee41..ac7c170 100644 (file)
@@ -108,7 +108,6 @@ static int ssp_gyro_probe(struct platform_device *pdev)
        spd->type = SSP_GYROSCOPE_SENSOR;
 
        indio_dev->name = ssp_gyro_name;
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->info = &ssp_gyro_iio_info;
        indio_dev->modes = INDIO_BUFFER_SOFTWARE;
        indio_dev->channels = ssp_gyro_channels;
index 9c92ff7..4feb7ad 100644 (file)
@@ -33,13 +33,9 @@ static int st_gyro_buffer_postenable(struct iio_dev *indio_dev)
 {
        int err;
 
-       err = iio_triggered_buffer_postenable(indio_dev);
-       if (err < 0)
-               return err;
-
        err = st_sensors_set_axis_enable(indio_dev, indio_dev->active_scan_mask[0]);
        if (err < 0)
-               goto st_gyro_buffer_predisable;
+               return err;
 
        err = st_sensors_set_enable(indio_dev, true);
        if (err < 0)
@@ -49,27 +45,18 @@ static int st_gyro_buffer_postenable(struct iio_dev *indio_dev)
 
 st_gyro_buffer_enable_all_axis:
        st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
-st_gyro_buffer_predisable:
-       iio_triggered_buffer_predisable(indio_dev);
        return err;
 }
 
 static int st_gyro_buffer_predisable(struct iio_dev *indio_dev)
 {
-       int err, err2;
+       int err;
 
        err = st_sensors_set_enable(indio_dev, false);
        if (err < 0)
-               goto st_gyro_buffer_predisable;
-
-       err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
-
-st_gyro_buffer_predisable:
-       err2 = iio_triggered_buffer_predisable(indio_dev);
-       if (!err)
-               err = err2;
+               return err;
 
-       return err;
+       return st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
 }
 
 static const struct iio_buffer_setup_ops st_gyro_buffer_setup_ops = {
index e9f87e4..c554725 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * AFE4403 Heart Rate Monitors and Low-Cost Pulse Oximeters
  *
- * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/
  *     Andrew F. Davis <afd@ti.com>
  */
 
@@ -509,7 +509,6 @@ static int afe4403_probe(struct spi_device *spi)
        }
 
        indio_dev->modes = INDIO_DIRECT_MODE;
-       indio_dev->dev.parent = afe->dev;
        indio_dev->channels = afe4403_channels;
        indio_dev->num_channels = ARRAY_SIZE(afe4403_channels);
        indio_dev->name = AFE4403_DRIVER_NAME;
index e728bbb..c44b688 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * AFE4404 Heart Rate Monitors and Low-Cost Pulse Oximeters
  *
- * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/
  *     Andrew F. Davis <afd@ti.com>
  */
 
@@ -517,7 +517,6 @@ static int afe4404_probe(struct i2c_client *client,
        }
 
        indio_dev->modes = INDIO_DIRECT_MODE;
-       indio_dev->dev.parent = afe->dev;
        indio_dev->channels = afe4404_channels;
        indio_dev->num_channels = ARRAY_SIZE(afe4404_channels);
        indio_dev->name = AFE4404_DRIVER_NAME;
index 7829c4f..0adea00 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * AFE440X Heart Rate Monitors and Low-Cost Pulse Oximeters
  *
- * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com/
  *     Andrew F. Davis <afd@ti.com>
  */
 
index 546fc37..38aa203 100644 (file)
@@ -439,7 +439,6 @@ static int max30100_probe(struct i2c_client *client,
        indio_dev->available_scan_masks = max30100_scan_masks;
        indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
        indio_dev->setup_ops = &max30100_buffer_setup_ops;
-       indio_dev->dev.parent = &client->dev;
 
        data = iio_priv(indio_dev);
        data->indio_dev = indio_dev;
index 74fc260..9b47d94 100644 (file)
@@ -526,7 +526,6 @@ static int max30102_probe(struct i2c_client *client,
        indio_dev->info = &max30102_info;
        indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
        indio_dev->setup_ops = &max30102_buffer_setup_ops;
-       indio_dev->dev.parent = &client->dev;
 
        data = iio_priv(indio_dev);
        data->indio_dev = indio_dev;
index 3bac98e..02ad176 100644 (file)
@@ -233,7 +233,6 @@ static int am2315_probe(struct i2c_client *client,
        i2c_set_clientdata(client, indio_dev);
        mutex_init(&data->lock);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &am2315_info;
        indio_dev->name = AM2315_DRIVER_NAME;
        indio_dev->modes = INDIO_DIRECT_MODE;
index d05c6fd..9a78198 100644 (file)
@@ -321,7 +321,6 @@ static int dht11_probe(struct platform_device *pdev)
        init_completion(&dht11->completion);
        mutex_init(&dht11->lock);
        iio->name = pdev->name;
-       iio->dev.parent = &pdev->dev;
        iio->info = &dht11_iio_info;
        iio->modes = INDIO_DIRECT_MODE;
        iio->channels = dht11_chan_spec;
index 7ecd2ff..2571224 100644 (file)
@@ -6,11 +6,11 @@
  * Author: Matt Ranostay <matt.ranostay@konsulko.com>
  *
  * Datasheets:
- * http://www.ti.com/product/HDC1000/datasheet
- * http://www.ti.com/product/HDC1008/datasheet
- * http://www.ti.com/product/HDC1010/datasheet
- * http://www.ti.com/product/HDC1050/datasheet
- * http://www.ti.com/product/HDC1080/datasheet
+ * https://www.ti.com/product/HDC1000/datasheet
+ * https://www.ti.com/product/HDC1008/datasheet
+ * https://www.ti.com/product/HDC1010/datasheet
+ * https://www.ti.com/product/HDC1050/datasheet
+ * https://www.ti.com/product/HDC1080/datasheet
  */
 
 #include <linux/delay.h>
@@ -278,17 +278,11 @@ static int hdc100x_buffer_postenable(struct iio_dev *indio_dev)
        struct hdc100x_data *data = iio_priv(indio_dev);
        int ret;
 
-       ret = iio_triggered_buffer_postenable(indio_dev);
-       if (ret)
-               return ret;
-
        /* Buffer is enabled. First set ACQ Mode, then attach poll func */
        mutex_lock(&data->lock);
        ret = hdc100x_update_config(data, HDC100X_REG_CONFIG_ACQ_MODE,
                                    HDC100X_REG_CONFIG_ACQ_MODE);
        mutex_unlock(&data->lock);
-       if (ret)
-               iio_triggered_buffer_predisable(indio_dev);
 
        return ret;
 }
@@ -296,16 +290,12 @@ static int hdc100x_buffer_postenable(struct iio_dev *indio_dev)
 static int hdc100x_buffer_predisable(struct iio_dev *indio_dev)
 {
        struct hdc100x_data *data = iio_priv(indio_dev);
-       int ret, ret2;
+       int ret;
 
        mutex_lock(&data->lock);
        ret = hdc100x_update_config(data, HDC100X_REG_CONFIG_ACQ_MODE, 0);
        mutex_unlock(&data->lock);
 
-       ret2 = iio_triggered_buffer_predisable(indio_dev);
-       if (ret == 0)
-               ret = ret2;
-
        return ret;
 }
 
@@ -374,7 +364,6 @@ static int hdc100x_probe(struct i2c_client *client,
        data->client = client;
        mutex_init(&data->lock);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->name = dev_name(&client->dev);
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &hdc100x_info;
index d2318c4..52f6051 100644 (file)
@@ -226,7 +226,6 @@ static int hid_humidity_probe(struct platform_device *pdev)
 
        indio_dev->channels = humid_chans;
        indio_dev->num_channels = ARRAY_SIZE(humidity_channels);
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->info = &humidity_info;
        indio_dev->name = name;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 7d6771f..7c650df 100644 (file)
@@ -46,7 +46,7 @@ extern const struct dev_pm_ops hts221_pm_ops;
 int hts221_probe(struct device *dev, int irq, const char *name,
                 struct regmap *regmap);
 int hts221_set_enable(struct hts221_hw *hw, bool enable);
-int hts221_allocate_buffers(struct hts221_hw *hw);
-int hts221_allocate_trigger(struct hts221_hw *hw);
+int hts221_allocate_buffers(struct iio_dev *iio_dev);
+int hts221_allocate_trigger(struct iio_dev *iio_dev);
 
 #endif /* HTS221_H */
index 9fb3f33..f75f0b2 100644 (file)
@@ -72,10 +72,10 @@ static irqreturn_t hts221_trigger_handler_thread(int irq, void *private)
        return IRQ_HANDLED;
 }
 
-int hts221_allocate_trigger(struct hts221_hw *hw)
+int hts221_allocate_trigger(struct iio_dev *iio_dev)
 {
+       struct hts221_hw *hw = iio_priv(iio_dev);
        struct st_sensors_platform_data *pdata = dev_get_platdata(hw->dev);
-       struct iio_dev *iio_dev = iio_priv_to_dev(hw);
        bool irq_active_low = false, open_drain = false;
        unsigned long irq_type;
        int err;
@@ -153,8 +153,6 @@ static int hts221_buffer_postdisable(struct iio_dev *iio_dev)
 
 static const struct iio_buffer_setup_ops hts221_buffer_ops = {
        .preenable = hts221_buffer_preenable,
-       .postenable = iio_triggered_buffer_postenable,
-       .predisable = iio_triggered_buffer_predisable,
        .postdisable = hts221_buffer_postdisable,
 };
 
@@ -190,9 +188,10 @@ out:
        return IRQ_HANDLED;
 }
 
-int hts221_allocate_buffers(struct hts221_hw *hw)
+int hts221_allocate_buffers(struct iio_dev *iio_dev)
 {
-       return devm_iio_triggered_buffer_setup(hw->dev, iio_priv_to_dev(hw),
+       struct hts221_hw *hw = iio_priv(iio_dev);
+       return devm_iio_triggered_buffer_setup(hw->dev, iio_dev,
                                        NULL, hts221_buffer_handler_thread,
                                        &hts221_buffer_ops);
 }
index 9003671..1665778 100644 (file)
@@ -572,7 +572,6 @@ int hts221_probe(struct device *dev, int irq, const char *name,
                return err;
 
        iio_dev->modes = INDIO_DIRECT_MODE;
-       iio_dev->dev.parent = hw->dev;
        iio_dev->available_scan_masks = hts221_scan_masks;
        iio_dev->channels = hts221_channels;
        iio_dev->num_channels = ARRAY_SIZE(hts221_channels);
@@ -621,11 +620,11 @@ int hts221_probe(struct device *dev, int irq, const char *name,
        }
 
        if (hw->irq > 0) {
-               err = hts221_allocate_buffers(hw);
+               err = hts221_allocate_buffers(iio_dev);
                if (err < 0)
                        return err;
 
-               err = hts221_allocate_trigger(hw);
+               err = hts221_allocate_trigger(iio_dev);
                if (err)
                        return err;
        }
index d4c0589..4f5d9d1 100644 (file)
@@ -204,7 +204,6 @@ static int htu21_probe(struct i2c_client *client,
 
        indio_dev->info = &htu21_info;
        indio_dev->name = id->name;
-       indio_dev->dev.parent = &client->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
        if (id->driver_data == MS8607) {
index d5aef0b..160b3d9 100644 (file)
@@ -142,7 +142,6 @@ static int si7005_probe(struct i2c_client *client,
        data->client = client;
        mutex_init(&data->lock);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->name = dev_name(&client->dev);
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &si7005_info;
index b938f07..a09b577 100644 (file)
@@ -128,7 +128,6 @@ static int si7020_probe(struct i2c_client *client,
        data = iio_priv(indio_dev);
        *data = client;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->name = dev_name(&client->dev);
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &si7020_info;
index e59fe2f..9d1a92c 100644 (file)
@@ -18,6 +18,12 @@ void iio_device_register_trigger_consumer(struct iio_dev *indio_dev);
  **/
 void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev);
 
+
+int iio_trigger_attach_poll_func(struct iio_trigger *trig,
+                                struct iio_poll_func *pf);
+int iio_trigger_detach_poll_func(struct iio_trigger *trig,
+                                struct iio_poll_func *pf);
+
 #else
 
 /**
@@ -37,4 +43,15 @@ static void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev)
 {
 }
 
+static inline int iio_trigger_attach_poll_func(struct iio_trigger *trig,
+                                              struct iio_poll_func *pf)
+{
+       return 0;
+}
+static inline int iio_trigger_detach_poll_func(struct iio_trigger *trig,
+                                              struct iio_poll_func *pf)
+{
+       return 0;
+}
+
 #endif /* CONFIG_TRIGGER_CONSUMER */
index fc4123d..f02883b 100644 (file)
@@ -91,6 +91,7 @@ config KMX61
          To compile this driver as module, choose M here: the module will
          be called kmx61.
 
+source "drivers/iio/imu/inv_icm42600/Kconfig"
 source "drivers/iio/imu/inv_mpu6050/Kconfig"
 source "drivers/iio/imu/st_lsm6dsx/Kconfig"
 
index 88b2c45..13e9ff4 100644 (file)
@@ -20,6 +20,7 @@ obj-$(CONFIG_FXOS8700) += fxos8700_core.o
 obj-$(CONFIG_FXOS8700_I2C) += fxos8700_i2c.o
 obj-$(CONFIG_FXOS8700_SPI) += fxos8700_spi.o
 
+obj-y += inv_icm42600/
 obj-y += inv_mpu6050/
 
 obj-$(CONFIG_KMX61) += kmx61.o
index 229f2ff..1ebe3e5 100644 (file)
@@ -1181,7 +1181,6 @@ static int adis16400_probe(struct spi_device *spi)
 
        /* setup the industrialio driver allocated elements */
        st->variant = &adis16400_chips[spi_get_device_id(spi)->driver_data];
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->channels = st->variant->channels;
        indio_dev->num_channels = st->variant->num_channels;
index ad20c48..b26a5f1 100644 (file)
@@ -393,7 +393,6 @@ static int adis16460_probe(struct spi_device *spi)
        st = iio_priv(indio_dev);
 
        st->chip_info = &adis16460_chip_info;
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->channels = st->chip_info->channels;
        indio_dev->num_channels = st->chip_info->num_channels;
index c6dac4f..35d10cc 100644 (file)
@@ -1289,7 +1289,6 @@ static int adis16475_probe(struct spi_device *spi)
        if (ret)
                return ret;
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = st->info->name;
        indio_dev->channels = st->info->channels;
        indio_dev->num_channels = st->info->num_channels;
index 6a471ee..1eb4f98 100644 (file)
@@ -1102,12 +1102,12 @@ static int adis16480_config_irq_pin(struct device_node *of_node,
        /*
         * Get the interrupt line behaviour. The data ready polarity can be
         * configured as positive or negative, corresponding to
-        * IRQF_TRIGGER_RISING or IRQF_TRIGGER_FALLING respectively.
+        * IRQ_TYPE_EDGE_RISING or IRQ_TYPE_EDGE_FALLING respectively.
         */
        irq_type = irqd_get_trigger_type(desc);
-       if (irq_type == IRQF_TRIGGER_RISING) { /* Default */
+       if (irq_type == IRQ_TYPE_EDGE_RISING) { /* Default */
                val |= ADIS16480_DRDY_POL(1);
-       } else if (irq_type == IRQF_TRIGGER_FALLING) {
+       } else if (irq_type == IRQ_TYPE_EDGE_FALLING) {
                val |= ADIS16480_DRDY_POL(0);
        } else {
                dev_err(&st->adis.spi->dev,
@@ -1229,7 +1229,6 @@ static int adis16480_probe(struct spi_device *spi)
        st = iio_priv(indio_dev);
 
        st->chip_info = &adis16480_chip_info[id->driver_data];
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->channels = st->chip_info->channels;
        indio_dev->num_channels = st->chip_info->num_channels;
index 621f530..a82e040 100644 (file)
@@ -3,10 +3,13 @@
 #define BMI160_H_
 
 #include <linux/iio/iio.h>
+#include <linux/regulator/consumer.h>
 
 struct bmi160_data {
        struct regmap *regmap;
        struct iio_trigger *trig;
+       struct regulator_bulk_data supplies[2];
+       struct iio_mount_matrix orientation;
 };
 
 extern const struct regmap_config bmi160_regmap_config;
index 6af65d6..222ebb2 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/of_irq.h>
+#include <linux/regulator/consumer.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/triggered_buffer.h>
                .storagebits = 16,                              \
                .endianness = IIO_LE,                           \
        },                                                      \
+       .ext_info = bmi160_ext_info,                            \
 }
 
 /* scan indexes follow DATA register order */
@@ -264,6 +266,20 @@ static const struct  bmi160_odr_item bmi160_odr_table[] = {
        },
 };
 
+static const struct iio_mount_matrix *
+bmi160_get_mount_matrix(const struct iio_dev *indio_dev,
+                       const struct iio_chan_spec *chan)
+{
+       struct bmi160_data *data = iio_priv(indio_dev);
+
+       return &data->orientation;
+}
+
+static const struct iio_chan_spec_ext_info bmi160_ext_info[] = {
+       IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, bmi160_get_mount_matrix),
+       { }
+};
+
 static const struct iio_chan_spec bmi160_channels[] = {
        BMI160_CHANNEL(IIO_ACCEL, X, BMI160_SCAN_ACCEL_X),
        BMI160_CHANNEL(IIO_ACCEL, Y, BMI160_SCAN_ACCEL_Y),
@@ -709,6 +725,12 @@ static int bmi160_chip_init(struct bmi160_data *data, bool use_spi)
        unsigned int val;
        struct device *dev = regmap_get_device(data->regmap);
 
+       ret = regulator_bulk_enable(ARRAY_SIZE(data->supplies), data->supplies);
+       if (ret) {
+               dev_err(dev, "Failed to enable regulators: %d\n", ret);
+               return ret;
+       }
+
        ret = regmap_write(data->regmap, BMI160_REG_CMD, BMI160_CMD_SOFTRESET);
        if (ret)
                return ret;
@@ -793,9 +815,16 @@ int bmi160_probe_trigger(struct iio_dev *indio_dev, int irq, u32 irq_type)
 static void bmi160_chip_uninit(void *data)
 {
        struct bmi160_data *bmi_data = data;
+       struct device *dev = regmap_get_device(bmi_data->regmap);
+       int ret;
 
        bmi160_set_mode(bmi_data, BMI160_GYRO, false);
        bmi160_set_mode(bmi_data, BMI160_ACCEL, false);
+
+       ret = regulator_bulk_disable(ARRAY_SIZE(bmi_data->supplies),
+                                    bmi_data->supplies);
+       if (ret)
+               dev_err(dev, "Failed to disable regulators: %d\n", ret);
 }
 
 int bmi160_core_probe(struct device *dev, struct regmap *regmap,
@@ -815,6 +844,21 @@ int bmi160_core_probe(struct device *dev, struct regmap *regmap,
        dev_set_drvdata(dev, indio_dev);
        data->regmap = regmap;
 
+       data->supplies[0].supply = "vdd";
+       data->supplies[1].supply = "vddio";
+       ret = devm_regulator_bulk_get(dev,
+                                     ARRAY_SIZE(data->supplies),
+                                     data->supplies);
+       if (ret) {
+               dev_err(dev, "Failed to get regulators: %d\n", ret);
+               return ret;
+       }
+
+       ret = iio_read_mount_matrix(dev, "mount-matrix",
+                                   &data->orientation);
+       if (ret)
+               return ret;
+
        ret = bmi160_chip_init(data, use_spi);
        if (ret)
                return ret;
@@ -826,7 +870,6 @@ int bmi160_core_probe(struct device *dev, struct regmap *regmap,
        if (!name && ACPI_HANDLE(dev))
                name = bmi160_match_acpi_device(dev);
 
-       indio_dev->dev.parent = dev;
        indio_dev->channels = bmi160_channels;
        indio_dev->num_channels = ARRAY_SIZE(bmi160_channels);
        indio_dev->name = name;
@@ -853,6 +896,6 @@ int bmi160_core_probe(struct device *dev, struct regmap *regmap,
 }
 EXPORT_SYMBOL_GPL(bmi160_core_probe);
 
-MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com");
+MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>");
 MODULE_DESCRIPTION("Bosch BMI160 driver");
 MODULE_LICENSE("GPL v2");
index 7b47be4..ab28818 100644 (file)
@@ -633,7 +633,6 @@ int fxos8700_core_probe(struct device *dev, struct regmap *regmap,
        if (ret)
                return ret;
 
-       indio_dev->dev.parent = dev;
        indio_dev->channels = fxos8700_channels;
        indio_dev->num_channels = ARRAY_SIZE(fxos8700_channels);
        indio_dev->name = name ? name : "fxos8700";
diff --git a/drivers/iio/imu/inv_icm42600/Kconfig b/drivers/iio/imu/inv_icm42600/Kconfig
new file mode 100644 (file)
index 0000000..50cbcfc
--- /dev/null
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+config INV_ICM42600
+       tristate
+       select IIO_BUFFER
+
+config INV_ICM42600_I2C
+       tristate "InvenSense ICM-426xx I2C driver"
+       depends on I2C
+       select INV_ICM42600
+       select REGMAP_I2C
+       help
+         This driver supports the InvenSense ICM-426xx motion tracking
+         devices over I2C.
+
+         This driver can be built as a module. The module will be called
+         inv-icm42600-i2c.
+
+config INV_ICM42600_SPI
+       tristate "InvenSense ICM-426xx SPI driver"
+       depends on SPI_MASTER
+       select INV_ICM42600
+       select REGMAP_SPI
+       help
+         This driver supports the InvenSense ICM-426xx motion tracking
+         devices over SPI.
+
+         This driver can be built as a module. The module will be called
+         inv-icm42600-spi.
diff --git a/drivers/iio/imu/inv_icm42600/Makefile b/drivers/iio/imu/inv_icm42600/Makefile
new file mode 100644 (file)
index 0000000..291714d
--- /dev/null
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+obj-$(CONFIG_INV_ICM42600) += inv-icm42600.o
+inv-icm42600-y += inv_icm42600_core.o
+inv-icm42600-y += inv_icm42600_gyro.o
+inv-icm42600-y += inv_icm42600_accel.o
+inv-icm42600-y += inv_icm42600_temp.o
+inv-icm42600-y += inv_icm42600_buffer.o
+inv-icm42600-y += inv_icm42600_timestamp.o
+
+obj-$(CONFIG_INV_ICM42600_I2C) += inv-icm42600-i2c.o
+inv-icm42600-i2c-y += inv_icm42600_i2c.o
+
+obj-$(CONFIG_INV_ICM42600_SPI) += inv-icm42600-spi.o
+inv-icm42600-spi-y += inv_icm42600_spi.o
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
new file mode 100644 (file)
index 0000000..c0f5059
--- /dev/null
@@ -0,0 +1,395 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#ifndef INV_ICM42600_H_
+#define INV_ICM42600_H_
+
+#include <linux/bits.h>
+#include <linux/bitfield.h>
+#include <linux/regmap.h>
+#include <linux/mutex.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm.h>
+#include <linux/iio/iio.h>
+
+#include "inv_icm42600_buffer.h"
+
+enum inv_icm42600_chip {
+       INV_CHIP_ICM42600,
+       INV_CHIP_ICM42602,
+       INV_CHIP_ICM42605,
+       INV_CHIP_ICM42622,
+       INV_CHIP_NB,
+};
+
+/* serial bus slew rates */
+enum inv_icm42600_slew_rate {
+       INV_ICM42600_SLEW_RATE_20_60NS,
+       INV_ICM42600_SLEW_RATE_12_36NS,
+       INV_ICM42600_SLEW_RATE_6_18NS,
+       INV_ICM42600_SLEW_RATE_4_12NS,
+       INV_ICM42600_SLEW_RATE_2_6NS,
+       INV_ICM42600_SLEW_RATE_INF_2NS,
+};
+
+enum inv_icm42600_sensor_mode {
+       INV_ICM42600_SENSOR_MODE_OFF,
+       INV_ICM42600_SENSOR_MODE_STANDBY,
+       INV_ICM42600_SENSOR_MODE_LOW_POWER,
+       INV_ICM42600_SENSOR_MODE_LOW_NOISE,
+       INV_ICM42600_SENSOR_MODE_NB,
+};
+
+/* gyroscope fullscale values */
+enum inv_icm42600_gyro_fs {
+       INV_ICM42600_GYRO_FS_2000DPS,
+       INV_ICM42600_GYRO_FS_1000DPS,
+       INV_ICM42600_GYRO_FS_500DPS,
+       INV_ICM42600_GYRO_FS_250DPS,
+       INV_ICM42600_GYRO_FS_125DPS,
+       INV_ICM42600_GYRO_FS_62_5DPS,
+       INV_ICM42600_GYRO_FS_31_25DPS,
+       INV_ICM42600_GYRO_FS_15_625DPS,
+       INV_ICM42600_GYRO_FS_NB,
+};
+
+/* accelerometer fullscale values */
+enum inv_icm42600_accel_fs {
+       INV_ICM42600_ACCEL_FS_16G,
+       INV_ICM42600_ACCEL_FS_8G,
+       INV_ICM42600_ACCEL_FS_4G,
+       INV_ICM42600_ACCEL_FS_2G,
+       INV_ICM42600_ACCEL_FS_NB,
+};
+
+/* ODR suffixed by LN or LP are Low-Noise or Low-Power mode only */
+enum inv_icm42600_odr {
+       INV_ICM42600_ODR_8KHZ_LN = 3,
+       INV_ICM42600_ODR_4KHZ_LN,
+       INV_ICM42600_ODR_2KHZ_LN,
+       INV_ICM42600_ODR_1KHZ_LN,
+       INV_ICM42600_ODR_200HZ,
+       INV_ICM42600_ODR_100HZ,
+       INV_ICM42600_ODR_50HZ,
+       INV_ICM42600_ODR_25HZ,
+       INV_ICM42600_ODR_12_5HZ,
+       INV_ICM42600_ODR_6_25HZ_LP,
+       INV_ICM42600_ODR_3_125HZ_LP,
+       INV_ICM42600_ODR_1_5625HZ_LP,
+       INV_ICM42600_ODR_500HZ,
+       INV_ICM42600_ODR_NB,
+};
+
+enum inv_icm42600_filter {
+       /* Low-Noise mode sensor data filter (3rd order filter by default) */
+       INV_ICM42600_FILTER_BW_ODR_DIV_2,
+
+       /* Low-Power mode sensor data filter (averaging) */
+       INV_ICM42600_FILTER_AVG_1X = 1,
+       INV_ICM42600_FILTER_AVG_16X = 6,
+};
+
+struct inv_icm42600_sensor_conf {
+       int mode;
+       int fs;
+       int odr;
+       int filter;
+};
+#define INV_ICM42600_SENSOR_CONF_INIT          {-1, -1, -1, -1}
+
+struct inv_icm42600_conf {
+       struct inv_icm42600_sensor_conf gyro;
+       struct inv_icm42600_sensor_conf accel;
+       bool temp_en;
+};
+
+struct inv_icm42600_suspended {
+       enum inv_icm42600_sensor_mode gyro;
+       enum inv_icm42600_sensor_mode accel;
+       bool temp;
+};
+
+/**
+ *  struct inv_icm42600_state - driver state variables
+ *  @lock:             lock for serializing multiple registers access.
+ *  @chip:             chip identifier.
+ *  @name:             chip name.
+ *  @map:              regmap pointer.
+ *  @vdd_supply:       VDD voltage regulator for the chip.
+ *  @vddio_supply:     I/O voltage regulator for the chip.
+ *  @orientation:      sensor chip orientation relative to main hardware.
+ *  @conf:             chip sensors configurations.
+ *  @suspended:                suspended sensors configuration.
+ *  @indio_gyro:       gyroscope IIO device.
+ *  @indio_accel:      accelerometer IIO device.
+ *  @buffer:           data transfer buffer aligned for DMA.
+ *  @fifo:             FIFO management structure.
+ *  @timestamp:                interrupt timestamps.
+ */
+struct inv_icm42600_state {
+       struct mutex lock;
+       enum inv_icm42600_chip chip;
+       const char *name;
+       struct regmap *map;
+       struct regulator *vdd_supply;
+       struct regulator *vddio_supply;
+       struct iio_mount_matrix orientation;
+       struct inv_icm42600_conf conf;
+       struct inv_icm42600_suspended suspended;
+       struct iio_dev *indio_gyro;
+       struct iio_dev *indio_accel;
+       uint8_t buffer[2] ____cacheline_aligned;
+       struct inv_icm42600_fifo fifo;
+       struct {
+               int64_t gyro;
+               int64_t accel;
+       } timestamp;
+};
+
+/* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
+
+/* Bank selection register, available in all banks */
+#define INV_ICM42600_REG_BANK_SEL                      0x76
+#define INV_ICM42600_BANK_SEL_MASK                     GENMASK(2, 0)
+
+/* User bank 0 (MSB 0x00) */
+#define INV_ICM42600_REG_DEVICE_CONFIG                 0x0011
+#define INV_ICM42600_DEVICE_CONFIG_SOFT_RESET          BIT(0)
+
+#define INV_ICM42600_REG_DRIVE_CONFIG                  0x0013
+#define INV_ICM42600_DRIVE_CONFIG_I2C_MASK             GENMASK(5, 3)
+#define INV_ICM42600_DRIVE_CONFIG_I2C(_rate)           \
+               FIELD_PREP(INV_ICM42600_DRIVE_CONFIG_I2C_MASK, (_rate))
+#define INV_ICM42600_DRIVE_CONFIG_SPI_MASK             GENMASK(2, 0)
+#define INV_ICM42600_DRIVE_CONFIG_SPI(_rate)           \
+               FIELD_PREP(INV_ICM42600_DRIVE_CONFIG_SPI_MASK, (_rate))
+
+#define INV_ICM42600_REG_INT_CONFIG                    0x0014
+#define INV_ICM42600_INT_CONFIG_INT2_LATCHED           BIT(5)
+#define INV_ICM42600_INT_CONFIG_INT2_PUSH_PULL         BIT(4)
+#define INV_ICM42600_INT_CONFIG_INT2_ACTIVE_HIGH       BIT(3)
+#define INV_ICM42600_INT_CONFIG_INT2_ACTIVE_LOW                0x00
+#define INV_ICM42600_INT_CONFIG_INT1_LATCHED           BIT(2)
+#define INV_ICM42600_INT_CONFIG_INT1_PUSH_PULL         BIT(1)
+#define INV_ICM42600_INT_CONFIG_INT1_ACTIVE_HIGH       BIT(0)
+#define INV_ICM42600_INT_CONFIG_INT1_ACTIVE_LOW                0x00
+
+#define INV_ICM42600_REG_FIFO_CONFIG                   0x0016
+#define INV_ICM42600_FIFO_CONFIG_MASK                  GENMASK(7, 6)
+#define INV_ICM42600_FIFO_CONFIG_BYPASS                        \
+               FIELD_PREP(INV_ICM42600_FIFO_CONFIG_MASK, 0)
+#define INV_ICM42600_FIFO_CONFIG_STREAM                        \
+               FIELD_PREP(INV_ICM42600_FIFO_CONFIG_MASK, 1)
+#define INV_ICM42600_FIFO_CONFIG_STOP_ON_FULL          \
+               FIELD_PREP(INV_ICM42600_FIFO_CONFIG_MASK, 2)
+
+/* all sensor data are 16 bits (2 registers wide) in big-endian */
+#define INV_ICM42600_REG_TEMP_DATA                     0x001D
+#define INV_ICM42600_REG_ACCEL_DATA_X                  0x001F
+#define INV_ICM42600_REG_ACCEL_DATA_Y                  0x0021
+#define INV_ICM42600_REG_ACCEL_DATA_Z                  0x0023
+#define INV_ICM42600_REG_GYRO_DATA_X                   0x0025
+#define INV_ICM42600_REG_GYRO_DATA_Y                   0x0027
+#define INV_ICM42600_REG_GYRO_DATA_Z                   0x0029
+#define INV_ICM42600_DATA_INVALID                      -32768
+
+#define INV_ICM42600_REG_INT_STATUS                    0x002D
+#define INV_ICM42600_INT_STATUS_UI_FSYNC               BIT(6)
+#define INV_ICM42600_INT_STATUS_PLL_RDY                        BIT(5)
+#define INV_ICM42600_INT_STATUS_RESET_DONE             BIT(4)
+#define INV_ICM42600_INT_STATUS_DATA_RDY               BIT(3)
+#define INV_ICM42600_INT_STATUS_FIFO_THS               BIT(2)
+#define INV_ICM42600_INT_STATUS_FIFO_FULL              BIT(1)
+#define INV_ICM42600_INT_STATUS_AGC_RDY                        BIT(0)
+
+/*
+ * FIFO access registers
+ * FIFO count is 16 bits (2 registers) big-endian
+ * FIFO data is a continuous read register to read FIFO content
+ */
+#define INV_ICM42600_REG_FIFO_COUNT                    0x002E
+#define INV_ICM42600_REG_FIFO_DATA                     0x0030
+
+#define INV_ICM42600_REG_SIGNAL_PATH_RESET             0x004B
+#define INV_ICM42600_SIGNAL_PATH_RESET_DMP_INIT_EN     BIT(6)
+#define INV_ICM42600_SIGNAL_PATH_RESET_DMP_MEM_RESET   BIT(5)
+#define INV_ICM42600_SIGNAL_PATH_RESET_RESET           BIT(3)
+#define INV_ICM42600_SIGNAL_PATH_RESET_TMST_STROBE     BIT(2)
+#define INV_ICM42600_SIGNAL_PATH_RESET_FIFO_FLUSH      BIT(1)
+
+/* default configuration: all data big-endian and fifo count in bytes */
+#define INV_ICM42600_REG_INTF_CONFIG0                  0x004C
+#define INV_ICM42600_INTF_CONFIG0_FIFO_HOLD_LAST_DATA  BIT(7)
+#define INV_ICM42600_INTF_CONFIG0_FIFO_COUNT_REC       BIT(6)
+#define INV_ICM42600_INTF_CONFIG0_FIFO_COUNT_ENDIAN    BIT(5)
+#define INV_ICM42600_INTF_CONFIG0_SENSOR_DATA_ENDIAN   BIT(4)
+#define INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK     GENMASK(1, 0)
+#define INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_SPI_DIS  \
+               FIELD_PREP(INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK, 2)
+#define INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_I2C_DIS  \
+               FIELD_PREP(INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK, 3)
+
+#define INV_ICM42600_REG_INTF_CONFIG1                  0x004D
+#define INV_ICM42600_INTF_CONFIG1_ACCEL_LP_CLK_RC      BIT(3)
+
+#define INV_ICM42600_REG_PWR_MGMT0                     0x004E
+#define INV_ICM42600_PWR_MGMT0_TEMP_DIS                        BIT(5)
+#define INV_ICM42600_PWR_MGMT0_IDLE                    BIT(4)
+#define INV_ICM42600_PWR_MGMT0_GYRO(_mode)             \
+               FIELD_PREP(GENMASK(3, 2), (_mode))
+#define INV_ICM42600_PWR_MGMT0_ACCEL(_mode)            \
+               FIELD_PREP(GENMASK(1, 0), (_mode))
+
+#define INV_ICM42600_REG_GYRO_CONFIG0                  0x004F
+#define INV_ICM42600_GYRO_CONFIG0_FS(_fs)              \
+               FIELD_PREP(GENMASK(7, 5), (_fs))
+#define INV_ICM42600_GYRO_CONFIG0_ODR(_odr)            \
+               FIELD_PREP(GENMASK(3, 0), (_odr))
+
+#define INV_ICM42600_REG_ACCEL_CONFIG0                 0x0050
+#define INV_ICM42600_ACCEL_CONFIG0_FS(_fs)             \
+               FIELD_PREP(GENMASK(7, 5), (_fs))
+#define INV_ICM42600_ACCEL_CONFIG0_ODR(_odr)           \
+               FIELD_PREP(GENMASK(3, 0), (_odr))
+
+#define INV_ICM42600_REG_GYRO_ACCEL_CONFIG0            0x0052
+#define INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(_f) \
+               FIELD_PREP(GENMASK(7, 4), (_f))
+#define INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(_f)  \
+               FIELD_PREP(GENMASK(3, 0), (_f))
+
+#define INV_ICM42600_REG_TMST_CONFIG                   0x0054
+#define INV_ICM42600_TMST_CONFIG_MASK                  GENMASK(4, 0)
+#define INV_ICM42600_TMST_CONFIG_TMST_TO_REGS_EN       BIT(4)
+#define INV_ICM42600_TMST_CONFIG_TMST_RES_16US         BIT(3)
+#define INV_ICM42600_TMST_CONFIG_TMST_DELTA_EN         BIT(2)
+#define INV_ICM42600_TMST_CONFIG_TMST_FSYNC_EN         BIT(1)
+#define INV_ICM42600_TMST_CONFIG_TMST_EN               BIT(0)
+
+#define INV_ICM42600_REG_FIFO_CONFIG1                  0x005F
+#define INV_ICM42600_FIFO_CONFIG1_RESUME_PARTIAL_RD    BIT(6)
+#define INV_ICM42600_FIFO_CONFIG1_WM_GT_TH             BIT(5)
+#define INV_ICM42600_FIFO_CONFIG1_TMST_FSYNC_EN                BIT(3)
+#define INV_ICM42600_FIFO_CONFIG1_TEMP_EN              BIT(2)
+#define INV_ICM42600_FIFO_CONFIG1_GYRO_EN              BIT(1)
+#define INV_ICM42600_FIFO_CONFIG1_ACCEL_EN             BIT(0)
+
+/* FIFO watermark is 16 bits (2 registers wide) in little-endian */
+#define INV_ICM42600_REG_FIFO_WATERMARK                        0x0060
+#define INV_ICM42600_FIFO_WATERMARK_VAL(_wm)           \
+               cpu_to_le16((_wm) & GENMASK(11, 0))
+/* FIFO is 2048 bytes, let 12 samples for reading latency */
+#define INV_ICM42600_FIFO_WATERMARK_MAX                        (2048 - 12 * 16)
+
+#define INV_ICM42600_REG_INT_CONFIG1                   0x0064
+#define INV_ICM42600_INT_CONFIG1_TPULSE_DURATION       BIT(6)
+#define INV_ICM42600_INT_CONFIG1_TDEASSERT_DISABLE     BIT(5)
+#define INV_ICM42600_INT_CONFIG1_ASYNC_RESET           BIT(4)
+
+#define INV_ICM42600_REG_INT_SOURCE0                   0x0065
+#define INV_ICM42600_INT_SOURCE0_UI_FSYNC_INT1_EN      BIT(6)
+#define INV_ICM42600_INT_SOURCE0_PLL_RDY_INT1_EN       BIT(5)
+#define INV_ICM42600_INT_SOURCE0_RESET_DONE_INT1_EN    BIT(4)
+#define INV_ICM42600_INT_SOURCE0_UI_DRDY_INT1_EN       BIT(3)
+#define INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN      BIT(2)
+#define INV_ICM42600_INT_SOURCE0_FIFO_FULL_INT1_EN     BIT(1)
+#define INV_ICM42600_INT_SOURCE0_UI_AGC_RDY_INT1_EN    BIT(0)
+
+#define INV_ICM42600_REG_WHOAMI                                0x0075
+#define INV_ICM42600_WHOAMI_ICM42600                   0x40
+#define INV_ICM42600_WHOAMI_ICM42602                   0x41
+#define INV_ICM42600_WHOAMI_ICM42605                   0x42
+#define INV_ICM42600_WHOAMI_ICM42622                   0x46
+
+/* User bank 1 (MSB 0x10) */
+#define INV_ICM42600_REG_SENSOR_CONFIG0                        0x1003
+#define INV_ICM42600_SENSOR_CONFIG0_ZG_DISABLE         BIT(5)
+#define INV_ICM42600_SENSOR_CONFIG0_YG_DISABLE         BIT(4)
+#define INV_ICM42600_SENSOR_CONFIG0_XG_DISABLE         BIT(3)
+#define INV_ICM42600_SENSOR_CONFIG0_ZA_DISABLE         BIT(2)
+#define INV_ICM42600_SENSOR_CONFIG0_YA_DISABLE         BIT(1)
+#define INV_ICM42600_SENSOR_CONFIG0_XA_DISABLE         BIT(0)
+
+/* Timestamp value is 20 bits (3 registers) in little-endian */
+#define INV_ICM42600_REG_TMSTVAL                       0x1062
+#define INV_ICM42600_TMSTVAL_MASK                      GENMASK(19, 0)
+
+#define INV_ICM42600_REG_INTF_CONFIG4                  0x107A
+#define INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY         BIT(6)
+#define INV_ICM42600_INTF_CONFIG4_SPI_AP_4WIRE         BIT(1)
+
+#define INV_ICM42600_REG_INTF_CONFIG6                  0x107C
+#define INV_ICM42600_INTF_CONFIG6_MASK                 GENMASK(4, 0)
+#define INV_ICM42600_INTF_CONFIG6_I3C_EN               BIT(4)
+#define INV_ICM42600_INTF_CONFIG6_I3C_IBI_BYTE_EN      BIT(3)
+#define INV_ICM42600_INTF_CONFIG6_I3C_IBI_EN           BIT(2)
+#define INV_ICM42600_INTF_CONFIG6_I3C_DDR_EN           BIT(1)
+#define INV_ICM42600_INTF_CONFIG6_I3C_SDR_EN           BIT(0)
+
+/* User bank 4 (MSB 0x40) */
+#define INV_ICM42600_REG_INT_SOURCE8                   0x404F
+#define INV_ICM42600_INT_SOURCE8_FSYNC_IBI_EN          BIT(5)
+#define INV_ICM42600_INT_SOURCE8_PLL_RDY_IBI_EN                BIT(4)
+#define INV_ICM42600_INT_SOURCE8_UI_DRDY_IBI_EN                BIT(3)
+#define INV_ICM42600_INT_SOURCE8_FIFO_THS_IBI_EN       BIT(2)
+#define INV_ICM42600_INT_SOURCE8_FIFO_FULL_IBI_EN      BIT(1)
+#define INV_ICM42600_INT_SOURCE8_AGC_RDY_IBI_EN                BIT(0)
+
+#define INV_ICM42600_REG_OFFSET_USER0                  0x4077
+#define INV_ICM42600_REG_OFFSET_USER1                  0x4078
+#define INV_ICM42600_REG_OFFSET_USER2                  0x4079
+#define INV_ICM42600_REG_OFFSET_USER3                  0x407A
+#define INV_ICM42600_REG_OFFSET_USER4                  0x407B
+#define INV_ICM42600_REG_OFFSET_USER5                  0x407C
+#define INV_ICM42600_REG_OFFSET_USER6                  0x407D
+#define INV_ICM42600_REG_OFFSET_USER7                  0x407E
+#define INV_ICM42600_REG_OFFSET_USER8                  0x407F
+
+/* Sleep times required by the driver */
+#define INV_ICM42600_POWER_UP_TIME_MS          100
+#define INV_ICM42600_RESET_TIME_MS             1
+#define INV_ICM42600_ACCEL_STARTUP_TIME_MS     20
+#define INV_ICM42600_GYRO_STARTUP_TIME_MS      60
+#define INV_ICM42600_GYRO_STOP_TIME_MS         150
+#define INV_ICM42600_TEMP_STARTUP_TIME_MS      14
+#define INV_ICM42600_SUSPEND_DELAY_MS          2000
+
+typedef int (*inv_icm42600_bus_setup)(struct inv_icm42600_state *);
+
+extern const struct regmap_config inv_icm42600_regmap_config;
+extern const struct dev_pm_ops inv_icm42600_pm_ops;
+
+const struct iio_mount_matrix *
+inv_icm42600_get_mount_matrix(const struct iio_dev *indio_dev,
+                             const struct iio_chan_spec *chan);
+
+uint32_t inv_icm42600_odr_to_period(enum inv_icm42600_odr odr);
+
+int inv_icm42600_set_accel_conf(struct inv_icm42600_state *st,
+                               struct inv_icm42600_sensor_conf *conf,
+                               unsigned int *sleep_ms);
+
+int inv_icm42600_set_gyro_conf(struct inv_icm42600_state *st,
+                              struct inv_icm42600_sensor_conf *conf,
+                              unsigned int *sleep_ms);
+
+int inv_icm42600_set_temp_conf(struct inv_icm42600_state *st, bool enable,
+                              unsigned int *sleep_ms);
+
+int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg,
+                            unsigned int writeval, unsigned int *readval);
+
+int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq,
+                           inv_icm42600_bus_setup bus_setup);
+
+struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st);
+
+int inv_icm42600_gyro_parse_fifo(struct iio_dev *indio_dev);
+
+struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st);
+
+int inv_icm42600_accel_parse_fifo(struct iio_dev *indio_dev);
+
+#endif
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
new file mode 100644 (file)
index 0000000..3441b0d
--- /dev/null
@@ -0,0 +1,787 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/delay.h>
+#include <linux/math64.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/kfifo_buf.h>
+
+#include "inv_icm42600.h"
+#include "inv_icm42600_temp.h"
+#include "inv_icm42600_buffer.h"
+#include "inv_icm42600_timestamp.h"
+
+#define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info)          \
+       {                                                               \
+               .type = IIO_ACCEL,                                      \
+               .modified = 1,                                          \
+               .channel2 = _modifier,                                  \
+               .info_mask_separate =                                   \
+                       BIT(IIO_CHAN_INFO_RAW) |                        \
+                       BIT(IIO_CHAN_INFO_CALIBBIAS),                   \
+               .info_mask_shared_by_type =                             \
+                       BIT(IIO_CHAN_INFO_SCALE),                       \
+               .info_mask_shared_by_type_available =                   \
+                       BIT(IIO_CHAN_INFO_SCALE) |                      \
+                       BIT(IIO_CHAN_INFO_CALIBBIAS),                   \
+               .info_mask_shared_by_all =                              \
+                       BIT(IIO_CHAN_INFO_SAMP_FREQ),                   \
+               .info_mask_shared_by_all_available =                    \
+                       BIT(IIO_CHAN_INFO_SAMP_FREQ),                   \
+               .scan_index = _index,                                   \
+               .scan_type = {                                          \
+                       .sign = 's',                                    \
+                       .realbits = 16,                                 \
+                       .storagebits = 16,                              \
+                       .endianness = IIO_BE,                           \
+               },                                                      \
+               .ext_info = _ext_info,                                  \
+       }
+
+enum inv_icm42600_accel_scan {
+       INV_ICM42600_ACCEL_SCAN_X,
+       INV_ICM42600_ACCEL_SCAN_Y,
+       INV_ICM42600_ACCEL_SCAN_Z,
+       INV_ICM42600_ACCEL_SCAN_TEMP,
+       INV_ICM42600_ACCEL_SCAN_TIMESTAMP,
+};
+
+static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = {
+       IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, inv_icm42600_get_mount_matrix),
+       {},
+};
+
+static const struct iio_chan_spec inv_icm42600_accel_channels[] = {
+       INV_ICM42600_ACCEL_CHAN(IIO_MOD_X, INV_ICM42600_ACCEL_SCAN_X,
+                               inv_icm42600_accel_ext_infos),
+       INV_ICM42600_ACCEL_CHAN(IIO_MOD_Y, INV_ICM42600_ACCEL_SCAN_Y,
+                               inv_icm42600_accel_ext_infos),
+       INV_ICM42600_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42600_ACCEL_SCAN_Z,
+                               inv_icm42600_accel_ext_infos),
+       INV_ICM42600_TEMP_CHAN(INV_ICM42600_ACCEL_SCAN_TEMP),
+       IIO_CHAN_SOFT_TIMESTAMP(INV_ICM42600_ACCEL_SCAN_TIMESTAMP),
+};
+
+/*
+ * IIO buffer data: size must be a power of 2 and timestamp aligned
+ * 16 bytes: 6 bytes acceleration, 2 bytes temperature, 8 bytes timestamp
+ */
+struct inv_icm42600_accel_buffer {
+       struct inv_icm42600_fifo_sensor_data accel;
+       int16_t temp;
+       int64_t timestamp __aligned(8);
+};
+
+#define INV_ICM42600_SCAN_MASK_ACCEL_3AXIS                             \
+       (BIT(INV_ICM42600_ACCEL_SCAN_X) |                               \
+       BIT(INV_ICM42600_ACCEL_SCAN_Y) |                                \
+       BIT(INV_ICM42600_ACCEL_SCAN_Z))
+
+#define INV_ICM42600_SCAN_MASK_TEMP    BIT(INV_ICM42600_ACCEL_SCAN_TEMP)
+
+static const unsigned long inv_icm42600_accel_scan_masks[] = {
+       /* 3-axis accel + temperature */
+       INV_ICM42600_SCAN_MASK_ACCEL_3AXIS | INV_ICM42600_SCAN_MASK_TEMP,
+       0,
+};
+
+/* enable accelerometer sensor and FIFO write */
+static int inv_icm42600_accel_update_scan_mode(struct iio_dev *indio_dev,
+                                              const unsigned long *scan_mask)
+{
+       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+       struct inv_icm42600_timestamp *ts = iio_priv(indio_dev);
+       struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
+       unsigned int fifo_en = 0;
+       unsigned int sleep_temp = 0;
+       unsigned int sleep_accel = 0;
+       unsigned int sleep;
+       int ret;
+
+       mutex_lock(&st->lock);
+
+       if (*scan_mask & INV_ICM42600_SCAN_MASK_TEMP) {
+               /* enable temp sensor */
+               ret = inv_icm42600_set_temp_conf(st, true, &sleep_temp);
+               if (ret)
+                       goto out_unlock;
+               fifo_en |= INV_ICM42600_SENSOR_TEMP;
+       }
+
+       if (*scan_mask & INV_ICM42600_SCAN_MASK_ACCEL_3AXIS) {
+               /* enable accel sensor */
+               conf.mode = INV_ICM42600_SENSOR_MODE_LOW_NOISE;
+               ret = inv_icm42600_set_accel_conf(st, &conf, &sleep_accel);
+               if (ret)
+                       goto out_unlock;
+               fifo_en |= INV_ICM42600_SENSOR_ACCEL;
+       }
+
+       /* update data FIFO write */
+       inv_icm42600_timestamp_apply_odr(ts, 0, 0, 0);
+       ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en);
+       if (ret)
+               goto out_unlock;
+
+       ret = inv_icm42600_buffer_update_watermark(st);
+
+out_unlock:
+       mutex_unlock(&st->lock);
+       /* sleep maximum required time */
+       if (sleep_accel > sleep_temp)
+               sleep = sleep_accel;
+       else
+               sleep = sleep_temp;
+       if (sleep)
+               msleep(sleep);
+       return ret;
+}
+
+static int inv_icm42600_accel_read_sensor(struct inv_icm42600_state *st,
+                                         struct iio_chan_spec const *chan,
+                                         int16_t *val)
+{
+       struct device *dev = regmap_get_device(st->map);
+       struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
+       unsigned int reg;
+       __be16 *data;
+       int ret;
+
+       if (chan->type != IIO_ACCEL)
+               return -EINVAL;
+
+       switch (chan->channel2) {
+       case IIO_MOD_X:
+               reg = INV_ICM42600_REG_ACCEL_DATA_X;
+               break;
+       case IIO_MOD_Y:
+               reg = INV_ICM42600_REG_ACCEL_DATA_Y;
+               break;
+       case IIO_MOD_Z:
+               reg = INV_ICM42600_REG_ACCEL_DATA_Z;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       pm_runtime_get_sync(dev);
+       mutex_lock(&st->lock);
+
+       /* enable accel sensor */
+       conf.mode = INV_ICM42600_SENSOR_MODE_LOW_NOISE;
+       ret = inv_icm42600_set_accel_conf(st, &conf, NULL);
+       if (ret)
+               goto exit;
+
+       /* read accel register data */
+       data = (__be16 *)&st->buffer[0];
+       ret = regmap_bulk_read(st->map, reg, data, sizeof(*data));
+       if (ret)
+               goto exit;
+
+       *val = (int16_t)be16_to_cpup(data);
+       if (*val == INV_ICM42600_DATA_INVALID)
+               ret = -EINVAL;
+exit:
+       mutex_unlock(&st->lock);
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
+       return ret;
+}
+
+/* IIO format int + nano */
+static const int inv_icm42600_accel_scale[] = {
+       /* +/- 16G => 0.004788403 m/s-2 */
+       [2 * INV_ICM42600_ACCEL_FS_16G] = 0,
+       [2 * INV_ICM42600_ACCEL_FS_16G + 1] = 4788403,
+       /* +/- 8G => 0.002394202 m/s-2 */
+       [2 * INV_ICM42600_ACCEL_FS_8G] = 0,
+       [2 * INV_ICM42600_ACCEL_FS_8G + 1] = 2394202,
+       /* +/- 4G => 0.001197101 m/s-2 */
+       [2 * INV_ICM42600_ACCEL_FS_4G] = 0,
+       [2 * INV_ICM42600_ACCEL_FS_4G + 1] = 1197101,
+       /* +/- 2G => 0.000598550 m/s-2 */
+       [2 * INV_ICM42600_ACCEL_FS_2G] = 0,
+       [2 * INV_ICM42600_ACCEL_FS_2G + 1] = 598550,
+};
+
+static int inv_icm42600_accel_read_scale(struct inv_icm42600_state *st,
+                                        int *val, int *val2)
+{
+       unsigned int idx;
+
+       idx = st->conf.accel.fs;
+
+       *val = inv_icm42600_accel_scale[2 * idx];
+       *val2 = inv_icm42600_accel_scale[2 * idx + 1];
+       return IIO_VAL_INT_PLUS_NANO;
+}
+
+static int inv_icm42600_accel_write_scale(struct inv_icm42600_state *st,
+                                         int val, int val2)
+{
+       struct device *dev = regmap_get_device(st->map);
+       unsigned int idx;
+       struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
+       int ret;
+
+       for (idx = 0; idx < ARRAY_SIZE(inv_icm42600_accel_scale); idx += 2) {
+               if (val == inv_icm42600_accel_scale[idx] &&
+                   val2 == inv_icm42600_accel_scale[idx + 1])
+                       break;
+       }
+       if (idx >= ARRAY_SIZE(inv_icm42600_accel_scale))
+               return -EINVAL;
+
+       conf.fs = idx / 2;
+
+       pm_runtime_get_sync(dev);
+       mutex_lock(&st->lock);
+
+       ret = inv_icm42600_set_accel_conf(st, &conf, NULL);
+
+       mutex_unlock(&st->lock);
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
+
+       return ret;
+}
+
+/* IIO format int + micro */
+static const int inv_icm42600_accel_odr[] = {
+       /* 12.5Hz */
+       12, 500000,
+       /* 25Hz */
+       25, 0,
+       /* 50Hz */
+       50, 0,
+       /* 100Hz */
+       100, 0,
+       /* 200Hz */
+       200, 0,
+       /* 1kHz */
+       1000, 0,
+       /* 2kHz */
+       2000, 0,
+       /* 4kHz */
+       4000, 0,
+};
+
+static const int inv_icm42600_accel_odr_conv[] = {
+       INV_ICM42600_ODR_12_5HZ,
+       INV_ICM42600_ODR_25HZ,
+       INV_ICM42600_ODR_50HZ,
+       INV_ICM42600_ODR_100HZ,
+       INV_ICM42600_ODR_200HZ,
+       INV_ICM42600_ODR_1KHZ_LN,
+       INV_ICM42600_ODR_2KHZ_LN,
+       INV_ICM42600_ODR_4KHZ_LN,
+};
+
+static int inv_icm42600_accel_read_odr(struct inv_icm42600_state *st,
+                                      int *val, int *val2)
+{
+       unsigned int odr;
+       unsigned int i;
+
+       odr = st->conf.accel.odr;
+
+       for (i = 0; i < ARRAY_SIZE(inv_icm42600_accel_odr_conv); ++i) {
+               if (inv_icm42600_accel_odr_conv[i] == odr)
+                       break;
+       }
+       if (i >= ARRAY_SIZE(inv_icm42600_accel_odr_conv))
+               return -EINVAL;
+
+       *val = inv_icm42600_accel_odr[2 * i];
+       *val2 = inv_icm42600_accel_odr[2 * i + 1];
+
+       return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static int inv_icm42600_accel_write_odr(struct iio_dev *indio_dev,
+                                       int val, int val2)
+{
+       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+       struct inv_icm42600_timestamp *ts = iio_priv(indio_dev);
+       struct device *dev = regmap_get_device(st->map);
+       unsigned int idx;
+       struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
+       int ret;
+
+       for (idx = 0; idx < ARRAY_SIZE(inv_icm42600_accel_odr); idx += 2) {
+               if (val == inv_icm42600_accel_odr[idx] &&
+                   val2 == inv_icm42600_accel_odr[idx + 1])
+                       break;
+       }
+       if (idx >= ARRAY_SIZE(inv_icm42600_accel_odr))
+               return -EINVAL;
+
+       conf.odr = inv_icm42600_accel_odr_conv[idx / 2];
+
+       pm_runtime_get_sync(dev);
+       mutex_lock(&st->lock);
+
+       ret = inv_icm42600_timestamp_update_odr(ts, inv_icm42600_odr_to_period(conf.odr),
+                                               iio_buffer_enabled(indio_dev));
+       if (ret)
+               goto out_unlock;
+
+       ret = inv_icm42600_set_accel_conf(st, &conf, NULL);
+       if (ret)
+               goto out_unlock;
+       inv_icm42600_buffer_update_fifo_period(st);
+       inv_icm42600_buffer_update_watermark(st);
+
+out_unlock:
+       mutex_unlock(&st->lock);
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
+
+       return ret;
+}
+
+/*
+ * Calibration bias values, IIO range format int + micro.
+ * Value is limited to +/-1g coded on 12 bits signed. Step is 0.5mg.
+ */
+static int inv_icm42600_accel_calibbias[] = {
+       -10, 42010,             /* min: -10.042010 m/s² */
+       0, 4903,                /* step: 0.004903 m/s² */
+       10, 37106,              /* max: 10.037106 m/s² */
+};
+
+static int inv_icm42600_accel_read_offset(struct inv_icm42600_state *st,
+                                         struct iio_chan_spec const *chan,
+                                         int *val, int *val2)
+{
+       struct device *dev = regmap_get_device(st->map);
+       int64_t val64;
+       int32_t bias;
+       unsigned int reg;
+       int16_t offset;
+       uint8_t data[2];
+       int ret;
+
+       if (chan->type != IIO_ACCEL)
+               return -EINVAL;
+
+       switch (chan->channel2) {
+       case IIO_MOD_X:
+               reg = INV_ICM42600_REG_OFFSET_USER4;
+               break;
+       case IIO_MOD_Y:
+               reg = INV_ICM42600_REG_OFFSET_USER6;
+               break;
+       case IIO_MOD_Z:
+               reg = INV_ICM42600_REG_OFFSET_USER7;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       pm_runtime_get_sync(dev);
+       mutex_lock(&st->lock);
+
+       ret = regmap_bulk_read(st->map, reg, st->buffer, sizeof(data));
+       memcpy(data, st->buffer, sizeof(data));
+
+       mutex_unlock(&st->lock);
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
+       if (ret)
+               return ret;
+
+       /* 12 bits signed value */
+       switch (chan->channel2) {
+       case IIO_MOD_X:
+               offset = sign_extend32(((data[0] & 0xF0) << 4) | data[1], 11);
+               break;
+       case IIO_MOD_Y:
+               offset = sign_extend32(((data[1] & 0x0F) << 8) | data[0], 11);
+               break;
+       case IIO_MOD_Z:
+               offset = sign_extend32(((data[0] & 0xF0) << 4) | data[1], 11);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /*
+        * convert raw offset to g then to m/s²
+        * 12 bits signed raw step 0.5mg to g: 5 / 10000
+        * g to m/s²: 9.806650
+        * result in micro (1000000)
+        * (offset * 5 * 9.806650 * 1000000) / 10000
+        */
+       val64 = (int64_t)offset * 5LL * 9806650LL;
+       /* for rounding, add + or - divisor (10000) divided by 2 */
+       if (val64 >= 0)
+               val64 += 10000LL / 2LL;
+       else
+               val64 -= 10000LL / 2LL;
+       bias = div_s64(val64, 10000L);
+       *val = bias / 1000000L;
+       *val2 = bias % 1000000L;
+
+       return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static int inv_icm42600_accel_write_offset(struct inv_icm42600_state *st,
+                                          struct iio_chan_spec const *chan,
+                                          int val, int val2)
+{
+       struct device *dev = regmap_get_device(st->map);
+       int64_t val64;
+       int32_t min, max;
+       unsigned int reg, regval;
+       int16_t offset;
+       int ret;
+
+       if (chan->type != IIO_ACCEL)
+               return -EINVAL;
+
+       switch (chan->channel2) {
+       case IIO_MOD_X:
+               reg = INV_ICM42600_REG_OFFSET_USER4;
+               break;
+       case IIO_MOD_Y:
+               reg = INV_ICM42600_REG_OFFSET_USER6;
+               break;
+       case IIO_MOD_Z:
+               reg = INV_ICM42600_REG_OFFSET_USER7;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* inv_icm42600_accel_calibbias: min - step - max in micro */
+       min = inv_icm42600_accel_calibbias[0] * 1000000L +
+             inv_icm42600_accel_calibbias[1];
+       max = inv_icm42600_accel_calibbias[4] * 1000000L +
+             inv_icm42600_accel_calibbias[5];
+       val64 = (int64_t)val * 1000000LL + (int64_t)val2;
+       if (val64 < min || val64 > max)
+               return -EINVAL;
+
+       /*
+        * convert m/s² to g then to raw value
+        * m/s² to g: 1 / 9.806650
+        * g to raw 12 bits signed, step 0.5mg: 10000 / 5
+        * val in micro (1000000)
+        * val * 10000 / (9.806650 * 1000000 * 5)
+        */
+       val64 = val64 * 10000LL;
+       /* for rounding, add + or - divisor (9806650 * 5) divided by 2 */
+       if (val64 >= 0)
+               val64 += 9806650 * 5 / 2;
+       else
+               val64 -= 9806650 * 5 / 2;
+       offset = div_s64(val64, 9806650 * 5);
+
+       /* clamp value limited to 12 bits signed */
+       if (offset < -2048)
+               offset = -2048;
+       else if (offset > 2047)
+               offset = 2047;
+
+       pm_runtime_get_sync(dev);
+       mutex_lock(&st->lock);
+
+       switch (chan->channel2) {
+       case IIO_MOD_X:
+               /* OFFSET_USER4 register is shared */
+               ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER4,
+                                 &regval);
+               if (ret)
+                       goto out_unlock;
+               st->buffer[0] = ((offset & 0xF00) >> 4) | (regval & 0x0F);
+               st->buffer[1] = offset & 0xFF;
+               break;
+       case IIO_MOD_Y:
+               /* OFFSET_USER7 register is shared */
+               ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER7,
+                                 &regval);
+               if (ret)
+                       goto out_unlock;
+               st->buffer[0] = offset & 0xFF;
+               st->buffer[1] = ((offset & 0xF00) >> 8) | (regval & 0xF0);
+               break;
+       case IIO_MOD_Z:
+               /* OFFSET_USER7 register is shared */
+               ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER7,
+                                 &regval);
+               if (ret)
+                       goto out_unlock;
+               st->buffer[0] = ((offset & 0xF00) >> 4) | (regval & 0x0F);
+               st->buffer[1] = offset & 0xFF;
+               break;
+       default:
+               ret = -EINVAL;
+               goto out_unlock;
+       }
+
+       ret = regmap_bulk_write(st->map, reg, st->buffer, 2);
+
+out_unlock:
+       mutex_unlock(&st->lock);
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
+       return ret;
+}
+
+static int inv_icm42600_accel_read_raw(struct iio_dev *indio_dev,
+                                      struct iio_chan_spec const *chan,
+                                      int *val, int *val2, long mask)
+{
+       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+       int16_t data;
+       int ret;
+
+       switch (chan->type) {
+       case IIO_ACCEL:
+               break;
+       case IIO_TEMP:
+               return inv_icm42600_temp_read_raw(indio_dev, chan, val, val2, mask);
+       default:
+               return -EINVAL;
+       }
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               ret = iio_device_claim_direct_mode(indio_dev);
+               if (ret)
+                       return ret;
+               ret = inv_icm42600_accel_read_sensor(st, chan, &data);
+               iio_device_release_direct_mode(indio_dev);
+               if (ret)
+                       return ret;
+               *val = data;
+               return IIO_VAL_INT;
+       case IIO_CHAN_INFO_SCALE:
+               return inv_icm42600_accel_read_scale(st, val, val2);
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               return inv_icm42600_accel_read_odr(st, val, val2);
+       case IIO_CHAN_INFO_CALIBBIAS:
+               return inv_icm42600_accel_read_offset(st, chan, val, val2);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int inv_icm42600_accel_read_avail(struct iio_dev *indio_dev,
+                                        struct iio_chan_spec const *chan,
+                                        const int **vals,
+                                        int *type, int *length, long mask)
+{
+       if (chan->type != IIO_ACCEL)
+               return -EINVAL;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_SCALE:
+               *vals = inv_icm42600_accel_scale;
+               *type = IIO_VAL_INT_PLUS_NANO;
+               *length = ARRAY_SIZE(inv_icm42600_accel_scale);
+               return IIO_AVAIL_LIST;
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               *vals = inv_icm42600_accel_odr;
+               *type = IIO_VAL_INT_PLUS_MICRO;
+               *length = ARRAY_SIZE(inv_icm42600_accel_odr);
+               return IIO_AVAIL_LIST;
+       case IIO_CHAN_INFO_CALIBBIAS:
+               *vals = inv_icm42600_accel_calibbias;
+               *type = IIO_VAL_INT_PLUS_MICRO;
+               return IIO_AVAIL_RANGE;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int inv_icm42600_accel_write_raw(struct iio_dev *indio_dev,
+                                       struct iio_chan_spec const *chan,
+                                       int val, int val2, long mask)
+{
+       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+       int ret;
+
+       if (chan->type != IIO_ACCEL)
+               return -EINVAL;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_SCALE:
+               ret = iio_device_claim_direct_mode(indio_dev);
+               if (ret)
+                       return ret;
+               ret = inv_icm42600_accel_write_scale(st, val, val2);
+               iio_device_release_direct_mode(indio_dev);
+               return ret;
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               return inv_icm42600_accel_write_odr(indio_dev, val, val2);
+       case IIO_CHAN_INFO_CALIBBIAS:
+               ret = iio_device_claim_direct_mode(indio_dev);
+               if (ret)
+                       return ret;
+               ret = inv_icm42600_accel_write_offset(st, chan, val, val2);
+               iio_device_release_direct_mode(indio_dev);
+               return ret;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int inv_icm42600_accel_write_raw_get_fmt(struct iio_dev *indio_dev,
+                                               struct iio_chan_spec const *chan,
+                                               long mask)
+{
+       if (chan->type != IIO_ACCEL)
+               return -EINVAL;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_SCALE:
+               return IIO_VAL_INT_PLUS_NANO;
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               return IIO_VAL_INT_PLUS_MICRO;
+       case IIO_CHAN_INFO_CALIBBIAS:
+               return IIO_VAL_INT_PLUS_MICRO;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int inv_icm42600_accel_hwfifo_set_watermark(struct iio_dev *indio_dev,
+                                                  unsigned int val)
+{
+       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+       int ret;
+
+       mutex_lock(&st->lock);
+
+       st->fifo.watermark.accel = val;
+       ret = inv_icm42600_buffer_update_watermark(st);
+
+       mutex_unlock(&st->lock);
+
+       return ret;
+}
+
+static int inv_icm42600_accel_hwfifo_flush(struct iio_dev *indio_dev,
+                                          unsigned int count)
+{
+       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+       int ret;
+
+       if (count == 0)
+               return 0;
+
+       mutex_lock(&st->lock);
+
+       ret = inv_icm42600_buffer_hwfifo_flush(st, count);
+       if (!ret)
+               ret = st->fifo.nb.accel;
+
+       mutex_unlock(&st->lock);
+
+       return ret;
+}
+
+static const struct iio_info inv_icm42600_accel_info = {
+       .read_raw = inv_icm42600_accel_read_raw,
+       .read_avail = inv_icm42600_accel_read_avail,
+       .write_raw = inv_icm42600_accel_write_raw,
+       .write_raw_get_fmt = inv_icm42600_accel_write_raw_get_fmt,
+       .debugfs_reg_access = inv_icm42600_debugfs_reg,
+       .update_scan_mode = inv_icm42600_accel_update_scan_mode,
+       .hwfifo_set_watermark = inv_icm42600_accel_hwfifo_set_watermark,
+       .hwfifo_flush_to_buffer = inv_icm42600_accel_hwfifo_flush,
+};
+
+struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st)
+{
+       struct device *dev = regmap_get_device(st->map);
+       const char *name;
+       struct inv_icm42600_timestamp *ts;
+       struct iio_dev *indio_dev;
+       struct iio_buffer *buffer;
+       int ret;
+
+       name = devm_kasprintf(dev, GFP_KERNEL, "%s-accel", st->name);
+       if (!name)
+               return ERR_PTR(-ENOMEM);
+
+       indio_dev = devm_iio_device_alloc(dev, sizeof(*ts));
+       if (!indio_dev)
+               return ERR_PTR(-ENOMEM);
+
+       buffer = devm_iio_kfifo_allocate(dev);
+       if (!buffer)
+               return ERR_PTR(-ENOMEM);
+
+       ts = iio_priv(indio_dev);
+       inv_icm42600_timestamp_init(ts, inv_icm42600_odr_to_period(st->conf.accel.odr));
+
+       iio_device_set_drvdata(indio_dev, st);
+       indio_dev->name = name;
+       indio_dev->info = &inv_icm42600_accel_info;
+       indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
+       indio_dev->channels = inv_icm42600_accel_channels;
+       indio_dev->num_channels = ARRAY_SIZE(inv_icm42600_accel_channels);
+       indio_dev->available_scan_masks = inv_icm42600_accel_scan_masks;
+       indio_dev->setup_ops = &inv_icm42600_buffer_ops;
+
+       iio_device_attach_buffer(indio_dev, buffer);
+
+       ret = devm_iio_device_register(dev, indio_dev);
+       if (ret)
+               return ERR_PTR(ret);
+
+       return indio_dev;
+}
+
+int inv_icm42600_accel_parse_fifo(struct iio_dev *indio_dev)
+{
+       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+       struct inv_icm42600_timestamp *ts = iio_priv(indio_dev);
+       ssize_t i, size;
+       unsigned int no;
+       const void *accel, *gyro, *timestamp;
+       const int8_t *temp;
+       unsigned int odr;
+       int64_t ts_val;
+       struct inv_icm42600_accel_buffer buffer;
+
+       /* parse all fifo packets */
+       for (i = 0, no = 0; i < st->fifo.count; i += size, ++no) {
+               size = inv_icm42600_fifo_decode_packet(&st->fifo.data[i],
+                               &accel, &gyro, &temp, &timestamp, &odr);
+               /* quit if error or FIFO is empty */
+               if (size <= 0)
+                       return size;
+
+               /* skip packet if no accel data or data is invalid */
+               if (accel == NULL || !inv_icm42600_fifo_is_data_valid(accel))
+                       continue;
+
+               /* update odr */
+               if (odr & INV_ICM42600_SENSOR_ACCEL)
+                       inv_icm42600_timestamp_apply_odr(ts, st->fifo.period,
+                                                        st->fifo.nb.total, no);
+
+               /* buffer is copied to userspace, zeroing it to avoid any data leak */
+               memset(&buffer, 0, sizeof(buffer));
+               memcpy(&buffer.accel, accel, sizeof(buffer.accel));
+               /* convert 8 bits FIFO temperature in high resolution format */
+               buffer.temp = temp ? (*temp * 64) : 0;
+               ts_val = inv_icm42600_timestamp_pop(ts);
+               iio_push_to_buffers_with_timestamp(indio_dev, &buffer, ts_val);
+       }
+
+       return 0;
+}
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c
new file mode 100644 (file)
index 0000000..99576b2
--- /dev/null
@@ -0,0 +1,601 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/delay.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+
+#include "inv_icm42600.h"
+#include "inv_icm42600_timestamp.h"
+#include "inv_icm42600_buffer.h"
+
+/* FIFO header: 1 byte */
+#define INV_ICM42600_FIFO_HEADER_MSG           BIT(7)
+#define INV_ICM42600_FIFO_HEADER_ACCEL         BIT(6)
+#define INV_ICM42600_FIFO_HEADER_GYRO          BIT(5)
+#define INV_ICM42600_FIFO_HEADER_TMST_FSYNC    GENMASK(3, 2)
+#define INV_ICM42600_FIFO_HEADER_ODR_ACCEL     BIT(1)
+#define INV_ICM42600_FIFO_HEADER_ODR_GYRO      BIT(0)
+
+struct inv_icm42600_fifo_1sensor_packet {
+       uint8_t header;
+       struct inv_icm42600_fifo_sensor_data data;
+       int8_t temp;
+} __packed;
+#define INV_ICM42600_FIFO_1SENSOR_PACKET_SIZE          8
+
+struct inv_icm42600_fifo_2sensors_packet {
+       uint8_t header;
+       struct inv_icm42600_fifo_sensor_data accel;
+       struct inv_icm42600_fifo_sensor_data gyro;
+       int8_t temp;
+       __be16 timestamp;
+} __packed;
+#define INV_ICM42600_FIFO_2SENSORS_PACKET_SIZE         16
+
+ssize_t inv_icm42600_fifo_decode_packet(const void *packet, const void **accel,
+                                       const void **gyro, const int8_t **temp,
+                                       const void **timestamp, unsigned int *odr)
+{
+       const struct inv_icm42600_fifo_1sensor_packet *pack1 = packet;
+       const struct inv_icm42600_fifo_2sensors_packet *pack2 = packet;
+       uint8_t header = *((const uint8_t *)packet);
+
+       /* FIFO empty */
+       if (header & INV_ICM42600_FIFO_HEADER_MSG) {
+               *accel = NULL;
+               *gyro = NULL;
+               *temp = NULL;
+               *timestamp = NULL;
+               *odr = 0;
+               return 0;
+       }
+
+       /* handle odr flags */
+       *odr = 0;
+       if (header & INV_ICM42600_FIFO_HEADER_ODR_GYRO)
+               *odr |= INV_ICM42600_SENSOR_GYRO;
+       if (header & INV_ICM42600_FIFO_HEADER_ODR_ACCEL)
+               *odr |= INV_ICM42600_SENSOR_ACCEL;
+
+       /* accel + gyro */
+       if ((header & INV_ICM42600_FIFO_HEADER_ACCEL) &&
+           (header & INV_ICM42600_FIFO_HEADER_GYRO)) {
+               *accel = &pack2->accel;
+               *gyro = &pack2->gyro;
+               *temp = &pack2->temp;
+               *timestamp = &pack2->timestamp;
+               return INV_ICM42600_FIFO_2SENSORS_PACKET_SIZE;
+       }
+
+       /* accel only */
+       if (header & INV_ICM42600_FIFO_HEADER_ACCEL) {
+               *accel = &pack1->data;
+               *gyro = NULL;
+               *temp = &pack1->temp;
+               *timestamp = NULL;
+               return INV_ICM42600_FIFO_1SENSOR_PACKET_SIZE;
+       }
+
+       /* gyro only */
+       if (header & INV_ICM42600_FIFO_HEADER_GYRO) {
+               *accel = NULL;
+               *gyro = &pack1->data;
+               *temp = &pack1->temp;
+               *timestamp = NULL;
+               return INV_ICM42600_FIFO_1SENSOR_PACKET_SIZE;
+       }
+
+       /* invalid packet if here */
+       return -EINVAL;
+}
+
+void inv_icm42600_buffer_update_fifo_period(struct inv_icm42600_state *st)
+{
+       uint32_t period_gyro, period_accel, period;
+
+       if (st->fifo.en & INV_ICM42600_SENSOR_GYRO)
+               period_gyro = inv_icm42600_odr_to_period(st->conf.gyro.odr);
+       else
+               period_gyro = U32_MAX;
+
+       if (st->fifo.en & INV_ICM42600_SENSOR_ACCEL)
+               period_accel = inv_icm42600_odr_to_period(st->conf.accel.odr);
+       else
+               period_accel = U32_MAX;
+
+       if (period_gyro <= period_accel)
+               period = period_gyro;
+       else
+               period = period_accel;
+
+       st->fifo.period = period;
+}
+
+int inv_icm42600_buffer_set_fifo_en(struct inv_icm42600_state *st,
+                                   unsigned int fifo_en)
+{
+       unsigned int mask, val;
+       int ret;
+
+       /* update only FIFO EN bits */
+       mask = INV_ICM42600_FIFO_CONFIG1_TMST_FSYNC_EN |
+               INV_ICM42600_FIFO_CONFIG1_TEMP_EN |
+               INV_ICM42600_FIFO_CONFIG1_GYRO_EN |
+               INV_ICM42600_FIFO_CONFIG1_ACCEL_EN;
+
+       val = 0;
+       if (fifo_en & INV_ICM42600_SENSOR_GYRO)
+               val |= INV_ICM42600_FIFO_CONFIG1_GYRO_EN;
+       if (fifo_en & INV_ICM42600_SENSOR_ACCEL)
+               val |= INV_ICM42600_FIFO_CONFIG1_ACCEL_EN;
+       if (fifo_en & INV_ICM42600_SENSOR_TEMP)
+               val |= INV_ICM42600_FIFO_CONFIG1_TEMP_EN;
+
+       ret = regmap_update_bits(st->map, INV_ICM42600_REG_FIFO_CONFIG1, mask, val);
+       if (ret)
+               return ret;
+
+       st->fifo.en = fifo_en;
+       inv_icm42600_buffer_update_fifo_period(st);
+
+       return 0;
+}
+
+static size_t inv_icm42600_get_packet_size(unsigned int fifo_en)
+{
+       size_t packet_size;
+
+       if ((fifo_en & INV_ICM42600_SENSOR_GYRO) &&
+           (fifo_en & INV_ICM42600_SENSOR_ACCEL))
+               packet_size = INV_ICM42600_FIFO_2SENSORS_PACKET_SIZE;
+       else
+               packet_size = INV_ICM42600_FIFO_1SENSOR_PACKET_SIZE;
+
+       return packet_size;
+}
+
+static unsigned int inv_icm42600_wm_truncate(unsigned int watermark,
+                                            size_t packet_size)
+{
+       size_t wm_size;
+       unsigned int wm;
+
+       wm_size = watermark * packet_size;
+       if (wm_size > INV_ICM42600_FIFO_WATERMARK_MAX)
+               wm_size = INV_ICM42600_FIFO_WATERMARK_MAX;
+
+       wm = wm_size / packet_size;
+
+       return wm;
+}
+
+/**
+ * inv_icm42600_buffer_update_watermark - update watermark FIFO threshold
+ * @st:        driver internal state
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ *
+ * FIFO watermark threshold is computed based on the required watermark values
+ * set for gyro and accel sensors. Since watermark is all about acceptable data
+ * latency, use the smallest setting between the 2. It means choosing the
+ * smallest latency but this is not as simple as choosing the smallest watermark
+ * value. Latency depends on watermark and ODR. It requires several steps:
+ * 1) compute gyro and accel latencies and choose the smallest value.
+ * 2) adapt the choosen latency so that it is a multiple of both gyro and accel
+ *    ones. Otherwise it is possible that you don't meet a requirement. (for
+ *    example with gyro @100Hz wm 4 and accel @100Hz with wm 6, choosing the
+ *    value of 4 will not meet accel latency requirement because 6 is not a
+ *    multiple of 4. You need to use the value 2.)
+ * 3) Since all periods are multiple of each others, watermark is computed by
+ *    dividing this computed latency by the smallest period, which corresponds
+ *    to the FIFO frequency. Beware that this is only true because we are not
+ *    using 500Hz frequency which is not a multiple of the others.
+ */
+int inv_icm42600_buffer_update_watermark(struct inv_icm42600_state *st)
+{
+       size_t packet_size, wm_size;
+       unsigned int wm_gyro, wm_accel, watermark;
+       uint32_t period_gyro, period_accel, period;
+       uint32_t latency_gyro, latency_accel, latency;
+       bool restore;
+       __le16 raw_wm;
+       int ret;
+
+       packet_size = inv_icm42600_get_packet_size(st->fifo.en);
+
+       /* compute sensors latency, depending on sensor watermark and odr */
+       wm_gyro = inv_icm42600_wm_truncate(st->fifo.watermark.gyro, packet_size);
+       wm_accel = inv_icm42600_wm_truncate(st->fifo.watermark.accel, packet_size);
+       /* use us for odr to avoid overflow using 32 bits values */
+       period_gyro = inv_icm42600_odr_to_period(st->conf.gyro.odr) / 1000UL;
+       period_accel = inv_icm42600_odr_to_period(st->conf.accel.odr) / 1000UL;
+       latency_gyro = period_gyro * wm_gyro;
+       latency_accel = period_accel * wm_accel;
+
+       /* 0 value for watermark means that the sensor is turned off */
+       if (latency_gyro == 0) {
+               watermark = wm_accel;
+       } else if (latency_accel == 0) {
+               watermark = wm_gyro;
+       } else {
+               /* compute the smallest latency that is a multiple of both */
+               if (latency_gyro <= latency_accel)
+                       latency = latency_gyro - (latency_accel % latency_gyro);
+               else
+                       latency = latency_accel - (latency_gyro % latency_accel);
+               /* use the shortest period */
+               if (period_gyro <= period_accel)
+                       period = period_gyro;
+               else
+                       period = period_accel;
+               /* all this works because periods are multiple of each others */
+               watermark = latency / period;
+               if (watermark < 1)
+                       watermark = 1;
+       }
+
+       /* compute watermark value in bytes */
+       wm_size = watermark * packet_size;
+
+       /* changing FIFO watermark requires to turn off watermark interrupt */
+       ret = regmap_update_bits_check(st->map, INV_ICM42600_REG_INT_SOURCE0,
+                                      INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN,
+                                      0, &restore);
+       if (ret)
+               return ret;
+
+       raw_wm = INV_ICM42600_FIFO_WATERMARK_VAL(wm_size);
+       memcpy(st->buffer, &raw_wm, sizeof(raw_wm));
+       ret = regmap_bulk_write(st->map, INV_ICM42600_REG_FIFO_WATERMARK,
+                               st->buffer, sizeof(raw_wm));
+       if (ret)
+               return ret;
+
+       /* restore watermark interrupt */
+       if (restore) {
+               ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0,
+                                        INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN,
+                                        INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int inv_icm42600_buffer_preenable(struct iio_dev *indio_dev)
+{
+       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+       struct device *dev = regmap_get_device(st->map);
+
+       pm_runtime_get_sync(dev);
+
+       return 0;
+}
+
+/*
+ * update_scan_mode callback is turning sensors on and setting data FIFO enable
+ * bits.
+ */
+static int inv_icm42600_buffer_postenable(struct iio_dev *indio_dev)
+{
+       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+       int ret;
+
+       mutex_lock(&st->lock);
+
+       /* exit if FIFO is already on */
+       if (st->fifo.on) {
+               ret = 0;
+               goto out_on;
+       }
+
+       /* set FIFO threshold interrupt */
+       ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0,
+                                INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN,
+                                INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN);
+       if (ret)
+               goto out_unlock;
+
+       /* flush FIFO data */
+       ret = regmap_write(st->map, INV_ICM42600_REG_SIGNAL_PATH_RESET,
+                          INV_ICM42600_SIGNAL_PATH_RESET_FIFO_FLUSH);
+       if (ret)
+               goto out_unlock;
+
+       /* set FIFO in streaming mode */
+       ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG,
+                          INV_ICM42600_FIFO_CONFIG_STREAM);
+       if (ret)
+               goto out_unlock;
+
+       /* workaround: first read of FIFO count after reset is always 0 */
+       ret = regmap_bulk_read(st->map, INV_ICM42600_REG_FIFO_COUNT, st->buffer, 2);
+       if (ret)
+               goto out_unlock;
+
+out_on:
+       /* increase FIFO on counter */
+       st->fifo.on++;
+out_unlock:
+       mutex_unlock(&st->lock);
+       return ret;
+}
+
+static int inv_icm42600_buffer_predisable(struct iio_dev *indio_dev)
+{
+       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+       int ret;
+
+       mutex_lock(&st->lock);
+
+       /* exit if there are several sensors using the FIFO */
+       if (st->fifo.on > 1) {
+               ret = 0;
+               goto out_off;
+       }
+
+       /* set FIFO in bypass mode */
+       ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG,
+                          INV_ICM42600_FIFO_CONFIG_BYPASS);
+       if (ret)
+               goto out_unlock;
+
+       /* flush FIFO data */
+       ret = regmap_write(st->map, INV_ICM42600_REG_SIGNAL_PATH_RESET,
+                          INV_ICM42600_SIGNAL_PATH_RESET_FIFO_FLUSH);
+       if (ret)
+               goto out_unlock;
+
+       /* disable FIFO threshold interrupt */
+       ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0,
+                                INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN, 0);
+       if (ret)
+               goto out_unlock;
+
+out_off:
+       /* decrease FIFO on counter */
+       st->fifo.on--;
+out_unlock:
+       mutex_unlock(&st->lock);
+       return ret;
+}
+
+static int inv_icm42600_buffer_postdisable(struct iio_dev *indio_dev)
+{
+       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+       struct device *dev = regmap_get_device(st->map);
+       unsigned int sensor;
+       unsigned int *watermark;
+       struct inv_icm42600_timestamp *ts;
+       struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
+       unsigned int sleep_temp = 0;
+       unsigned int sleep_sensor = 0;
+       unsigned int sleep;
+       int ret;
+
+       if (indio_dev == st->indio_gyro) {
+               sensor = INV_ICM42600_SENSOR_GYRO;
+               watermark = &st->fifo.watermark.gyro;
+               ts = iio_priv(st->indio_gyro);
+       } else if (indio_dev == st->indio_accel) {
+               sensor = INV_ICM42600_SENSOR_ACCEL;
+               watermark = &st->fifo.watermark.accel;
+               ts = iio_priv(st->indio_accel);
+       } else {
+               return -EINVAL;
+       }
+
+       mutex_lock(&st->lock);
+
+       ret = inv_icm42600_buffer_set_fifo_en(st, st->fifo.en & ~sensor);
+       if (ret)
+               goto out_unlock;
+
+       *watermark = 0;
+       ret = inv_icm42600_buffer_update_watermark(st);
+       if (ret)
+               goto out_unlock;
+
+       conf.mode = INV_ICM42600_SENSOR_MODE_OFF;
+       if (sensor == INV_ICM42600_SENSOR_GYRO)
+               ret = inv_icm42600_set_gyro_conf(st, &conf, &sleep_sensor);
+       else
+               ret = inv_icm42600_set_accel_conf(st, &conf, &sleep_sensor);
+       if (ret)
+               goto out_unlock;
+
+       /* if FIFO is off, turn temperature off */
+       if (!st->fifo.on)
+               ret = inv_icm42600_set_temp_conf(st, false, &sleep_temp);
+
+       inv_icm42600_timestamp_reset(ts);
+
+out_unlock:
+       mutex_unlock(&st->lock);
+
+       /* sleep maximum required time */
+       if (sleep_sensor > sleep_temp)
+               sleep = sleep_sensor;
+       else
+               sleep = sleep_temp;
+       if (sleep)
+               msleep(sleep);
+
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
+
+       return ret;
+}
+
+const struct iio_buffer_setup_ops inv_icm42600_buffer_ops = {
+       .preenable = inv_icm42600_buffer_preenable,
+       .postenable = inv_icm42600_buffer_postenable,
+       .predisable = inv_icm42600_buffer_predisable,
+       .postdisable = inv_icm42600_buffer_postdisable,
+};
+
+int inv_icm42600_buffer_fifo_read(struct inv_icm42600_state *st,
+                                 unsigned int max)
+{
+       size_t max_count;
+       __be16 *raw_fifo_count;
+       ssize_t i, size;
+       const void *accel, *gyro, *timestamp;
+       const int8_t *temp;
+       unsigned int odr;
+       int ret;
+
+       /* reset all samples counters */
+       st->fifo.count = 0;
+       st->fifo.nb.gyro = 0;
+       st->fifo.nb.accel = 0;
+       st->fifo.nb.total = 0;
+
+       /* compute maximum FIFO read size */
+       if (max == 0)
+               max_count = sizeof(st->fifo.data);
+       else
+               max_count = max * inv_icm42600_get_packet_size(st->fifo.en);
+
+       /* read FIFO count value */
+       raw_fifo_count = (__be16 *)st->buffer;
+       ret = regmap_bulk_read(st->map, INV_ICM42600_REG_FIFO_COUNT,
+                              raw_fifo_count, sizeof(*raw_fifo_count));
+       if (ret)
+               return ret;
+       st->fifo.count = be16_to_cpup(raw_fifo_count);
+
+       /* check and clamp FIFO count value */
+       if (st->fifo.count == 0)
+               return 0;
+       if (st->fifo.count > max_count)
+               st->fifo.count = max_count;
+
+       /* read all FIFO data in internal buffer */
+       ret = regmap_noinc_read(st->map, INV_ICM42600_REG_FIFO_DATA,
+                               st->fifo.data, st->fifo.count);
+       if (ret)
+               return ret;
+
+       /* compute number of samples for each sensor */
+       for (i = 0; i < st->fifo.count; i += size) {
+               size = inv_icm42600_fifo_decode_packet(&st->fifo.data[i],
+                               &accel, &gyro, &temp, &timestamp, &odr);
+               if (size <= 0)
+                       break;
+               if (gyro != NULL && inv_icm42600_fifo_is_data_valid(gyro))
+                       st->fifo.nb.gyro++;
+               if (accel != NULL && inv_icm42600_fifo_is_data_valid(accel))
+                       st->fifo.nb.accel++;
+               st->fifo.nb.total++;
+       }
+
+       return 0;
+}
+
+int inv_icm42600_buffer_fifo_parse(struct inv_icm42600_state *st)
+{
+       struct inv_icm42600_timestamp *ts;
+       int ret;
+
+       if (st->fifo.nb.total == 0)
+               return 0;
+
+       /* handle gyroscope timestamp and FIFO data parsing */
+       ts = iio_priv(st->indio_gyro);
+       inv_icm42600_timestamp_interrupt(ts, st->fifo.period, st->fifo.nb.total,
+                                        st->fifo.nb.gyro, st->timestamp.gyro);
+       if (st->fifo.nb.gyro > 0) {
+               ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro);
+               if (ret)
+                       return ret;
+       }
+
+       /* handle accelerometer timestamp and FIFO data parsing */
+       ts = iio_priv(st->indio_accel);
+       inv_icm42600_timestamp_interrupt(ts, st->fifo.period, st->fifo.nb.total,
+                                        st->fifo.nb.accel, st->timestamp.accel);
+       if (st->fifo.nb.accel > 0) {
+               ret = inv_icm42600_accel_parse_fifo(st->indio_accel);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+int inv_icm42600_buffer_hwfifo_flush(struct inv_icm42600_state *st,
+                                    unsigned int count)
+{
+       struct inv_icm42600_timestamp *ts;
+       int64_t gyro_ts, accel_ts;
+       int ret;
+
+       gyro_ts = iio_get_time_ns(st->indio_gyro);
+       accel_ts = iio_get_time_ns(st->indio_accel);
+
+       ret = inv_icm42600_buffer_fifo_read(st, count);
+       if (ret)
+               return ret;
+
+       if (st->fifo.nb.total == 0)
+               return 0;
+
+       if (st->fifo.nb.gyro > 0) {
+               ts = iio_priv(st->indio_gyro);
+               inv_icm42600_timestamp_interrupt(ts, st->fifo.period,
+                                                st->fifo.nb.total, st->fifo.nb.gyro,
+                                                gyro_ts);
+               ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro);
+               if (ret)
+                       return ret;
+       }
+
+       if (st->fifo.nb.accel > 0) {
+               ts = iio_priv(st->indio_accel);
+               inv_icm42600_timestamp_interrupt(ts, st->fifo.period,
+                                                st->fifo.nb.total, st->fifo.nb.accel,
+                                                accel_ts);
+               ret = inv_icm42600_accel_parse_fifo(st->indio_accel);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+int inv_icm42600_buffer_init(struct inv_icm42600_state *st)
+{
+       unsigned int val;
+       int ret;
+
+       /*
+        * Default FIFO configuration (bits 7 to 5)
+        * - use invalid value
+        * - FIFO count in bytes
+        * - FIFO count in big endian
+        */
+       val = INV_ICM42600_INTF_CONFIG0_FIFO_COUNT_ENDIAN;
+       ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0,
+                                GENMASK(7, 5), val);
+       if (ret)
+               return ret;
+
+       /*
+        * Enable FIFO partial read and continuous watermark interrupt.
+        * Disable all FIFO EN bits.
+        */
+       val = INV_ICM42600_FIFO_CONFIG1_RESUME_PARTIAL_RD |
+             INV_ICM42600_FIFO_CONFIG1_WM_GT_TH;
+       return regmap_update_bits(st->map, INV_ICM42600_REG_FIFO_CONFIG1,
+                                 GENMASK(6, 5) | GENMASK(3, 0), val);
+}
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h
new file mode 100644 (file)
index 0000000..de2a394
--- /dev/null
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#ifndef INV_ICM42600_BUFFER_H_
+#define INV_ICM42600_BUFFER_H_
+
+#include <linux/kernel.h>
+#include <linux/bits.h>
+
+struct inv_icm42600_state;
+
+#define INV_ICM42600_SENSOR_GYRO       BIT(0)
+#define INV_ICM42600_SENSOR_ACCEL      BIT(1)
+#define INV_ICM42600_SENSOR_TEMP       BIT(2)
+
+/**
+ * struct inv_icm42600_fifo - FIFO state variables
+ * @on:                reference counter for FIFO on.
+ * @en:                bits field of INV_ICM42600_SENSOR_* for FIFO EN bits.
+ * @period:    FIFO internal period.
+ * @watermark: watermark configuration values for accel and gyro.
+ * @count:     number of bytes in the FIFO data buffer.
+ * @nb:                gyro, accel and total samples in the FIFO data buffer.
+ * @data:      FIFO data buffer aligned for DMA (2kB + 32 bytes of read cache).
+ */
+struct inv_icm42600_fifo {
+       unsigned int on;
+       unsigned int en;
+       uint32_t period;
+       struct {
+               unsigned int gyro;
+               unsigned int accel;
+       } watermark;
+       size_t count;
+       struct {
+               size_t gyro;
+               size_t accel;
+               size_t total;
+       } nb;
+       uint8_t data[2080] ____cacheline_aligned;
+};
+
+/* FIFO data packet */
+struct inv_icm42600_fifo_sensor_data {
+       __be16 x;
+       __be16 y;
+       __be16 z;
+} __packed;
+#define INV_ICM42600_FIFO_DATA_INVALID         -32768
+
+static inline int16_t inv_icm42600_fifo_get_sensor_data(__be16 d)
+{
+       return be16_to_cpu(d);
+}
+
+static inline bool
+inv_icm42600_fifo_is_data_valid(const struct inv_icm42600_fifo_sensor_data *s)
+{
+       int16_t x, y, z;
+
+       x = inv_icm42600_fifo_get_sensor_data(s->x);
+       y = inv_icm42600_fifo_get_sensor_data(s->y);
+       z = inv_icm42600_fifo_get_sensor_data(s->z);
+
+       if (x == INV_ICM42600_FIFO_DATA_INVALID &&
+           y == INV_ICM42600_FIFO_DATA_INVALID &&
+           z == INV_ICM42600_FIFO_DATA_INVALID)
+               return false;
+
+       return true;
+}
+
+ssize_t inv_icm42600_fifo_decode_packet(const void *packet, const void **accel,
+                                       const void **gyro, const int8_t **temp,
+                                       const void **timestamp, unsigned int *odr);
+
+extern const struct iio_buffer_setup_ops inv_icm42600_buffer_ops;
+
+int inv_icm42600_buffer_init(struct inv_icm42600_state *st);
+
+void inv_icm42600_buffer_update_fifo_period(struct inv_icm42600_state *st);
+
+int inv_icm42600_buffer_set_fifo_en(struct inv_icm42600_state *st,
+                                   unsigned int fifo_en);
+
+int inv_icm42600_buffer_update_watermark(struct inv_icm42600_state *st);
+
+int inv_icm42600_buffer_fifo_read(struct inv_icm42600_state *st,
+                                 unsigned int max);
+
+int inv_icm42600_buffer_fifo_parse(struct inv_icm42600_state *st);
+
+int inv_icm42600_buffer_hwfifo_flush(struct inv_icm42600_state *st,
+                                    unsigned int count);
+
+#endif
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
new file mode 100644 (file)
index 0000000..8bd7718
--- /dev/null
@@ -0,0 +1,786 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/iio/iio.h>
+
+#include "inv_icm42600.h"
+#include "inv_icm42600_buffer.h"
+#include "inv_icm42600_timestamp.h"
+
+static const struct regmap_range_cfg inv_icm42600_regmap_ranges[] = {
+       {
+               .name = "user banks",
+               .range_min = 0x0000,
+               .range_max = 0x4FFF,
+               .selector_reg = INV_ICM42600_REG_BANK_SEL,
+               .selector_mask = INV_ICM42600_BANK_SEL_MASK,
+               .selector_shift = 0,
+               .window_start = 0,
+               .window_len = 0x1000,
+       },
+};
+
+const struct regmap_config inv_icm42600_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = 0x4FFF,
+       .ranges = inv_icm42600_regmap_ranges,
+       .num_ranges = ARRAY_SIZE(inv_icm42600_regmap_ranges),
+};
+EXPORT_SYMBOL_GPL(inv_icm42600_regmap_config);
+
+struct inv_icm42600_hw {
+       uint8_t whoami;
+       const char *name;
+       const struct inv_icm42600_conf *conf;
+};
+
+/* chip initial default configuration */
+static const struct inv_icm42600_conf inv_icm42600_default_conf = {
+       .gyro = {
+               .mode = INV_ICM42600_SENSOR_MODE_OFF,
+               .fs = INV_ICM42600_GYRO_FS_2000DPS,
+               .odr = INV_ICM42600_ODR_50HZ,
+               .filter = INV_ICM42600_FILTER_BW_ODR_DIV_2,
+       },
+       .accel = {
+               .mode = INV_ICM42600_SENSOR_MODE_OFF,
+               .fs = INV_ICM42600_ACCEL_FS_16G,
+               .odr = INV_ICM42600_ODR_50HZ,
+               .filter = INV_ICM42600_FILTER_BW_ODR_DIV_2,
+       },
+       .temp_en = false,
+};
+
+static const struct inv_icm42600_hw inv_icm42600_hw[INV_CHIP_NB] = {
+       [INV_CHIP_ICM42600] = {
+               .whoami = INV_ICM42600_WHOAMI_ICM42600,
+               .name = "icm42600",
+               .conf = &inv_icm42600_default_conf,
+       },
+       [INV_CHIP_ICM42602] = {
+               .whoami = INV_ICM42600_WHOAMI_ICM42602,
+               .name = "icm42602",
+               .conf = &inv_icm42600_default_conf,
+       },
+       [INV_CHIP_ICM42605] = {
+               .whoami = INV_ICM42600_WHOAMI_ICM42605,
+               .name = "icm42605",
+               .conf = &inv_icm42600_default_conf,
+       },
+       [INV_CHIP_ICM42622] = {
+               .whoami = INV_ICM42600_WHOAMI_ICM42622,
+               .name = "icm42622",
+               .conf = &inv_icm42600_default_conf,
+       },
+};
+
+const struct iio_mount_matrix *
+inv_icm42600_get_mount_matrix(const struct iio_dev *indio_dev,
+                             const struct iio_chan_spec *chan)
+{
+       const struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+
+       return &st->orientation;
+}
+
+uint32_t inv_icm42600_odr_to_period(enum inv_icm42600_odr odr)
+{
+       static uint32_t odr_periods[INV_ICM42600_ODR_NB] = {
+               /* reserved values */
+               0, 0, 0,
+               /* 8kHz */
+               125000,
+               /* 4kHz */
+               250000,
+               /* 2kHz */
+               500000,
+               /* 1kHz */
+               1000000,
+               /* 200Hz */
+               5000000,
+               /* 100Hz */
+               10000000,
+               /* 50Hz */
+               20000000,
+               /* 25Hz */
+               40000000,
+               /* 12.5Hz */
+               80000000,
+               /* 6.25Hz */
+               160000000,
+               /* 3.125Hz */
+               320000000,
+               /* 1.5625Hz */
+               640000000,
+               /* 500Hz */
+               2000000,
+       };
+
+       return odr_periods[odr];
+}
+
+static int inv_icm42600_set_pwr_mgmt0(struct inv_icm42600_state *st,
+                                     enum inv_icm42600_sensor_mode gyro,
+                                     enum inv_icm42600_sensor_mode accel,
+                                     bool temp, unsigned int *sleep_ms)
+{
+       enum inv_icm42600_sensor_mode oldgyro = st->conf.gyro.mode;
+       enum inv_icm42600_sensor_mode oldaccel = st->conf.accel.mode;
+       bool oldtemp = st->conf.temp_en;
+       unsigned int sleepval;
+       unsigned int val;
+       int ret;
+
+       /* if nothing changed, exit */
+       if (gyro == oldgyro && accel == oldaccel && temp == oldtemp)
+               return 0;
+
+       val = INV_ICM42600_PWR_MGMT0_GYRO(gyro) |
+             INV_ICM42600_PWR_MGMT0_ACCEL(accel);
+       if (!temp)
+               val |= INV_ICM42600_PWR_MGMT0_TEMP_DIS;
+       ret = regmap_write(st->map, INV_ICM42600_REG_PWR_MGMT0, val);
+       if (ret)
+               return ret;
+
+       st->conf.gyro.mode = gyro;
+       st->conf.accel.mode = accel;
+       st->conf.temp_en = temp;
+
+       /* compute required wait time for sensors to stabilize */
+       sleepval = 0;
+       /* temperature stabilization time */
+       if (temp && !oldtemp) {
+               if (sleepval < INV_ICM42600_TEMP_STARTUP_TIME_MS)
+                       sleepval = INV_ICM42600_TEMP_STARTUP_TIME_MS;
+       }
+       /* accel startup time */
+       if (accel != oldaccel && oldaccel == INV_ICM42600_SENSOR_MODE_OFF) {
+               /* block any register write for at least 200 Âµs */
+               usleep_range(200, 300);
+               if (sleepval < INV_ICM42600_ACCEL_STARTUP_TIME_MS)
+                       sleepval = INV_ICM42600_ACCEL_STARTUP_TIME_MS;
+       }
+       if (gyro != oldgyro) {
+               /* gyro startup time */
+               if (oldgyro == INV_ICM42600_SENSOR_MODE_OFF) {
+                       /* block any register write for at least 200 Âµs */
+                       usleep_range(200, 300);
+                       if (sleepval < INV_ICM42600_GYRO_STARTUP_TIME_MS)
+                               sleepval = INV_ICM42600_GYRO_STARTUP_TIME_MS;
+               /* gyro stop time */
+               } else if (gyro == INV_ICM42600_SENSOR_MODE_OFF) {
+                       if (sleepval < INV_ICM42600_GYRO_STOP_TIME_MS)
+                               sleepval =  INV_ICM42600_GYRO_STOP_TIME_MS;
+               }
+       }
+
+       /* deferred sleep value if sleep pointer is provided or direct sleep */
+       if (sleep_ms)
+               *sleep_ms = sleepval;
+       else if (sleepval)
+               msleep(sleepval);
+
+       return 0;
+}
+
+int inv_icm42600_set_accel_conf(struct inv_icm42600_state *st,
+                               struct inv_icm42600_sensor_conf *conf,
+                               unsigned int *sleep_ms)
+{
+       struct inv_icm42600_sensor_conf *oldconf = &st->conf.accel;
+       unsigned int val;
+       int ret;
+
+       /* Sanitize missing values with current values */
+       if (conf->mode < 0)
+               conf->mode = oldconf->mode;
+       if (conf->fs < 0)
+               conf->fs = oldconf->fs;
+       if (conf->odr < 0)
+               conf->odr = oldconf->odr;
+       if (conf->filter < 0)
+               conf->filter = oldconf->filter;
+
+       /* set ACCEL_CONFIG0 register (accel fullscale & odr) */
+       if (conf->fs != oldconf->fs || conf->odr != oldconf->odr) {
+               val = INV_ICM42600_ACCEL_CONFIG0_FS(conf->fs) |
+                     INV_ICM42600_ACCEL_CONFIG0_ODR(conf->odr);
+               ret = regmap_write(st->map, INV_ICM42600_REG_ACCEL_CONFIG0, val);
+               if (ret)
+                       return ret;
+               oldconf->fs = conf->fs;
+               oldconf->odr = conf->odr;
+       }
+
+       /* set GYRO_ACCEL_CONFIG0 register (accel filter) */
+       if (conf->filter != oldconf->filter) {
+               val = INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(conf->filter) |
+                     INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(st->conf.gyro.filter);
+               ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_ACCEL_CONFIG0, val);
+               if (ret)
+                       return ret;
+               oldconf->filter = conf->filter;
+       }
+
+       /* set PWR_MGMT0 register (accel sensor mode) */
+       return inv_icm42600_set_pwr_mgmt0(st, st->conf.gyro.mode, conf->mode,
+                                         st->conf.temp_en, sleep_ms);
+}
+
+int inv_icm42600_set_gyro_conf(struct inv_icm42600_state *st,
+                              struct inv_icm42600_sensor_conf *conf,
+                              unsigned int *sleep_ms)
+{
+       struct inv_icm42600_sensor_conf *oldconf = &st->conf.gyro;
+       unsigned int val;
+       int ret;
+
+       /* sanitize missing values with current values */
+       if (conf->mode < 0)
+               conf->mode = oldconf->mode;
+       if (conf->fs < 0)
+               conf->fs = oldconf->fs;
+       if (conf->odr < 0)
+               conf->odr = oldconf->odr;
+       if (conf->filter < 0)
+               conf->filter = oldconf->filter;
+
+       /* set GYRO_CONFIG0 register (gyro fullscale & odr) */
+       if (conf->fs != oldconf->fs || conf->odr != oldconf->odr) {
+               val = INV_ICM42600_GYRO_CONFIG0_FS(conf->fs) |
+                     INV_ICM42600_GYRO_CONFIG0_ODR(conf->odr);
+               ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_CONFIG0, val);
+               if (ret)
+                       return ret;
+               oldconf->fs = conf->fs;
+               oldconf->odr = conf->odr;
+       }
+
+       /* set GYRO_ACCEL_CONFIG0 register (gyro filter) */
+       if (conf->filter != oldconf->filter) {
+               val = INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(st->conf.accel.filter) |
+                     INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(conf->filter);
+               ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_ACCEL_CONFIG0, val);
+               if (ret)
+                       return ret;
+               oldconf->filter = conf->filter;
+       }
+
+       /* set PWR_MGMT0 register (gyro sensor mode) */
+       return inv_icm42600_set_pwr_mgmt0(st, conf->mode, st->conf.accel.mode,
+                                         st->conf.temp_en, sleep_ms);
+
+       return 0;
+}
+
+int inv_icm42600_set_temp_conf(struct inv_icm42600_state *st, bool enable,
+                              unsigned int *sleep_ms)
+{
+       return inv_icm42600_set_pwr_mgmt0(st, st->conf.gyro.mode,
+                                         st->conf.accel.mode, enable,
+                                         sleep_ms);
+}
+
+int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg,
+                            unsigned int writeval, unsigned int *readval)
+{
+       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+       int ret;
+
+       mutex_lock(&st->lock);
+
+       if (readval)
+               ret = regmap_read(st->map, reg, readval);
+       else
+               ret = regmap_write(st->map, reg, writeval);
+
+       mutex_unlock(&st->lock);
+
+       return ret;
+}
+
+static int inv_icm42600_set_conf(struct inv_icm42600_state *st,
+                                const struct inv_icm42600_conf *conf)
+{
+       unsigned int val;
+       int ret;
+
+       /* set PWR_MGMT0 register (gyro & accel sensor mode, temp enabled) */
+       val = INV_ICM42600_PWR_MGMT0_GYRO(conf->gyro.mode) |
+             INV_ICM42600_PWR_MGMT0_ACCEL(conf->accel.mode);
+       if (!conf->temp_en)
+               val |= INV_ICM42600_PWR_MGMT0_TEMP_DIS;
+       ret = regmap_write(st->map, INV_ICM42600_REG_PWR_MGMT0, val);
+       if (ret)
+               return ret;
+
+       /* set GYRO_CONFIG0 register (gyro fullscale & odr) */
+       val = INV_ICM42600_GYRO_CONFIG0_FS(conf->gyro.fs) |
+             INV_ICM42600_GYRO_CONFIG0_ODR(conf->gyro.odr);
+       ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_CONFIG0, val);
+       if (ret)
+               return ret;
+
+       /* set ACCEL_CONFIG0 register (accel fullscale & odr) */
+       val = INV_ICM42600_ACCEL_CONFIG0_FS(conf->accel.fs) |
+             INV_ICM42600_ACCEL_CONFIG0_ODR(conf->accel.odr);
+       ret = regmap_write(st->map, INV_ICM42600_REG_ACCEL_CONFIG0, val);
+       if (ret)
+               return ret;
+
+       /* set GYRO_ACCEL_CONFIG0 register (gyro & accel filters) */
+       val = INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(conf->accel.filter) |
+             INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(conf->gyro.filter);
+       ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_ACCEL_CONFIG0, val);
+       if (ret)
+               return ret;
+
+       /* update internal conf */
+       st->conf = *conf;
+
+       return 0;
+}
+
+/**
+ *  inv_icm42600_setup() - check and setup chip
+ *  @st:       driver internal state
+ *  @bus_setup:        callback for setting up bus specific registers
+ *
+ *  Returns 0 on success, a negative error code otherwise.
+ */
+static int inv_icm42600_setup(struct inv_icm42600_state *st,
+                             inv_icm42600_bus_setup bus_setup)
+{
+       const struct inv_icm42600_hw *hw = &inv_icm42600_hw[st->chip];
+       const struct device *dev = regmap_get_device(st->map);
+       unsigned int val;
+       int ret;
+
+       /* check chip self-identification value */
+       ret = regmap_read(st->map, INV_ICM42600_REG_WHOAMI, &val);
+       if (ret)
+               return ret;
+       if (val != hw->whoami) {
+               dev_err(dev, "invalid whoami %#02x expected %#02x (%s)\n",
+                       val, hw->whoami, hw->name);
+               return -ENODEV;
+       }
+       st->name = hw->name;
+
+       /* reset to make sure previous state are not there */
+       ret = regmap_write(st->map, INV_ICM42600_REG_DEVICE_CONFIG,
+                          INV_ICM42600_DEVICE_CONFIG_SOFT_RESET);
+       if (ret)
+               return ret;
+       msleep(INV_ICM42600_RESET_TIME_MS);
+
+       ret = regmap_read(st->map, INV_ICM42600_REG_INT_STATUS, &val);
+       if (ret)
+               return ret;
+       if (!(val & INV_ICM42600_INT_STATUS_RESET_DONE)) {
+               dev_err(dev, "reset error, reset done bit not set\n");
+               return -ENODEV;
+       }
+
+       /* set chip bus configuration */
+       ret = bus_setup(st);
+       if (ret)
+               return ret;
+
+       /* sensor data in big-endian (default) */
+       ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0,
+                                INV_ICM42600_INTF_CONFIG0_SENSOR_DATA_ENDIAN,
+                                INV_ICM42600_INTF_CONFIG0_SENSOR_DATA_ENDIAN);
+       if (ret)
+               return ret;
+
+       return inv_icm42600_set_conf(st, hw->conf);
+}
+
+static irqreturn_t inv_icm42600_irq_timestamp(int irq, void *_data)
+{
+       struct inv_icm42600_state *st = _data;
+
+       st->timestamp.gyro = iio_get_time_ns(st->indio_gyro);
+       st->timestamp.accel = iio_get_time_ns(st->indio_accel);
+
+       return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t inv_icm42600_irq_handler(int irq, void *_data)
+{
+       struct inv_icm42600_state *st = _data;
+       struct device *dev = regmap_get_device(st->map);
+       unsigned int status;
+       int ret;
+
+       mutex_lock(&st->lock);
+
+       ret = regmap_read(st->map, INV_ICM42600_REG_INT_STATUS, &status);
+       if (ret)
+               goto out_unlock;
+
+       /* FIFO full */
+       if (status & INV_ICM42600_INT_STATUS_FIFO_FULL)
+               dev_warn(dev, "FIFO full data lost!\n");
+
+       /* FIFO threshold reached */
+       if (status & INV_ICM42600_INT_STATUS_FIFO_THS) {
+               ret = inv_icm42600_buffer_fifo_read(st, 0);
+               if (ret) {
+                       dev_err(dev, "FIFO read error %d\n", ret);
+                       goto out_unlock;
+               }
+               ret = inv_icm42600_buffer_fifo_parse(st);
+               if (ret)
+                       dev_err(dev, "FIFO parsing error %d\n", ret);
+       }
+
+out_unlock:
+       mutex_unlock(&st->lock);
+       return IRQ_HANDLED;
+}
+
+/**
+ * inv_icm42600_irq_init() - initialize int pin and interrupt handler
+ * @st:                driver internal state
+ * @irq:       irq number
+ * @irq_type:  irq trigger type
+ * @open_drain:        true if irq is open drain, false for push-pull
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ */
+static int inv_icm42600_irq_init(struct inv_icm42600_state *st, int irq,
+                                int irq_type, bool open_drain)
+{
+       struct device *dev = regmap_get_device(st->map);
+       unsigned int val;
+       int ret;
+
+       /* configure INT1 interrupt: default is active low on edge */
+       switch (irq_type) {
+       case IRQF_TRIGGER_RISING:
+       case IRQF_TRIGGER_HIGH:
+               val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_HIGH;
+               break;
+       default:
+               val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_LOW;
+               break;
+       }
+
+       switch (irq_type) {
+       case IRQF_TRIGGER_LOW:
+       case IRQF_TRIGGER_HIGH:
+               val |= INV_ICM42600_INT_CONFIG_INT1_LATCHED;
+               break;
+       default:
+               break;
+       }
+
+       if (!open_drain)
+               val |= INV_ICM42600_INT_CONFIG_INT1_PUSH_PULL;
+
+       ret = regmap_write(st->map, INV_ICM42600_REG_INT_CONFIG, val);
+       if (ret)
+               return ret;
+
+       /* Deassert async reset for proper INT pin operation (cf datasheet) */
+       ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_CONFIG1,
+                                INV_ICM42600_INT_CONFIG1_ASYNC_RESET, 0);
+       if (ret)
+               return ret;
+
+       return devm_request_threaded_irq(dev, irq, inv_icm42600_irq_timestamp,
+                                        inv_icm42600_irq_handler, irq_type,
+                                        "inv_icm42600", st);
+}
+
+static int inv_icm42600_enable_regulator_vddio(struct inv_icm42600_state *st)
+{
+       int ret;
+
+       ret = regulator_enable(st->vddio_supply);
+       if (ret)
+               return ret;
+
+       /* wait a little for supply ramp */
+       usleep_range(3000, 4000);
+
+       return 0;
+}
+
+static void inv_icm42600_disable_vdd_reg(void *_data)
+{
+       struct inv_icm42600_state *st = _data;
+       const struct device *dev = regmap_get_device(st->map);
+       int ret;
+
+       ret = regulator_disable(st->vdd_supply);
+       if (ret)
+               dev_err(dev, "failed to disable vdd error %d\n", ret);
+}
+
+static void inv_icm42600_disable_vddio_reg(void *_data)
+{
+       struct inv_icm42600_state *st = _data;
+       const struct device *dev = regmap_get_device(st->map);
+       int ret;
+
+       ret = regulator_disable(st->vddio_supply);
+       if (ret)
+               dev_err(dev, "failed to disable vddio error %d\n", ret);
+}
+
+static void inv_icm42600_disable_pm(void *_data)
+{
+       struct device *dev = _data;
+
+       pm_runtime_put_sync(dev);
+       pm_runtime_disable(dev);
+}
+
+int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq,
+                           inv_icm42600_bus_setup bus_setup)
+{
+       struct device *dev = regmap_get_device(regmap);
+       struct inv_icm42600_state *st;
+       struct irq_data *irq_desc;
+       int irq_type;
+       bool open_drain;
+       int ret;
+
+       if (chip < 0 || chip >= INV_CHIP_NB) {
+               dev_err(dev, "invalid chip = %d\n", chip);
+               return -ENODEV;
+       }
+
+       /* get irq properties, set trigger falling by default */
+       irq_desc = irq_get_irq_data(irq);
+       if (!irq_desc) {
+               dev_err(dev, "could not find IRQ %d\n", irq);
+               return -EINVAL;
+       }
+
+       irq_type = irqd_get_trigger_type(irq_desc);
+       if (!irq_type)
+               irq_type = IRQF_TRIGGER_FALLING;
+
+       open_drain = device_property_read_bool(dev, "drive-open-drain");
+
+       st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
+       if (!st)
+               return -ENOMEM;
+
+       dev_set_drvdata(dev, st);
+       mutex_init(&st->lock);
+       st->chip = chip;
+       st->map = regmap;
+
+       ret = iio_read_mount_matrix(dev, "mount-matrix", &st->orientation);
+       if (ret) {
+               dev_err(dev, "failed to retrieve mounting matrix %d\n", ret);
+               return ret;
+       }
+
+       st->vdd_supply = devm_regulator_get(dev, "vdd");
+       if (IS_ERR(st->vdd_supply))
+               return PTR_ERR(st->vdd_supply);
+
+       st->vddio_supply = devm_regulator_get(dev, "vddio");
+       if (IS_ERR(st->vddio_supply))
+               return PTR_ERR(st->vddio_supply);
+
+       ret = regulator_enable(st->vdd_supply);
+       if (ret)
+               return ret;
+       msleep(INV_ICM42600_POWER_UP_TIME_MS);
+
+       ret = devm_add_action_or_reset(dev, inv_icm42600_disable_vdd_reg, st);
+       if (ret)
+               return ret;
+
+       ret = inv_icm42600_enable_regulator_vddio(st);
+       if (ret)
+               return ret;
+
+       ret = devm_add_action_or_reset(dev, inv_icm42600_disable_vddio_reg, st);
+       if (ret)
+               return ret;
+
+       /* setup chip registers */
+       ret = inv_icm42600_setup(st, bus_setup);
+       if (ret)
+               return ret;
+
+       ret = inv_icm42600_timestamp_setup(st);
+       if (ret)
+               return ret;
+
+       ret = inv_icm42600_buffer_init(st);
+       if (ret)
+               return ret;
+
+       st->indio_gyro = inv_icm42600_gyro_init(st);
+       if (IS_ERR(st->indio_gyro))
+               return PTR_ERR(st->indio_gyro);
+
+       st->indio_accel = inv_icm42600_accel_init(st);
+       if (IS_ERR(st->indio_accel))
+               return PTR_ERR(st->indio_accel);
+
+       ret = inv_icm42600_irq_init(st, irq, irq_type, open_drain);
+       if (ret)
+               return ret;
+
+       /* setup runtime power management */
+       ret = pm_runtime_set_active(dev);
+       if (ret)
+               return ret;
+       pm_runtime_get_noresume(dev);
+       pm_runtime_enable(dev);
+       pm_runtime_set_autosuspend_delay(dev, INV_ICM42600_SUSPEND_DELAY_MS);
+       pm_runtime_use_autosuspend(dev);
+       pm_runtime_put(dev);
+
+       return devm_add_action_or_reset(dev, inv_icm42600_disable_pm, dev);
+}
+EXPORT_SYMBOL_GPL(inv_icm42600_core_probe);
+
+/*
+ * Suspend saves sensors state and turns everything off.
+ * Check first if runtime suspend has not already done the job.
+ */
+static int __maybe_unused inv_icm42600_suspend(struct device *dev)
+{
+       struct inv_icm42600_state *st = dev_get_drvdata(dev);
+       int ret;
+
+       mutex_lock(&st->lock);
+
+       st->suspended.gyro = st->conf.gyro.mode;
+       st->suspended.accel = st->conf.accel.mode;
+       st->suspended.temp = st->conf.temp_en;
+       if (pm_runtime_suspended(dev)) {
+               ret = 0;
+               goto out_unlock;
+       }
+
+       /* disable FIFO data streaming */
+       if (st->fifo.on) {
+               ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG,
+                                  INV_ICM42600_FIFO_CONFIG_BYPASS);
+               if (ret)
+                       goto out_unlock;
+       }
+
+       ret = inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF,
+                                        INV_ICM42600_SENSOR_MODE_OFF, false,
+                                        NULL);
+       if (ret)
+               goto out_unlock;
+
+       regulator_disable(st->vddio_supply);
+
+out_unlock:
+       mutex_unlock(&st->lock);
+       return ret;
+}
+
+/*
+ * System resume gets the system back on and restores the sensors state.
+ * Manually put runtime power management in system active state.
+ */
+static int __maybe_unused inv_icm42600_resume(struct device *dev)
+{
+       struct inv_icm42600_state *st = dev_get_drvdata(dev);
+       int ret;
+
+       mutex_lock(&st->lock);
+
+       ret = inv_icm42600_enable_regulator_vddio(st);
+       if (ret)
+               goto out_unlock;
+
+       pm_runtime_disable(dev);
+       pm_runtime_set_active(dev);
+       pm_runtime_enable(dev);
+
+       /* restore sensors state */
+       ret = inv_icm42600_set_pwr_mgmt0(st, st->suspended.gyro,
+                                        st->suspended.accel,
+                                        st->suspended.temp, NULL);
+       if (ret)
+               goto out_unlock;
+
+       /* restore FIFO data streaming */
+       if (st->fifo.on)
+               ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG,
+                                  INV_ICM42600_FIFO_CONFIG_STREAM);
+
+out_unlock:
+       mutex_unlock(&st->lock);
+       return ret;
+}
+
+/* Runtime suspend will turn off sensors that are enabled by iio devices. */
+static int __maybe_unused inv_icm42600_runtime_suspend(struct device *dev)
+{
+       struct inv_icm42600_state *st = dev_get_drvdata(dev);
+       int ret;
+
+       mutex_lock(&st->lock);
+
+       /* disable all sensors */
+       ret = inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF,
+                                        INV_ICM42600_SENSOR_MODE_OFF, false,
+                                        NULL);
+       if (ret)
+               goto error_unlock;
+
+       regulator_disable(st->vddio_supply);
+
+error_unlock:
+       mutex_unlock(&st->lock);
+       return ret;
+}
+
+/* Sensors are enabled by iio devices, no need to turn them back on here. */
+static int __maybe_unused inv_icm42600_runtime_resume(struct device *dev)
+{
+       struct inv_icm42600_state *st = dev_get_drvdata(dev);
+       int ret;
+
+       mutex_lock(&st->lock);
+
+       ret = inv_icm42600_enable_regulator_vddio(st);
+
+       mutex_unlock(&st->lock);
+       return ret;
+}
+
+const struct dev_pm_ops inv_icm42600_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(inv_icm42600_suspend, inv_icm42600_resume)
+       SET_RUNTIME_PM_OPS(inv_icm42600_runtime_suspend,
+                          inv_icm42600_runtime_resume, NULL)
+};
+EXPORT_SYMBOL_GPL(inv_icm42600_pm_ops);
+
+MODULE_AUTHOR("InvenSense, Inc.");
+MODULE_DESCRIPTION("InvenSense ICM-426xx device driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
new file mode 100644 (file)
index 0000000..aee7b9f
--- /dev/null
@@ -0,0 +1,798 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/delay.h>
+#include <linux/math64.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/kfifo_buf.h>
+
+#include "inv_icm42600.h"
+#include "inv_icm42600_temp.h"
+#include "inv_icm42600_buffer.h"
+#include "inv_icm42600_timestamp.h"
+
+#define INV_ICM42600_GYRO_CHAN(_modifier, _index, _ext_info)           \
+       {                                                               \
+               .type = IIO_ANGL_VEL,                                   \
+               .modified = 1,                                          \
+               .channel2 = _modifier,                                  \
+               .info_mask_separate =                                   \
+                       BIT(IIO_CHAN_INFO_RAW) |                        \
+                       BIT(IIO_CHAN_INFO_CALIBBIAS),                   \
+               .info_mask_shared_by_type =                             \
+                       BIT(IIO_CHAN_INFO_SCALE),                       \
+               .info_mask_shared_by_type_available =                   \
+                       BIT(IIO_CHAN_INFO_SCALE) |                      \
+                       BIT(IIO_CHAN_INFO_CALIBBIAS),                   \
+               .info_mask_shared_by_all =                              \
+                       BIT(IIO_CHAN_INFO_SAMP_FREQ),                   \
+               .info_mask_shared_by_all_available =                    \
+                       BIT(IIO_CHAN_INFO_SAMP_FREQ),                   \
+               .scan_index = _index,                                   \
+               .scan_type = {                                          \
+                       .sign = 's',                                    \
+                       .realbits = 16,                                 \
+                       .storagebits = 16,                              \
+                       .endianness = IIO_BE,                           \
+               },                                                      \
+               .ext_info = _ext_info,                                  \
+       }
+
+enum inv_icm42600_gyro_scan {
+       INV_ICM42600_GYRO_SCAN_X,
+       INV_ICM42600_GYRO_SCAN_Y,
+       INV_ICM42600_GYRO_SCAN_Z,
+       INV_ICM42600_GYRO_SCAN_TEMP,
+       INV_ICM42600_GYRO_SCAN_TIMESTAMP,
+};
+
+static const struct iio_chan_spec_ext_info inv_icm42600_gyro_ext_infos[] = {
+       IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, inv_icm42600_get_mount_matrix),
+       {},
+};
+
+static const struct iio_chan_spec inv_icm42600_gyro_channels[] = {
+       INV_ICM42600_GYRO_CHAN(IIO_MOD_X, INV_ICM42600_GYRO_SCAN_X,
+                              inv_icm42600_gyro_ext_infos),
+       INV_ICM42600_GYRO_CHAN(IIO_MOD_Y, INV_ICM42600_GYRO_SCAN_Y,
+                              inv_icm42600_gyro_ext_infos),
+       INV_ICM42600_GYRO_CHAN(IIO_MOD_Z, INV_ICM42600_GYRO_SCAN_Z,
+                              inv_icm42600_gyro_ext_infos),
+       INV_ICM42600_TEMP_CHAN(INV_ICM42600_GYRO_SCAN_TEMP),
+       IIO_CHAN_SOFT_TIMESTAMP(INV_ICM42600_GYRO_SCAN_TIMESTAMP),
+};
+
+/*
+ * IIO buffer data: size must be a power of 2 and timestamp aligned
+ * 16 bytes: 6 bytes angular velocity, 2 bytes temperature, 8 bytes timestamp
+ */
+struct inv_icm42600_gyro_buffer {
+       struct inv_icm42600_fifo_sensor_data gyro;
+       int16_t temp;
+       int64_t timestamp __aligned(8);
+};
+
+#define INV_ICM42600_SCAN_MASK_GYRO_3AXIS                              \
+       (BIT(INV_ICM42600_GYRO_SCAN_X) |                                \
+       BIT(INV_ICM42600_GYRO_SCAN_Y) |                                 \
+       BIT(INV_ICM42600_GYRO_SCAN_Z))
+
+#define INV_ICM42600_SCAN_MASK_TEMP    BIT(INV_ICM42600_GYRO_SCAN_TEMP)
+
+static const unsigned long inv_icm42600_gyro_scan_masks[] = {
+       /* 3-axis gyro + temperature */
+       INV_ICM42600_SCAN_MASK_GYRO_3AXIS | INV_ICM42600_SCAN_MASK_TEMP,
+       0,
+};
+
+/* enable gyroscope sensor and FIFO write */
+static int inv_icm42600_gyro_update_scan_mode(struct iio_dev *indio_dev,
+                                             const unsigned long *scan_mask)
+{
+       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+       struct inv_icm42600_timestamp *ts = iio_priv(indio_dev);
+       struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
+       unsigned int fifo_en = 0;
+       unsigned int sleep_gyro = 0;
+       unsigned int sleep_temp = 0;
+       unsigned int sleep;
+       int ret;
+
+       mutex_lock(&st->lock);
+
+       if (*scan_mask & INV_ICM42600_SCAN_MASK_TEMP) {
+               /* enable temp sensor */
+               ret = inv_icm42600_set_temp_conf(st, true, &sleep_temp);
+               if (ret)
+                       goto out_unlock;
+               fifo_en |= INV_ICM42600_SENSOR_TEMP;
+       }
+
+       if (*scan_mask & INV_ICM42600_SCAN_MASK_GYRO_3AXIS) {
+               /* enable gyro sensor */
+               conf.mode = INV_ICM42600_SENSOR_MODE_LOW_NOISE;
+               ret = inv_icm42600_set_gyro_conf(st, &conf, &sleep_gyro);
+               if (ret)
+                       goto out_unlock;
+               fifo_en |= INV_ICM42600_SENSOR_GYRO;
+       }
+
+       /* update data FIFO write */
+       inv_icm42600_timestamp_apply_odr(ts, 0, 0, 0);
+       ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en);
+       if (ret)
+               goto out_unlock;
+
+       ret = inv_icm42600_buffer_update_watermark(st);
+
+out_unlock:
+       mutex_unlock(&st->lock);
+       /* sleep maximum required time */
+       if (sleep_gyro > sleep_temp)
+               sleep = sleep_gyro;
+       else
+               sleep = sleep_temp;
+       if (sleep)
+               msleep(sleep);
+       return ret;
+}
+
+static int inv_icm42600_gyro_read_sensor(struct inv_icm42600_state *st,
+                                        struct iio_chan_spec const *chan,
+                                        int16_t *val)
+{
+       struct device *dev = regmap_get_device(st->map);
+       struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
+       unsigned int reg;
+       __be16 *data;
+       int ret;
+
+       if (chan->type != IIO_ANGL_VEL)
+               return -EINVAL;
+
+       switch (chan->channel2) {
+       case IIO_MOD_X:
+               reg = INV_ICM42600_REG_GYRO_DATA_X;
+               break;
+       case IIO_MOD_Y:
+               reg = INV_ICM42600_REG_GYRO_DATA_Y;
+               break;
+       case IIO_MOD_Z:
+               reg = INV_ICM42600_REG_GYRO_DATA_Z;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       pm_runtime_get_sync(dev);
+       mutex_lock(&st->lock);
+
+       /* enable gyro sensor */
+       conf.mode = INV_ICM42600_SENSOR_MODE_LOW_NOISE;
+       ret = inv_icm42600_set_gyro_conf(st, &conf, NULL);
+       if (ret)
+               goto exit;
+
+       /* read gyro register data */
+       data = (__be16 *)&st->buffer[0];
+       ret = regmap_bulk_read(st->map, reg, data, sizeof(*data));
+       if (ret)
+               goto exit;
+
+       *val = (int16_t)be16_to_cpup(data);
+       if (*val == INV_ICM42600_DATA_INVALID)
+               ret = -EINVAL;
+exit:
+       mutex_unlock(&st->lock);
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
+       return ret;
+}
+
+/* IIO format int + nano */
+static const int inv_icm42600_gyro_scale[] = {
+       /* +/- 2000dps => 0.001065264 rad/s */
+       [2 * INV_ICM42600_GYRO_FS_2000DPS] = 0,
+       [2 * INV_ICM42600_GYRO_FS_2000DPS + 1] = 1065264,
+       /* +/- 1000dps => 0.000532632 rad/s */
+       [2 * INV_ICM42600_GYRO_FS_1000DPS] = 0,
+       [2 * INV_ICM42600_GYRO_FS_1000DPS + 1] = 532632,
+       /* +/- 500dps => 0.000266316 rad/s */
+       [2 * INV_ICM42600_GYRO_FS_500DPS] = 0,
+       [2 * INV_ICM42600_GYRO_FS_500DPS + 1] = 266316,
+       /* +/- 250dps => 0.000133158 rad/s */
+       [2 * INV_ICM42600_GYRO_FS_250DPS] = 0,
+       [2 * INV_ICM42600_GYRO_FS_250DPS + 1] = 133158,
+       /* +/- 125dps => 0.000066579 rad/s */
+       [2 * INV_ICM42600_GYRO_FS_125DPS] = 0,
+       [2 * INV_ICM42600_GYRO_FS_125DPS + 1] = 66579,
+       /* +/- 62.5dps => 0.000033290 rad/s */
+       [2 * INV_ICM42600_GYRO_FS_62_5DPS] = 0,
+       [2 * INV_ICM42600_GYRO_FS_62_5DPS + 1] = 33290,
+       /* +/- 31.25dps => 0.000016645 rad/s */
+       [2 * INV_ICM42600_GYRO_FS_31_25DPS] = 0,
+       [2 * INV_ICM42600_GYRO_FS_31_25DPS + 1] = 16645,
+       /* +/- 15.625dps => 0.000008322 rad/s */
+       [2 * INV_ICM42600_GYRO_FS_15_625DPS] = 0,
+       [2 * INV_ICM42600_GYRO_FS_15_625DPS + 1] = 8322,
+};
+
+static int inv_icm42600_gyro_read_scale(struct inv_icm42600_state *st,
+                                       int *val, int *val2)
+{
+       unsigned int idx;
+
+       idx = st->conf.gyro.fs;
+
+       *val = inv_icm42600_gyro_scale[2 * idx];
+       *val2 = inv_icm42600_gyro_scale[2 * idx + 1];
+       return IIO_VAL_INT_PLUS_NANO;
+}
+
+static int inv_icm42600_gyro_write_scale(struct inv_icm42600_state *st,
+                                        int val, int val2)
+{
+       struct device *dev = regmap_get_device(st->map);
+       unsigned int idx;
+       struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
+       int ret;
+
+       for (idx = 0; idx < ARRAY_SIZE(inv_icm42600_gyro_scale); idx += 2) {
+               if (val == inv_icm42600_gyro_scale[idx] &&
+                   val2 == inv_icm42600_gyro_scale[idx + 1])
+                       break;
+       }
+       if (idx >= ARRAY_SIZE(inv_icm42600_gyro_scale))
+               return -EINVAL;
+
+       conf.fs = idx / 2;
+
+       pm_runtime_get_sync(dev);
+       mutex_lock(&st->lock);
+
+       ret = inv_icm42600_set_gyro_conf(st, &conf, NULL);
+
+       mutex_unlock(&st->lock);
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
+
+       return ret;
+}
+
+/* IIO format int + micro */
+static const int inv_icm42600_gyro_odr[] = {
+       /* 12.5Hz */
+       12, 500000,
+       /* 25Hz */
+       25, 0,
+       /* 50Hz */
+       50, 0,
+       /* 100Hz */
+       100, 0,
+       /* 200Hz */
+       200, 0,
+       /* 1kHz */
+       1000, 0,
+       /* 2kHz */
+       2000, 0,
+       /* 4kHz */
+       4000, 0,
+};
+
+static const int inv_icm42600_gyro_odr_conv[] = {
+       INV_ICM42600_ODR_12_5HZ,
+       INV_ICM42600_ODR_25HZ,
+       INV_ICM42600_ODR_50HZ,
+       INV_ICM42600_ODR_100HZ,
+       INV_ICM42600_ODR_200HZ,
+       INV_ICM42600_ODR_1KHZ_LN,
+       INV_ICM42600_ODR_2KHZ_LN,
+       INV_ICM42600_ODR_4KHZ_LN,
+};
+
+static int inv_icm42600_gyro_read_odr(struct inv_icm42600_state *st,
+                                     int *val, int *val2)
+{
+       unsigned int odr;
+       unsigned int i;
+
+       odr = st->conf.gyro.odr;
+
+       for (i = 0; i < ARRAY_SIZE(inv_icm42600_gyro_odr_conv); ++i) {
+               if (inv_icm42600_gyro_odr_conv[i] == odr)
+                       break;
+       }
+       if (i >= ARRAY_SIZE(inv_icm42600_gyro_odr_conv))
+               return -EINVAL;
+
+       *val = inv_icm42600_gyro_odr[2 * i];
+       *val2 = inv_icm42600_gyro_odr[2 * i + 1];
+
+       return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static int inv_icm42600_gyro_write_odr(struct iio_dev *indio_dev,
+                                      int val, int val2)
+{
+       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+       struct inv_icm42600_timestamp *ts = iio_priv(indio_dev);
+       struct device *dev = regmap_get_device(st->map);
+       unsigned int idx;
+       struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
+       int ret;
+
+       for (idx = 0; idx < ARRAY_SIZE(inv_icm42600_gyro_odr); idx += 2) {
+               if (val == inv_icm42600_gyro_odr[idx] &&
+                   val2 == inv_icm42600_gyro_odr[idx + 1])
+                       break;
+       }
+       if (idx >= ARRAY_SIZE(inv_icm42600_gyro_odr))
+               return -EINVAL;
+
+       conf.odr = inv_icm42600_gyro_odr_conv[idx / 2];
+
+       pm_runtime_get_sync(dev);
+       mutex_lock(&st->lock);
+
+       ret = inv_icm42600_timestamp_update_odr(ts, inv_icm42600_odr_to_period(conf.odr),
+                                               iio_buffer_enabled(indio_dev));
+       if (ret)
+               goto out_unlock;
+
+       ret = inv_icm42600_set_gyro_conf(st, &conf, NULL);
+       if (ret)
+               goto out_unlock;
+       inv_icm42600_buffer_update_fifo_period(st);
+       inv_icm42600_buffer_update_watermark(st);
+
+out_unlock:
+       mutex_unlock(&st->lock);
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
+
+       return ret;
+}
+
+/*
+ * Calibration bias values, IIO range format int + nano.
+ * Value is limited to +/-64dps coded on 12 bits signed. Step is 1/32 dps.
+ */
+static int inv_icm42600_gyro_calibbias[] = {
+       -1, 117010721,          /* min: -1.117010721 rad/s */
+       0, 545415,              /* step: 0.000545415 rad/s */
+       1, 116465306,           /* max: 1.116465306 rad/s */
+};
+
+static int inv_icm42600_gyro_read_offset(struct inv_icm42600_state *st,
+                                        struct iio_chan_spec const *chan,
+                                        int *val, int *val2)
+{
+       struct device *dev = regmap_get_device(st->map);
+       int64_t val64;
+       int32_t bias;
+       unsigned int reg;
+       int16_t offset;
+       uint8_t data[2];
+       int ret;
+
+       if (chan->type != IIO_ANGL_VEL)
+               return -EINVAL;
+
+       switch (chan->channel2) {
+       case IIO_MOD_X:
+               reg = INV_ICM42600_REG_OFFSET_USER0;
+               break;
+       case IIO_MOD_Y:
+               reg = INV_ICM42600_REG_OFFSET_USER1;
+               break;
+       case IIO_MOD_Z:
+               reg = INV_ICM42600_REG_OFFSET_USER3;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       pm_runtime_get_sync(dev);
+       mutex_lock(&st->lock);
+
+       ret = regmap_bulk_read(st->map, reg, st->buffer, sizeof(data));
+       memcpy(data, st->buffer, sizeof(data));
+
+       mutex_unlock(&st->lock);
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
+       if (ret)
+               return ret;
+
+       /* 12 bits signed value */
+       switch (chan->channel2) {
+       case IIO_MOD_X:
+               offset = sign_extend32(((data[1] & 0x0F) << 8) | data[0], 11);
+               break;
+       case IIO_MOD_Y:
+               offset = sign_extend32(((data[0] & 0xF0) << 4) | data[1], 11);
+               break;
+       case IIO_MOD_Z:
+               offset = sign_extend32(((data[1] & 0x0F) << 8) | data[0], 11);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /*
+        * convert raw offset to dps then to rad/s
+        * 12 bits signed raw max 64 to dps: 64 / 2048
+        * dps to rad: Pi / 180
+        * result in nano (1000000000)
+        * (offset * 64 * Pi * 1000000000) / (2048 * 180)
+        */
+       val64 = (int64_t)offset * 64LL * 3141592653LL;
+       /* for rounding, add + or - divisor (2048 * 180) divided by 2 */
+       if (val64 >= 0)
+               val64 += 2048 * 180 / 2;
+       else
+               val64 -= 2048 * 180 / 2;
+       bias = div_s64(val64, 2048 * 180);
+       *val = bias / 1000000000L;
+       *val2 = bias % 1000000000L;
+
+       return IIO_VAL_INT_PLUS_NANO;
+}
+
+static int inv_icm42600_gyro_write_offset(struct inv_icm42600_state *st,
+                                         struct iio_chan_spec const *chan,
+                                         int val, int val2)
+{
+       struct device *dev = regmap_get_device(st->map);
+       int64_t val64, min, max;
+       unsigned int reg, regval;
+       int16_t offset;
+       int ret;
+
+       if (chan->type != IIO_ANGL_VEL)
+               return -EINVAL;
+
+       switch (chan->channel2) {
+       case IIO_MOD_X:
+               reg = INV_ICM42600_REG_OFFSET_USER0;
+               break;
+       case IIO_MOD_Y:
+               reg = INV_ICM42600_REG_OFFSET_USER1;
+               break;
+       case IIO_MOD_Z:
+               reg = INV_ICM42600_REG_OFFSET_USER3;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* inv_icm42600_gyro_calibbias: min - step - max in nano */
+       min = (int64_t)inv_icm42600_gyro_calibbias[0] * 1000000000LL +
+             (int64_t)inv_icm42600_gyro_calibbias[1];
+       max = (int64_t)inv_icm42600_gyro_calibbias[4] * 1000000000LL +
+             (int64_t)inv_icm42600_gyro_calibbias[5];
+       val64 = (int64_t)val * 1000000000LL + (int64_t)val2;
+       if (val64 < min || val64 > max)
+               return -EINVAL;
+
+       /*
+        * convert rad/s to dps then to raw value
+        * rad to dps: 180 / Pi
+        * dps to raw 12 bits signed, max 64: 2048 / 64
+        * val in nano (1000000000)
+        * val * 180 * 2048 / (Pi * 1000000000 * 64)
+        */
+       val64 = val64 * 180LL * 2048LL;
+       /* for rounding, add + or - divisor (3141592653 * 64) divided by 2 */
+       if (val64 >= 0)
+               val64 += 3141592653LL * 64LL / 2LL;
+       else
+               val64 -= 3141592653LL * 64LL / 2LL;
+       offset = div64_s64(val64, 3141592653LL * 64LL);
+
+       /* clamp value limited to 12 bits signed */
+       if (offset < -2048)
+               offset = -2048;
+       else if (offset > 2047)
+               offset = 2047;
+
+       pm_runtime_get_sync(dev);
+       mutex_lock(&st->lock);
+
+       switch (chan->channel2) {
+       case IIO_MOD_X:
+               /* OFFSET_USER1 register is shared */
+               ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER1,
+                                 &regval);
+               if (ret)
+                       goto out_unlock;
+               st->buffer[0] = offset & 0xFF;
+               st->buffer[1] = (regval & 0xF0) | ((offset & 0xF00) >> 8);
+               break;
+       case IIO_MOD_Y:
+               /* OFFSET_USER1 register is shared */
+               ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER1,
+                                 &regval);
+               if (ret)
+                       goto out_unlock;
+               st->buffer[0] = ((offset & 0xF00) >> 4) | (regval & 0x0F);
+               st->buffer[1] = offset & 0xFF;
+               break;
+       case IIO_MOD_Z:
+               /* OFFSET_USER4 register is shared */
+               ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER4,
+                                 &regval);
+               if (ret)
+                       goto out_unlock;
+               st->buffer[0] = offset & 0xFF;
+               st->buffer[1] = (regval & 0xF0) | ((offset & 0xF00) >> 8);
+               break;
+       default:
+               ret = -EINVAL;
+               goto out_unlock;
+       }
+
+       ret = regmap_bulk_write(st->map, reg, st->buffer, 2);
+
+out_unlock:
+       mutex_unlock(&st->lock);
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
+       return ret;
+}
+
+static int inv_icm42600_gyro_read_raw(struct iio_dev *indio_dev,
+                                     struct iio_chan_spec const *chan,
+                                     int *val, int *val2, long mask)
+{
+       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+       int16_t data;
+       int ret;
+
+       switch (chan->type) {
+       case IIO_ANGL_VEL:
+               break;
+       case IIO_TEMP:
+               return inv_icm42600_temp_read_raw(indio_dev, chan, val, val2, mask);
+       default:
+               return -EINVAL;
+       }
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               ret = iio_device_claim_direct_mode(indio_dev);
+               if (ret)
+                       return ret;
+               ret = inv_icm42600_gyro_read_sensor(st, chan, &data);
+               iio_device_release_direct_mode(indio_dev);
+               if (ret)
+                       return ret;
+               *val = data;
+               return IIO_VAL_INT;
+       case IIO_CHAN_INFO_SCALE:
+               return inv_icm42600_gyro_read_scale(st, val, val2);
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               return inv_icm42600_gyro_read_odr(st, val, val2);
+       case IIO_CHAN_INFO_CALIBBIAS:
+               return inv_icm42600_gyro_read_offset(st, chan, val, val2);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int inv_icm42600_gyro_read_avail(struct iio_dev *indio_dev,
+                                       struct iio_chan_spec const *chan,
+                                       const int **vals,
+                                       int *type, int *length, long mask)
+{
+       if (chan->type != IIO_ANGL_VEL)
+               return -EINVAL;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_SCALE:
+               *vals = inv_icm42600_gyro_scale;
+               *type = IIO_VAL_INT_PLUS_NANO;
+               *length = ARRAY_SIZE(inv_icm42600_gyro_scale);
+               return IIO_AVAIL_LIST;
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               *vals = inv_icm42600_gyro_odr;
+               *type = IIO_VAL_INT_PLUS_MICRO;
+               *length = ARRAY_SIZE(inv_icm42600_gyro_odr);
+               return IIO_AVAIL_LIST;
+       case IIO_CHAN_INFO_CALIBBIAS:
+               *vals = inv_icm42600_gyro_calibbias;
+               *type = IIO_VAL_INT_PLUS_NANO;
+               return IIO_AVAIL_RANGE;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int inv_icm42600_gyro_write_raw(struct iio_dev *indio_dev,
+                                      struct iio_chan_spec const *chan,
+                                      int val, int val2, long mask)
+{
+       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+       int ret;
+
+       if (chan->type != IIO_ANGL_VEL)
+               return -EINVAL;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_SCALE:
+               ret = iio_device_claim_direct_mode(indio_dev);
+               if (ret)
+                       return ret;
+               ret = inv_icm42600_gyro_write_scale(st, val, val2);
+               iio_device_release_direct_mode(indio_dev);
+               return ret;
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               return inv_icm42600_gyro_write_odr(indio_dev, val, val2);
+       case IIO_CHAN_INFO_CALIBBIAS:
+               ret = iio_device_claim_direct_mode(indio_dev);
+               if (ret)
+                       return ret;
+               ret = inv_icm42600_gyro_write_offset(st, chan, val, val2);
+               iio_device_release_direct_mode(indio_dev);
+               return ret;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int inv_icm42600_gyro_write_raw_get_fmt(struct iio_dev *indio_dev,
+                                              struct iio_chan_spec const *chan,
+                                              long mask)
+{
+       if (chan->type != IIO_ANGL_VEL)
+               return -EINVAL;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_SCALE:
+               return IIO_VAL_INT_PLUS_NANO;
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               return IIO_VAL_INT_PLUS_MICRO;
+       case IIO_CHAN_INFO_CALIBBIAS:
+               return IIO_VAL_INT_PLUS_NANO;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int inv_icm42600_gyro_hwfifo_set_watermark(struct iio_dev *indio_dev,
+                                                 unsigned int val)
+{
+       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+       int ret;
+
+       mutex_lock(&st->lock);
+
+       st->fifo.watermark.gyro = val;
+       ret = inv_icm42600_buffer_update_watermark(st);
+
+       mutex_unlock(&st->lock);
+
+       return ret;
+}
+
+static int inv_icm42600_gyro_hwfifo_flush(struct iio_dev *indio_dev,
+                                         unsigned int count)
+{
+       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+       int ret;
+
+       if (count == 0)
+               return 0;
+
+       mutex_lock(&st->lock);
+
+       ret = inv_icm42600_buffer_hwfifo_flush(st, count);
+       if (!ret)
+               ret = st->fifo.nb.gyro;
+
+       mutex_unlock(&st->lock);
+
+       return ret;
+}
+
+static const struct iio_info inv_icm42600_gyro_info = {
+       .read_raw = inv_icm42600_gyro_read_raw,
+       .read_avail = inv_icm42600_gyro_read_avail,
+       .write_raw = inv_icm42600_gyro_write_raw,
+       .write_raw_get_fmt = inv_icm42600_gyro_write_raw_get_fmt,
+       .debugfs_reg_access = inv_icm42600_debugfs_reg,
+       .update_scan_mode = inv_icm42600_gyro_update_scan_mode,
+       .hwfifo_set_watermark = inv_icm42600_gyro_hwfifo_set_watermark,
+       .hwfifo_flush_to_buffer = inv_icm42600_gyro_hwfifo_flush,
+};
+
+struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st)
+{
+       struct device *dev = regmap_get_device(st->map);
+       const char *name;
+       struct inv_icm42600_timestamp *ts;
+       struct iio_dev *indio_dev;
+       struct iio_buffer *buffer;
+       int ret;
+
+       name = devm_kasprintf(dev, GFP_KERNEL, "%s-gyro", st->name);
+       if (!name)
+               return ERR_PTR(-ENOMEM);
+
+       indio_dev = devm_iio_device_alloc(dev, sizeof(*ts));
+       if (!indio_dev)
+               return ERR_PTR(-ENOMEM);
+
+       buffer = devm_iio_kfifo_allocate(dev);
+       if (!buffer)
+               return ERR_PTR(-ENOMEM);
+
+       ts = iio_priv(indio_dev);
+       inv_icm42600_timestamp_init(ts, inv_icm42600_odr_to_period(st->conf.gyro.odr));
+
+       iio_device_set_drvdata(indio_dev, st);
+       indio_dev->name = name;
+       indio_dev->info = &inv_icm42600_gyro_info;
+       indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
+       indio_dev->channels = inv_icm42600_gyro_channels;
+       indio_dev->num_channels = ARRAY_SIZE(inv_icm42600_gyro_channels);
+       indio_dev->available_scan_masks = inv_icm42600_gyro_scan_masks;
+       indio_dev->setup_ops = &inv_icm42600_buffer_ops;
+
+       iio_device_attach_buffer(indio_dev, buffer);
+
+       ret = devm_iio_device_register(dev, indio_dev);
+       if (ret)
+               return ERR_PTR(ret);
+
+       return indio_dev;
+}
+
+int inv_icm42600_gyro_parse_fifo(struct iio_dev *indio_dev)
+{
+       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+       struct inv_icm42600_timestamp *ts = iio_priv(indio_dev);
+       ssize_t i, size;
+       unsigned int no;
+       const void *accel, *gyro, *timestamp;
+       const int8_t *temp;
+       unsigned int odr;
+       int64_t ts_val;
+       struct inv_icm42600_gyro_buffer buffer;
+
+       /* parse all fifo packets */
+       for (i = 0, no = 0; i < st->fifo.count; i += size, ++no) {
+               size = inv_icm42600_fifo_decode_packet(&st->fifo.data[i],
+                               &accel, &gyro, &temp, &timestamp, &odr);
+               /* quit if error or FIFO is empty */
+               if (size <= 0)
+                       return size;
+
+               /* skip packet if no gyro data or data is invalid */
+               if (gyro == NULL || !inv_icm42600_fifo_is_data_valid(gyro))
+                       continue;
+
+               /* update odr */
+               if (odr & INV_ICM42600_SENSOR_GYRO)
+                       inv_icm42600_timestamp_apply_odr(ts, st->fifo.period,
+                                                        st->fifo.nb.total, no);
+
+               /* buffer is copied to userspace, zeroing it to avoid any data leak */
+               memset(&buffer, 0, sizeof(buffer));
+               memcpy(&buffer.gyro, gyro, sizeof(buffer.gyro));
+               /* convert 8 bits FIFO temperature in high resolution format */
+               buffer.temp = temp ? (*temp * 64) : 0;
+               ts_val = inv_icm42600_timestamp_pop(ts);
+               iio_push_to_buffers_with_timestamp(indio_dev, &buffer, ts_val);
+       }
+
+       return 0;
+}
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
new file mode 100644 (file)
index 0000000..85b1934
--- /dev/null
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 InvenSense, Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/property.h>
+
+#include "inv_icm42600.h"
+
+static int inv_icm42600_i2c_bus_setup(struct inv_icm42600_state *st)
+{
+       unsigned int mask, val;
+       int ret;
+
+       /* setup interface registers */
+       ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG6,
+                                INV_ICM42600_INTF_CONFIG6_MASK,
+                                INV_ICM42600_INTF_CONFIG6_I3C_EN);
+       if (ret)
+               return ret;
+
+       ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4,
+                                INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY, 0);
+       if (ret)
+               return ret;
+
+       /* set slew rates for I2C and SPI */
+       mask = INV_ICM42600_DRIVE_CONFIG_I2C_MASK |
+              INV_ICM42600_DRIVE_CONFIG_SPI_MASK;
+       val = INV_ICM42600_DRIVE_CONFIG_I2C(INV_ICM42600_SLEW_RATE_12_36NS) |
+             INV_ICM42600_DRIVE_CONFIG_SPI(INV_ICM42600_SLEW_RATE_12_36NS);
+       ret = regmap_update_bits(st->map, INV_ICM42600_REG_DRIVE_CONFIG,
+                                mask, val);
+       if (ret)
+               return ret;
+
+       /* disable SPI bus */
+       return regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0,
+                                 INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK,
+                                 INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_SPI_DIS);
+}
+
+static int inv_icm42600_probe(struct i2c_client *client)
+{
+       const void *match;
+       enum inv_icm42600_chip chip;
+       struct regmap *regmap;
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
+               return -ENOTSUPP;
+
+       match = device_get_match_data(&client->dev);
+       if (!match)
+               return -EINVAL;
+       chip = (enum inv_icm42600_chip)match;
+
+       regmap = devm_regmap_init_i2c(client, &inv_icm42600_regmap_config);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
+
+       return inv_icm42600_core_probe(regmap, chip, client->irq,
+                                      inv_icm42600_i2c_bus_setup);
+}
+
+static const struct of_device_id inv_icm42600_of_matches[] = {
+       {
+               .compatible = "invensense,icm42600",
+               .data = (void *)INV_CHIP_ICM42600,
+       }, {
+               .compatible = "invensense,icm42602",
+               .data = (void *)INV_CHIP_ICM42602,
+       }, {
+               .compatible = "invensense,icm42605",
+               .data = (void *)INV_CHIP_ICM42605,
+       }, {
+               .compatible = "invensense,icm42622",
+               .data = (void *)INV_CHIP_ICM42622,
+       },
+       {}
+};
+MODULE_DEVICE_TABLE(of, inv_icm42600_of_matches);
+
+static struct i2c_driver inv_icm42600_driver = {
+       .driver = {
+               .name = "inv-icm42600-i2c",
+               .of_match_table = inv_icm42600_of_matches,
+               .pm = &inv_icm42600_pm_ops,
+       },
+       .probe_new = inv_icm42600_probe,
+};
+module_i2c_driver(inv_icm42600_driver);
+
+MODULE_AUTHOR("InvenSense, Inc.");
+MODULE_DESCRIPTION("InvenSense ICM-426xx I2C driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
new file mode 100644 (file)
index 0000000..3237896
--- /dev/null
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 InvenSense, Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/spi/spi.h>
+#include <linux/regmap.h>
+#include <linux/property.h>
+
+#include "inv_icm42600.h"
+
+static int inv_icm42600_spi_bus_setup(struct inv_icm42600_state *st)
+{
+       unsigned int mask, val;
+       int ret;
+
+       /* setup interface registers */
+       val = INV_ICM42600_INTF_CONFIG6_I3C_EN |
+             INV_ICM42600_INTF_CONFIG6_I3C_SDR_EN |
+             INV_ICM42600_INTF_CONFIG6_I3C_DDR_EN;
+       ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG6,
+                                INV_ICM42600_INTF_CONFIG6_MASK, val);
+       if (ret)
+               return ret;
+
+       ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4,
+                                INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY, 0);
+       if (ret)
+               return ret;
+
+       /* set slew rates for I2C and SPI */
+       mask = INV_ICM42600_DRIVE_CONFIG_I2C_MASK |
+              INV_ICM42600_DRIVE_CONFIG_SPI_MASK;
+       val = INV_ICM42600_DRIVE_CONFIG_I2C(INV_ICM42600_SLEW_RATE_20_60NS) |
+             INV_ICM42600_DRIVE_CONFIG_SPI(INV_ICM42600_SLEW_RATE_INF_2NS);
+       ret = regmap_update_bits(st->map, INV_ICM42600_REG_DRIVE_CONFIG,
+                                mask, val);
+       if (ret)
+               return ret;
+
+       /* disable i2c bus */
+       return regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0,
+                                 INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK,
+                                 INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_I2C_DIS);
+}
+
+static int inv_icm42600_probe(struct spi_device *spi)
+{
+       const void *match;
+       enum inv_icm42600_chip chip;
+       struct regmap *regmap;
+
+       match = device_get_match_data(&spi->dev);
+       if (!match)
+               return -EINVAL;
+       chip = (enum inv_icm42600_chip)match;
+
+       regmap = devm_regmap_init_spi(spi, &inv_icm42600_regmap_config);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
+
+       return inv_icm42600_core_probe(regmap, chip, spi->irq,
+                                      inv_icm42600_spi_bus_setup);
+}
+
+static const struct of_device_id inv_icm42600_of_matches[] = {
+       {
+               .compatible = "invensense,icm42600",
+               .data = (void *)INV_CHIP_ICM42600,
+       }, {
+               .compatible = "invensense,icm42602",
+               .data = (void *)INV_CHIP_ICM42602,
+       }, {
+               .compatible = "invensense,icm42605",
+               .data = (void *)INV_CHIP_ICM42605,
+       }, {
+               .compatible = "invensense,icm42622",
+               .data = (void *)INV_CHIP_ICM42622,
+       },
+       {}
+};
+MODULE_DEVICE_TABLE(of, inv_icm42600_of_matches);
+
+static struct spi_driver inv_icm42600_driver = {
+       .driver = {
+               .name = "inv-icm42600-spi",
+               .of_match_table = inv_icm42600_of_matches,
+               .pm = &inv_icm42600_pm_ops,
+       },
+       .probe = inv_icm42600_probe,
+};
+module_spi_driver(inv_icm42600_driver);
+
+MODULE_AUTHOR("InvenSense, Inc.");
+MODULE_DESCRIPTION("InvenSense ICM-426xx SPI driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
new file mode 100644 (file)
index 0000000..213cce1
--- /dev/null
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/iio/iio.h>
+
+#include "inv_icm42600.h"
+#include "inv_icm42600_temp.h"
+
+static int inv_icm42600_temp_read(struct inv_icm42600_state *st, int16_t *temp)
+{
+       struct device *dev = regmap_get_device(st->map);
+       __be16 *raw;
+       int ret;
+
+       pm_runtime_get_sync(dev);
+       mutex_lock(&st->lock);
+
+       ret = inv_icm42600_set_temp_conf(st, true, NULL);
+       if (ret)
+               goto exit;
+
+       raw = (__be16 *)&st->buffer[0];
+       ret = regmap_bulk_read(st->map, INV_ICM42600_REG_TEMP_DATA, raw, sizeof(*raw));
+       if (ret)
+               goto exit;
+
+       *temp = (int16_t)be16_to_cpup(raw);
+       if (*temp == INV_ICM42600_DATA_INVALID)
+               ret = -EINVAL;
+
+exit:
+       mutex_unlock(&st->lock);
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
+
+       return ret;
+}
+
+int inv_icm42600_temp_read_raw(struct iio_dev *indio_dev,
+                              struct iio_chan_spec const *chan,
+                              int *val, int *val2, long mask)
+{
+       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+       int16_t temp;
+       int ret;
+
+       if (chan->type != IIO_TEMP)
+               return -EINVAL;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               ret = iio_device_claim_direct_mode(indio_dev);
+               if (ret)
+                       return ret;
+               ret = inv_icm42600_temp_read(st, &temp);
+               iio_device_release_direct_mode(indio_dev);
+               if (ret)
+                       return ret;
+               *val = temp;
+               return IIO_VAL_INT;
+       /*
+        * T°C = (temp / 132.48) + 25
+        * Tm°C = 1000 * ((temp * 100 / 13248) + 25)
+        * scale: 100000 / 13248 ~= 7.548309
+        * offset: 25000
+        */
+       case IIO_CHAN_INFO_SCALE:
+               *val = 7;
+               *val2 = 548309;
+               return IIO_VAL_INT_PLUS_MICRO;
+       case IIO_CHAN_INFO_OFFSET:
+               *val = 25000;
+               return IIO_VAL_INT;
+       default:
+               return -EINVAL;
+       }
+}
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h
new file mode 100644 (file)
index 0000000..3941186
--- /dev/null
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#ifndef INV_ICM42600_TEMP_H_
+#define INV_ICM42600_TEMP_H_
+
+#include <linux/iio/iio.h>
+
+#define INV_ICM42600_TEMP_CHAN(_index)                                 \
+       {                                                               \
+               .type = IIO_TEMP,                                       \
+               .info_mask_separate =                                   \
+                       BIT(IIO_CHAN_INFO_RAW) |                        \
+                       BIT(IIO_CHAN_INFO_OFFSET) |                     \
+                       BIT(IIO_CHAN_INFO_SCALE),                       \
+               .scan_index = _index,                                   \
+               .scan_type = {                                          \
+                       .sign = 's',                                    \
+                       .realbits = 16,                                 \
+                       .storagebits = 16,                              \
+               },                                                      \
+       }
+
+int inv_icm42600_temp_read_raw(struct iio_dev *indio_dev,
+                              struct iio_chan_spec const *chan,
+                              int *val, int *val2, long mask);
+
+#endif
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c
new file mode 100644 (file)
index 0000000..7f2dc41
--- /dev/null
@@ -0,0 +1,195 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/regmap.h>
+#include <linux/math64.h>
+
+#include "inv_icm42600.h"
+#include "inv_icm42600_timestamp.h"
+
+/* internal chip period is 32kHz, 31250ns */
+#define INV_ICM42600_TIMESTAMP_PERIOD          31250
+/* allow a jitter of +/- 2% */
+#define INV_ICM42600_TIMESTAMP_JITTER          2
+/* compute min and max periods accepted */
+#define INV_ICM42600_TIMESTAMP_MIN_PERIOD(_p)          \
+       (((_p) * (100 - INV_ICM42600_TIMESTAMP_JITTER)) / 100)
+#define INV_ICM42600_TIMESTAMP_MAX_PERIOD(_p)          \
+       (((_p) * (100 + INV_ICM42600_TIMESTAMP_JITTER)) / 100)
+
+/* Add a new value inside an accumulator and update the estimate value */
+static void inv_update_acc(struct inv_icm42600_timestamp_acc *acc, uint32_t val)
+{
+       uint64_t sum = 0;
+       size_t i;
+
+       acc->values[acc->idx++] = val;
+       if (acc->idx >= ARRAY_SIZE(acc->values))
+               acc->idx = 0;
+
+       /* compute the mean of all stored values, use 0 as empty slot */
+       for (i = 0; i < ARRAY_SIZE(acc->values); ++i) {
+               if (acc->values[i] == 0)
+                       break;
+               sum += acc->values[i];
+       }
+
+       acc->val = div_u64(sum, i);
+}
+
+void inv_icm42600_timestamp_init(struct inv_icm42600_timestamp *ts,
+                                uint32_t period)
+{
+       /* initial odr for sensor after reset is 1kHz */
+       const uint32_t default_period = 1000000;
+
+       /* current multiplier and period values after reset */
+       ts->mult = default_period / INV_ICM42600_TIMESTAMP_PERIOD;
+       ts->period = default_period;
+       /* new set multiplier is the one from chip initialization */
+       ts->new_mult = period / INV_ICM42600_TIMESTAMP_PERIOD;
+
+       /* use theoretical value for chip period */
+       inv_update_acc(&ts->chip_period, INV_ICM42600_TIMESTAMP_PERIOD);
+}
+
+int inv_icm42600_timestamp_setup(struct inv_icm42600_state *st)
+{
+       unsigned int val;
+
+       /* enable timestamp register */
+       val = INV_ICM42600_TMST_CONFIG_TMST_TO_REGS_EN |
+             INV_ICM42600_TMST_CONFIG_TMST_EN;
+       return regmap_update_bits(st->map, INV_ICM42600_REG_TMST_CONFIG,
+                                 INV_ICM42600_TMST_CONFIG_MASK, val);
+}
+
+int inv_icm42600_timestamp_update_odr(struct inv_icm42600_timestamp *ts,
+                                     uint32_t period, bool fifo)
+{
+       /* when FIFO is on, prevent odr change if one is already pending */
+       if (fifo && ts->new_mult != 0)
+               return -EAGAIN;
+
+       ts->new_mult = period / INV_ICM42600_TIMESTAMP_PERIOD;
+
+       return 0;
+}
+
+static bool inv_validate_period(uint32_t period, uint32_t mult)
+{
+       const uint32_t chip_period = INV_ICM42600_TIMESTAMP_PERIOD;
+       uint32_t period_min, period_max;
+
+       /* check that period is acceptable */
+       period_min = INV_ICM42600_TIMESTAMP_MIN_PERIOD(chip_period) * mult;
+       period_max = INV_ICM42600_TIMESTAMP_MAX_PERIOD(chip_period) * mult;
+       if (period > period_min && period < period_max)
+               return true;
+       else
+               return false;
+}
+
+static bool inv_compute_chip_period(struct inv_icm42600_timestamp *ts,
+                                   uint32_t mult, uint32_t period)
+{
+       uint32_t new_chip_period;
+
+       if (!inv_validate_period(period, mult))
+               return false;
+
+       /* update chip internal period estimation */
+       new_chip_period = period / mult;
+       inv_update_acc(&ts->chip_period, new_chip_period);
+
+       return true;
+}
+
+void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts,
+                                     uint32_t fifo_period, size_t fifo_nb,
+                                     size_t sensor_nb, int64_t timestamp)
+{
+       struct inv_icm42600_timestamp_interval *it;
+       int64_t delta, interval;
+       const uint32_t fifo_mult = fifo_period / INV_ICM42600_TIMESTAMP_PERIOD;
+       uint32_t period = ts->period;
+       int32_t m;
+       bool valid = false;
+
+       if (fifo_nb == 0)
+               return;
+
+       /* update interrupt timestamp and compute chip and sensor periods */
+       it = &ts->it;
+       it->lo = it->up;
+       it->up = timestamp;
+       delta = it->up - it->lo;
+       if (it->lo != 0) {
+               /* compute period: delta time divided by number of samples */
+               period = div_s64(delta, fifo_nb);
+               valid = inv_compute_chip_period(ts, fifo_mult, period);
+               /* update sensor period if chip internal period is updated */
+               if (valid)
+                       ts->period = ts->mult * ts->chip_period.val;
+       }
+
+       /* no previous data, compute theoritical value from interrupt */
+       if (ts->timestamp == 0) {
+               /* elapsed time: sensor period * sensor samples number */
+               interval = (int64_t)ts->period * (int64_t)sensor_nb;
+               ts->timestamp = it->up - interval;
+               return;
+       }
+
+       /* if interrupt interval is valid, sync with interrupt timestamp */
+       if (valid) {
+               /* compute measured fifo_period */
+               fifo_period = fifo_mult * ts->chip_period.val;
+               /* delta time between last sample and last interrupt */
+               delta = it->lo - ts->timestamp;
+               /* if there are multiple samples, go back to first one */
+               while (delta >= (fifo_period * 3 / 2))
+                       delta -= fifo_period;
+               /* compute maximal adjustment value */
+               m = INV_ICM42600_TIMESTAMP_MAX_PERIOD(ts->period) - ts->period;
+               if (delta > m)
+                       delta = m;
+               else if (delta < -m)
+                       delta = -m;
+               ts->timestamp += delta;
+       }
+}
+
+void inv_icm42600_timestamp_apply_odr(struct inv_icm42600_timestamp *ts,
+                                     uint32_t fifo_period, size_t fifo_nb,
+                                     unsigned int fifo_no)
+{
+       int64_t interval;
+       uint32_t fifo_mult;
+
+       if (ts->new_mult == 0)
+               return;
+
+       /* update to new multiplier and update period */
+       ts->mult = ts->new_mult;
+       ts->new_mult = 0;
+       ts->period = ts->mult * ts->chip_period.val;
+
+       /*
+        * After ODR change the time interval with the previous sample is
+        * undertermined (depends when the change occures). So we compute the
+        * timestamp from the current interrupt using the new FIFO period, the
+        * total number of samples and the current sample numero.
+        */
+       if (ts->timestamp != 0) {
+               /* compute measured fifo period */
+               fifo_mult = fifo_period / INV_ICM42600_TIMESTAMP_PERIOD;
+               fifo_period = fifo_mult * ts->chip_period.val;
+               /* computes time interval between interrupt and this sample */
+               interval = (int64_t)(fifo_nb - fifo_no) * (int64_t)fifo_period;
+               ts->timestamp = ts->it.up - interval;
+       }
+}
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h b/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h
new file mode 100644 (file)
index 0000000..4e4f331
--- /dev/null
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#ifndef INV_ICM42600_TIMESTAMP_H_
+#define INV_ICM42600_TIMESTAMP_H_
+
+#include <linux/kernel.h>
+
+struct inv_icm42600_state;
+
+/**
+ * struct inv_icm42600_timestamp_interval - timestamps interval
+ * @lo:        interval lower bound
+ * @up:        interval upper bound
+ */
+struct inv_icm42600_timestamp_interval {
+       int64_t lo;
+       int64_t up;
+};
+
+/**
+ * struct inv_icm42600_timestamp_acc - accumulator for computing an estimation
+ * @val:       current estimation of the value, the mean of all values
+ * @idx:       current index of the next free place in values table
+ * @values:    table of all measured values, use for computing the mean
+ */
+struct inv_icm42600_timestamp_acc {
+       uint32_t val;
+       size_t idx;
+       uint32_t values[32];
+};
+
+/**
+ * struct inv_icm42600_timestamp - timestamp management states
+ * @it:                        interrupts interval timestamps
+ * @timestamp:         store last timestamp for computing next data timestamp
+ * @mult:              current internal period multiplier
+ * @new_mult:          new set internal period multiplier (not yet effective)
+ * @period:            measured current period of the sensor
+ * @chip_period:       accumulator for computing internal chip period
+ */
+struct inv_icm42600_timestamp {
+       struct inv_icm42600_timestamp_interval it;
+       int64_t timestamp;
+       uint32_t mult;
+       uint32_t new_mult;
+       uint32_t period;
+       struct inv_icm42600_timestamp_acc chip_period;
+};
+
+void inv_icm42600_timestamp_init(struct inv_icm42600_timestamp *ts,
+                                uint32_t period);
+
+int inv_icm42600_timestamp_setup(struct inv_icm42600_state *st);
+
+int inv_icm42600_timestamp_update_odr(struct inv_icm42600_timestamp *ts,
+                                     uint32_t period, bool fifo);
+
+void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts,
+                                     uint32_t fifo_period, size_t fifo_nb,
+                                     size_t sensor_nb, int64_t timestamp);
+
+static inline int64_t
+inv_icm42600_timestamp_pop(struct inv_icm42600_timestamp *ts)
+{
+       ts->timestamp += ts->period;
+       return ts->timestamp;
+}
+
+void inv_icm42600_timestamp_apply_odr(struct inv_icm42600_timestamp *ts,
+                                     uint32_t fifo_period, size_t fifo_nb,
+                                     unsigned int fifo_no);
+
+static inline void
+inv_icm42600_timestamp_reset(struct inv_icm42600_timestamp *ts)
+{
+       const struct inv_icm42600_timestamp_interval interval_init = {0LL, 0LL};
+
+       ts->it = interval_init;
+       ts->timestamp = 0;
+}
+
+#endif
index c27d060..f8f0cf7 100644 (file)
@@ -101,8 +101,8 @@ static int inv_mpu_process_acpi_config(struct i2c_client *client,
                                       unsigned short *primary_addr,
                                       unsigned short *secondary_addr)
 {
+       struct acpi_device *adev = ACPI_COMPANION(&client->dev);
        const struct acpi_device_id *id;
-       struct acpi_device *adev;
        u32 i2c_addr = 0;
        LIST_HEAD(resources);
        int ret;
@@ -112,10 +112,6 @@ static int inv_mpu_process_acpi_config(struct i2c_client *client,
        if (!id)
                return -ENODEV;
 
-       adev = ACPI_COMPANION(&client->dev);
-       if (!adev)
-               return -ENODEV;
-
        ret = acpi_dev_get_resources(adev, &resources,
                                     acpi_i2c_check_resource, &i2c_addr);
        if (ret < 0)
index 4d604fe..153f855 100644 (file)
@@ -1530,7 +1530,6 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
        }
 
        dev_set_drvdata(dev, indio_dev);
-       indio_dev->dev.parent = dev;
        /* name will be NULL when enumerated via ACPI */
        if (name)
                indio_dev->name = name;
index e674661..e37bf0c 100644 (file)
@@ -1248,7 +1248,6 @@ static struct iio_dev *kmx61_indiodev_setup(struct kmx61_data *data,
 
        kmx61_set_data(indio_dev, data);
 
-       indio_dev->dev.parent = &data->client->dev;
        indio_dev->channels = chan;
        indio_dev->num_channels = num_channels;
        indio_dev->name = name;
index 0b776cb..c8ddeb3 100644 (file)
@@ -2152,7 +2152,6 @@ static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw,
                return NULL;
 
        iio_dev->modes = INDIO_DIRECT_MODE;
-       iio_dev->dev.parent = hw->dev;
        iio_dev->available_scan_masks = st_lsm6dsx_available_scan_masks;
        iio_dev->channels = hw->settings->channels[id].chan;
        iio_dev->num_channels = hw->settings->channels[id].len;
index c1f83fe..f0d615c 100644 (file)
@@ -735,7 +735,6 @@ st_lsm6dsx_shub_alloc_iiodev(struct st_lsm6dsx_hw *hw,
                return NULL;
 
        iio_dev->modes = INDIO_DIRECT_MODE;
-       iio_dev->dev.parent = hw->dev;
        iio_dev->info = &st_lsm6dsx_ext_info;
 
        sensor = iio_priv(iio_dev);
index 9fa238c..a7d7e51 100644 (file)
@@ -19,7 +19,9 @@
 #include <linux/sched/signal.h>
 
 #include <linux/iio/iio.h>
+#include <linux/iio/iio-opaque.h>
 #include "iio_core.h"
+#include "iio_core_trigger.h"
 #include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
 #include <linux/iio/buffer_impl.h>
@@ -598,8 +600,10 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
 static void iio_buffer_activate(struct iio_dev *indio_dev,
        struct iio_buffer *buffer)
 {
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
+
        iio_buffer_get(buffer);
-       list_add(&buffer->buffer_list, &indio_dev->buffer_list);
+       list_add(&buffer->buffer_list, &iio_dev_opaque->buffer_list);
 }
 
 static void iio_buffer_deactivate(struct iio_buffer *buffer)
@@ -611,10 +615,11 @@ static void iio_buffer_deactivate(struct iio_buffer *buffer)
 
 static void iio_buffer_deactivate_all(struct iio_dev *indio_dev)
 {
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
        struct iio_buffer *buffer, *_buffer;
 
        list_for_each_entry_safe(buffer, _buffer,
-                       &indio_dev->buffer_list, buffer_list)
+                       &iio_dev_opaque->buffer_list, buffer_list)
                iio_buffer_deactivate(buffer);
 }
 
@@ -687,6 +692,7 @@ static int iio_verify_update(struct iio_dev *indio_dev,
        struct iio_buffer *insert_buffer, struct iio_buffer *remove_buffer,
        struct iio_device_config *config)
 {
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
        unsigned long *compound_mask;
        const unsigned long *scan_mask;
        bool strict_scanmask = false;
@@ -709,12 +715,12 @@ static int iio_verify_update(struct iio_dev *indio_dev,
         * to verify.
         */
        if (remove_buffer && !insert_buffer &&
-               list_is_singular(&indio_dev->buffer_list))
+               list_is_singular(&iio_dev_opaque->buffer_list))
                        return 0;
 
        modes = indio_dev->modes;
 
-       list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) {
+       list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
                if (buffer == remove_buffer)
                        continue;
                modes &= buffer->access->modes;
@@ -735,7 +741,7 @@ static int iio_verify_update(struct iio_dev *indio_dev,
                 * Keep things simple for now and only allow a single buffer to
                 * be connected in hardware mode.
                 */
-               if (insert_buffer && !list_empty(&indio_dev->buffer_list))
+               if (insert_buffer && !list_empty(&iio_dev_opaque->buffer_list))
                        return -EINVAL;
                config->mode = INDIO_BUFFER_HARDWARE;
                strict_scanmask = true;
@@ -755,7 +761,7 @@ static int iio_verify_update(struct iio_dev *indio_dev,
 
        scan_timestamp = false;
 
-       list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) {
+       list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
                if (buffer == remove_buffer)
                        continue;
                bitmap_or(compound_mask, compound_mask, buffer->scan_mask,
@@ -901,10 +907,11 @@ error_clear_mux_table:
 
 static int iio_update_demux(struct iio_dev *indio_dev)
 {
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
        struct iio_buffer *buffer;
        int ret;
 
-       list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) {
+       list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
                ret = iio_buffer_update_demux(indio_dev, buffer);
                if (ret < 0)
                        goto error_clear_mux_table;
@@ -912,7 +919,7 @@ static int iio_update_demux(struct iio_dev *indio_dev)
        return 0;
 
 error_clear_mux_table:
-       list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list)
+       list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list)
                iio_buffer_demux_free(buffer);
 
        return ret;
@@ -921,6 +928,7 @@ error_clear_mux_table:
 static int iio_enable_buffers(struct iio_dev *indio_dev,
        struct iio_device_config *config)
 {
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
        struct iio_buffer *buffer;
        int ret;
 
@@ -957,25 +965,37 @@ static int iio_enable_buffers(struct iio_dev *indio_dev,
                indio_dev->info->hwfifo_set_watermark(indio_dev,
                        config->watermark);
 
-       list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) {
+       list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
                ret = iio_buffer_enable(buffer, indio_dev);
                if (ret)
                        goto err_disable_buffers;
        }
 
+       if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
+               ret = iio_trigger_attach_poll_func(indio_dev->trig,
+                                                  indio_dev->pollfunc);
+               if (ret)
+                       goto err_disable_buffers;
+       }
+
        if (indio_dev->setup_ops->postenable) {
                ret = indio_dev->setup_ops->postenable(indio_dev);
                if (ret) {
                        dev_dbg(&indio_dev->dev,
                               "Buffer not started: postenable failed (%d)\n", ret);
-                       goto err_disable_buffers;
+                       goto err_detach_pollfunc;
                }
        }
 
        return 0;
 
+err_detach_pollfunc:
+       if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
+               iio_trigger_detach_poll_func(indio_dev->trig,
+                                            indio_dev->pollfunc);
+       }
 err_disable_buffers:
-       list_for_each_entry_continue_reverse(buffer, &indio_dev->buffer_list,
+       list_for_each_entry_continue_reverse(buffer, &iio_dev_opaque->buffer_list,
                                             buffer_list)
                iio_buffer_disable(buffer, indio_dev);
 err_run_postdisable:
@@ -990,12 +1010,13 @@ err_undo_config:
 
 static int iio_disable_buffers(struct iio_dev *indio_dev)
 {
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
        struct iio_buffer *buffer;
        int ret = 0;
        int ret2;
 
        /* Wind down existing buffers - iff there are any */
-       if (list_empty(&indio_dev->buffer_list))
+       if (list_empty(&iio_dev_opaque->buffer_list))
                return 0;
 
        /*
@@ -1011,7 +1032,12 @@ static int iio_disable_buffers(struct iio_dev *indio_dev)
                        ret = ret2;
        }
 
-       list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) {
+       if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
+               iio_trigger_detach_poll_func(indio_dev->trig,
+                                            indio_dev->pollfunc);
+       }
+
+       list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) {
                ret2 = iio_buffer_disable(buffer, indio_dev);
                if (ret2 && !ret)
                        ret = ret2;
@@ -1034,6 +1060,7 @@ static int __iio_update_buffers(struct iio_dev *indio_dev,
                       struct iio_buffer *insert_buffer,
                       struct iio_buffer *remove_buffer)
 {
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
        struct iio_device_config new_config;
        int ret;
 
@@ -1058,7 +1085,7 @@ static int __iio_update_buffers(struct iio_dev *indio_dev,
                iio_buffer_activate(indio_dev, insert_buffer);
 
        /* If no buffers in list, we are done */
-       if (list_empty(&indio_dev->buffer_list))
+       if (list_empty(&iio_dev_opaque->buffer_list))
                return 0;
 
        ret = iio_enable_buffers(indio_dev, &new_config);
@@ -1407,10 +1434,11 @@ static int iio_push_to_buffer(struct iio_buffer *buffer, const void *data)
  */
 int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data)
 {
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
        int ret;
        struct iio_buffer *buf;
 
-       list_for_each_entry(buf, &indio_dev->buffer_list, buffer_list) {
+       list_for_each_entry(buf, &iio_dev_opaque->buffer_list, buffer_list) {
                ret = iio_push_to_buffer(buf, data);
                if (ret < 0)
                        return ret;
index 1527f01..ef5e23c 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/debugfs.h>
 #include <linux/mutex.h>
 #include <linux/iio/iio.h>
+#include <linux/iio/iio-opaque.h>
 #include "iio_core.h"
 #include "iio_core_trigger.h"
 #include <linux/iio/sysfs.h>
@@ -164,6 +165,19 @@ static const char * const iio_chan_info_postfix[] = {
        [IIO_CHAN_INFO_THERMOCOUPLE_TYPE] = "thermocouple_type",
 };
 
+#if defined(CONFIG_DEBUG_FS)
+/**
+ * There's also a CONFIG_DEBUG_FS guard in include/linux/iio/iio.h for
+ * iio_get_debugfs_dentry() to make it inline if CONFIG_DEBUG_FS is undefined
+ */
+struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev)
+{
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
+       return iio_dev_opaque->debugfs_dentry;
+}
+EXPORT_SYMBOL_GPL(iio_get_debugfs_dentry);
+#endif
+
 /**
  * iio_find_channel_from_si() - get channel from its scan index
  * @indio_dev:         device
@@ -197,7 +211,8 @@ EXPORT_SYMBOL(iio_read_const_attr);
 int iio_device_set_clock(struct iio_dev *indio_dev, clockid_t clock_id)
 {
        int ret;
-       const struct iio_event_interface *ev_int = indio_dev->event_interface;
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
+       const struct iio_event_interface *ev_int = iio_dev_opaque->event_interface;
 
        ret = mutex_lock_interruptible(&indio_dev->mlock);
        if (ret)
@@ -307,35 +322,37 @@ static ssize_t iio_debugfs_read_reg(struct file *file, char __user *userbuf,
                              size_t count, loff_t *ppos)
 {
        struct iio_dev *indio_dev = file->private_data;
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
        unsigned val = 0;
        int ret;
 
        if (*ppos > 0)
                return simple_read_from_buffer(userbuf, count, ppos,
-                                              indio_dev->read_buf,
-                                              indio_dev->read_buf_len);
+                                              iio_dev_opaque->read_buf,
+                                              iio_dev_opaque->read_buf_len);
 
        ret = indio_dev->info->debugfs_reg_access(indio_dev,
-                                                 indio_dev->cached_reg_addr,
+                                                 iio_dev_opaque->cached_reg_addr,
                                                  0, &val);
        if (ret) {
                dev_err(indio_dev->dev.parent, "%s: read failed\n", __func__);
                return ret;
        }
 
-       indio_dev->read_buf_len = snprintf(indio_dev->read_buf,
-                                          sizeof(indio_dev->read_buf),
-                                          "0x%X\n", val);
+       iio_dev_opaque->read_buf_len = snprintf(iio_dev_opaque->read_buf,
+                                             sizeof(iio_dev_opaque->read_buf),
+                                             "0x%X\n", val);
 
        return simple_read_from_buffer(userbuf, count, ppos,
-                                      indio_dev->read_buf,
-                                      indio_dev->read_buf_len);
+                                      iio_dev_opaque->read_buf,
+                                      iio_dev_opaque->read_buf_len);
 }
 
 static ssize_t iio_debugfs_write_reg(struct file *file,
                     const char __user *userbuf, size_t count, loff_t *ppos)
 {
        struct iio_dev *indio_dev = file->private_data;
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
        unsigned reg, val;
        char buf[80];
        int ret;
@@ -350,10 +367,10 @@ static ssize_t iio_debugfs_write_reg(struct file *file,
 
        switch (ret) {
        case 1:
-               indio_dev->cached_reg_addr = reg;
+               iio_dev_opaque->cached_reg_addr = reg;
                break;
        case 2:
-               indio_dev->cached_reg_addr = reg;
+               iio_dev_opaque->cached_reg_addr = reg;
                ret = indio_dev->info->debugfs_reg_access(indio_dev, reg,
                                                          val, NULL);
                if (ret) {
@@ -377,23 +394,28 @@ static const struct file_operations iio_debugfs_reg_fops = {
 
 static void iio_device_unregister_debugfs(struct iio_dev *indio_dev)
 {
-       debugfs_remove_recursive(indio_dev->debugfs_dentry);
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
+       debugfs_remove_recursive(iio_dev_opaque->debugfs_dentry);
 }
 
 static void iio_device_register_debugfs(struct iio_dev *indio_dev)
 {
+       struct iio_dev_opaque *iio_dev_opaque;
+
        if (indio_dev->info->debugfs_reg_access == NULL)
                return;
 
        if (!iio_debugfs_dentry)
                return;
 
-       indio_dev->debugfs_dentry =
+       iio_dev_opaque = to_iio_dev_opaque(indio_dev);
+
+       iio_dev_opaque->debugfs_dentry =
                debugfs_create_dir(dev_name(&indio_dev->dev),
                                   iio_debugfs_dentry);
 
        debugfs_create_file("direct_reg_access", 0644,
-                           indio_dev->debugfs_dentry, indio_dev,
+                           iio_dev_opaque->debugfs_dentry, indio_dev,
                            &iio_debugfs_reg_fops);
 }
 #else
@@ -1116,6 +1138,7 @@ static int iio_device_add_info_mask_type(struct iio_dev *indio_dev,
                                         enum iio_shared_by shared_by,
                                         const long *infomask)
 {
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
        int i, ret, attrcount = 0;
 
        for_each_set_bit(i, infomask, sizeof(*infomask)*8) {
@@ -1128,7 +1151,7 @@ static int iio_device_add_info_mask_type(struct iio_dev *indio_dev,
                                             i,
                                             shared_by,
                                             &indio_dev->dev,
-                                            &indio_dev->channel_attr_list);
+                                            &iio_dev_opaque->channel_attr_list);
                if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE))
                        continue;
                else if (ret < 0)
@@ -1144,6 +1167,7 @@ static int iio_device_add_info_mask_type_avail(struct iio_dev *indio_dev,
                                               enum iio_shared_by shared_by,
                                               const long *infomask)
 {
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
        int i, ret, attrcount = 0;
        char *avail_postfix;
 
@@ -1163,7 +1187,7 @@ static int iio_device_add_info_mask_type_avail(struct iio_dev *indio_dev,
                                             i,
                                             shared_by,
                                             &indio_dev->dev,
-                                            &indio_dev->channel_attr_list);
+                                            &iio_dev_opaque->channel_attr_list);
                kfree(avail_postfix);
                if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE))
                        continue;
@@ -1178,6 +1202,7 @@ static int iio_device_add_info_mask_type_avail(struct iio_dev *indio_dev,
 static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
                                        struct iio_chan_spec const *chan)
 {
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
        int ret, attrcount = 0;
        const struct iio_chan_spec_ext_info *ext_info;
 
@@ -1253,7 +1278,7 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
                                        i,
                                        ext_info->shared,
                                        &indio_dev->dev,
-                                       &indio_dev->channel_attr_list);
+                                       &iio_dev_opaque->channel_attr_list);
                        i++;
                        if (ret == -EBUSY && ext_info->shared)
                                continue;
@@ -1388,6 +1413,7 @@ static DEVICE_ATTR(current_timestamp_clock, S_IRUGO | S_IWUSR,
 
 static int iio_device_register_sysfs(struct iio_dev *indio_dev)
 {
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
        int i, ret = 0, attrcount, attrn, attrcount_orig = 0;
        struct iio_dev_attr *p;
        struct attribute **attr, *clk = NULL;
@@ -1417,7 +1443,7 @@ static int iio_device_register_sysfs(struct iio_dev *indio_dev)
                        attrcount += ret;
                }
 
-       if (indio_dev->event_interface)
+       if (iio_dev_opaque->event_interface)
                clk = &dev_attr_current_timestamp_clock.attr;
 
        if (indio_dev->name)
@@ -1427,52 +1453,56 @@ static int iio_device_register_sysfs(struct iio_dev *indio_dev)
        if (clk)
                attrcount++;
 
-       indio_dev->chan_attr_group.attrs = kcalloc(attrcount + 1,
-                                                  sizeof(indio_dev->chan_attr_group.attrs[0]),
-                                                  GFP_KERNEL);
-       if (indio_dev->chan_attr_group.attrs == NULL) {
+       iio_dev_opaque->chan_attr_group.attrs =
+               kcalloc(attrcount + 1,
+                       sizeof(iio_dev_opaque->chan_attr_group.attrs[0]),
+                       GFP_KERNEL);
+       if (iio_dev_opaque->chan_attr_group.attrs == NULL) {
                ret = -ENOMEM;
                goto error_clear_attrs;
        }
        /* Copy across original attributes */
        if (indio_dev->info->attrs)
-               memcpy(indio_dev->chan_attr_group.attrs,
+               memcpy(iio_dev_opaque->chan_attr_group.attrs,
                       indio_dev->info->attrs->attrs,
-                      sizeof(indio_dev->chan_attr_group.attrs[0])
+                      sizeof(iio_dev_opaque->chan_attr_group.attrs[0])
                       *attrcount_orig);
        attrn = attrcount_orig;
        /* Add all elements from the list. */
-       list_for_each_entry(p, &indio_dev->channel_attr_list, l)
-               indio_dev->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr;
+       list_for_each_entry(p, &iio_dev_opaque->channel_attr_list, l)
+               iio_dev_opaque->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr;
        if (indio_dev->name)
-               indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr;
+               iio_dev_opaque->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr;
        if (indio_dev->label)
-               indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_label.attr;
+               iio_dev_opaque->chan_attr_group.attrs[attrn++] = &dev_attr_label.attr;
        if (clk)
-               indio_dev->chan_attr_group.attrs[attrn++] = clk;
+               iio_dev_opaque->chan_attr_group.attrs[attrn++] = clk;
 
        indio_dev->groups[indio_dev->groupcounter++] =
-               &indio_dev->chan_attr_group;
+               &iio_dev_opaque->chan_attr_group;
 
        return 0;
 
 error_clear_attrs:
-       iio_free_chan_devattr_list(&indio_dev->channel_attr_list);
+       iio_free_chan_devattr_list(&iio_dev_opaque->channel_attr_list);
 
        return ret;
 }
 
 static void iio_device_unregister_sysfs(struct iio_dev *indio_dev)
 {
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
 
-       iio_free_chan_devattr_list(&indio_dev->channel_attr_list);
-       kfree(indio_dev->chan_attr_group.attrs);
-       indio_dev->chan_attr_group.attrs = NULL;
+       iio_free_chan_devattr_list(&iio_dev_opaque->channel_attr_list);
+       kfree(iio_dev_opaque->chan_attr_group.attrs);
+       iio_dev_opaque->chan_attr_group.attrs = NULL;
 }
 
 static void iio_dev_release(struct device *device)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(device);
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
+
        if (indio_dev->modes & INDIO_ALL_TRIGGERED_MODES)
                iio_device_unregister_trigger_consumer(indio_dev);
        iio_device_unregister_eventset(indio_dev);
@@ -1481,7 +1511,7 @@ static void iio_dev_release(struct device *device)
        iio_buffer_put(indio_dev->buffer);
 
        ida_simple_remove(&iio_ida, indio_dev->id);
-       kfree(indio_dev);
+       kfree(iio_dev_opaque);
 }
 
 struct device_type iio_device_type = {
@@ -1493,23 +1523,26 @@ struct device_type iio_device_type = {
  * iio_device_alloc() - allocate an iio_dev from a driver
  * @sizeof_priv:       Space to allocate for private structure.
  **/
-struct iio_dev *iio_device_alloc(int sizeof_priv)
+struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv)
 {
+       struct iio_dev_opaque *iio_dev_opaque;
        struct iio_dev *dev;
        size_t alloc_size;
 
-       alloc_size = sizeof(struct iio_dev);
+       alloc_size = sizeof(struct iio_dev_opaque);
        if (sizeof_priv) {
                alloc_size = ALIGN(alloc_size, IIO_ALIGN);
                alloc_size += sizeof_priv;
        }
-       /* ensure 32-byte alignment of whole construct ? */
-       alloc_size += IIO_ALIGN - 1;
 
-       dev = kzalloc(alloc_size, GFP_KERNEL);
-       if (!dev)
+       iio_dev_opaque = kzalloc(alloc_size, GFP_KERNEL);
+       if (!iio_dev_opaque)
                return NULL;
 
+       dev = &iio_dev_opaque->indio_dev;
+       dev->priv = (char *)iio_dev_opaque +
+               ALIGN(sizeof(struct iio_dev_opaque), IIO_ALIGN);
+
        dev->dev.groups = dev->groups;
        dev->dev.type = &iio_device_type;
        dev->dev.bus = &iio_bus_type;
@@ -1517,17 +1550,17 @@ struct iio_dev *iio_device_alloc(int sizeof_priv)
        dev_set_drvdata(&dev->dev, (void *)dev);
        mutex_init(&dev->mlock);
        mutex_init(&dev->info_exist_lock);
-       INIT_LIST_HEAD(&dev->channel_attr_list);
+       INIT_LIST_HEAD(&iio_dev_opaque->channel_attr_list);
 
        dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL);
        if (dev->id < 0) {
                /* cannot use a dev_err as the name isn't available */
                pr_err("failed to get device id\n");
-               kfree(dev);
+               kfree(iio_dev_opaque);
                return NULL;
        }
        dev_set_name(&dev->dev, "iio:device%d", dev->id);
-       INIT_LIST_HEAD(&dev->buffer_list);
+       INIT_LIST_HEAD(&iio_dev_opaque->buffer_list);
 
        return dev;
 }
@@ -1551,7 +1584,7 @@ static void devm_iio_device_release(struct device *dev, void *res)
 
 /**
  * devm_iio_device_alloc - Resource-managed iio_device_alloc()
- * @dev:               Device to allocate iio_dev for
+ * @parent:            Device to allocate iio_dev for, and parent for this IIO device
  * @sizeof_priv:       Space to allocate for private structure.
  *
  * Managed iio_device_alloc. iio_dev allocated with this function is
@@ -1560,7 +1593,7 @@ static void devm_iio_device_release(struct device *dev, void *res)
  * RETURNS:
  * Pointer to allocated iio_dev on success, NULL on failure.
  */
-struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv)
+struct iio_dev *devm_iio_device_alloc(struct device *parent, int sizeof_priv)
 {
        struct iio_dev **ptr, *iio_dev;
 
@@ -1569,10 +1602,10 @@ struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv)
        if (!ptr)
                return NULL;
 
-       iio_dev = iio_device_alloc(sizeof_priv);
+       iio_dev = iio_device_alloc(parent, sizeof_priv);
        if (iio_dev) {
                *ptr = iio_dev;
-               devres_add(dev, ptr);
+               devres_add(parent, ptr);
        } else {
                devres_free(ptr);
        }
index 5b17c92..2ab4d4c 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/uaccess.h>
 #include <linux/wait.h>
 #include <linux/iio/iio.h>
+#include <linux/iio/iio-opaque.h>
 #include "iio_core.h"
 #include <linux/iio/sysfs.h>
 #include <linux/iio/events.h>
@@ -62,7 +63,8 @@ bool iio_event_enabled(const struct iio_event_interface *ev_int)
  **/
 int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp)
 {
-       struct iio_event_interface *ev_int = indio_dev->event_interface;
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
+       struct iio_event_interface *ev_int = iio_dev_opaque->event_interface;
        struct iio_event_data ev;
        int copied;
 
@@ -96,7 +98,8 @@ static __poll_t iio_event_poll(struct file *filep,
                             struct poll_table_struct *wait)
 {
        struct iio_dev *indio_dev = filep->private_data;
-       struct iio_event_interface *ev_int = indio_dev->event_interface;
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
+       struct iio_event_interface *ev_int = iio_dev_opaque->event_interface;
        __poll_t events = 0;
 
        if (!indio_dev->info)
@@ -116,7 +119,8 @@ static ssize_t iio_event_chrdev_read(struct file *filep,
                                     loff_t *f_ps)
 {
        struct iio_dev *indio_dev = filep->private_data;
-       struct iio_event_interface *ev_int = indio_dev->event_interface;
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
+       struct iio_event_interface *ev_int = iio_dev_opaque->event_interface;
        unsigned int copied;
        int ret;
 
@@ -165,7 +169,8 @@ static ssize_t iio_event_chrdev_read(struct file *filep,
 static int iio_event_chrdev_release(struct inode *inode, struct file *filep)
 {
        struct iio_dev *indio_dev = filep->private_data;
-       struct iio_event_interface *ev_int = indio_dev->event_interface;
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
+       struct iio_event_interface *ev_int = iio_dev_opaque->event_interface;
 
        clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
 
@@ -184,7 +189,8 @@ static const struct file_operations iio_event_chrdev_fileops = {
 
 int iio_event_getfd(struct iio_dev *indio_dev)
 {
-       struct iio_event_interface *ev_int = indio_dev->event_interface;
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
+       struct iio_event_interface *ev_int = iio_dev_opaque->event_interface;
        int fd;
 
        if (ev_int == NULL)
@@ -343,6 +349,7 @@ static int iio_device_add_event(struct iio_dev *indio_dev,
        enum iio_event_type type, enum iio_event_direction dir,
        enum iio_shared_by shared_by, const unsigned long *mask)
 {
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
        ssize_t (*show)(struct device *, struct device_attribute *, char *);
        ssize_t (*store)(struct device *, struct device_attribute *,
                const char *, size_t);
@@ -376,7 +383,7 @@ static int iio_device_add_event(struct iio_dev *indio_dev,
 
                ret = __iio_add_chan_devattr(postfix, chan, show, store,
                         (i << 16) | spec_index, shared_by, &indio_dev->dev,
-                       &indio_dev->event_interface->dev_attr_list);
+                       &iio_dev_opaque->event_interface->dev_attr_list);
                kfree(postfix);
 
                if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE))
@@ -469,6 +476,7 @@ static void iio_setup_ev_int(struct iio_event_interface *ev_int)
 static const char *iio_event_group_name = "events";
 int iio_device_register_eventset(struct iio_dev *indio_dev)
 {
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
        struct iio_dev_attr *p;
        int ret = 0, attrcount_orig = 0, attrcount, attrn;
        struct attribute **attr;
@@ -477,14 +485,14 @@ int iio_device_register_eventset(struct iio_dev *indio_dev)
              iio_check_for_dynamic_events(indio_dev)))
                return 0;
 
-       indio_dev->event_interface =
+       iio_dev_opaque->event_interface =
                kzalloc(sizeof(struct iio_event_interface), GFP_KERNEL);
-       if (indio_dev->event_interface == NULL)
+       if (iio_dev_opaque->event_interface == NULL)
                return -ENOMEM;
 
-       INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list);
+       INIT_LIST_HEAD(&iio_dev_opaque->event_interface->dev_attr_list);
 
-       iio_setup_ev_int(indio_dev->event_interface);
+       iio_setup_ev_int(iio_dev_opaque->event_interface);
        if (indio_dev->info->event_attrs != NULL) {
                attr = indio_dev->info->event_attrs->attrs;
                while (*attr++ != NULL)
@@ -498,35 +506,35 @@ int iio_device_register_eventset(struct iio_dev *indio_dev)
                attrcount += ret;
        }
 
-       indio_dev->event_interface->group.name = iio_event_group_name;
-       indio_dev->event_interface->group.attrs = kcalloc(attrcount + 1,
-                                                         sizeof(indio_dev->event_interface->group.attrs[0]),
+       iio_dev_opaque->event_interface->group.name = iio_event_group_name;
+       iio_dev_opaque->event_interface->group.attrs = kcalloc(attrcount + 1,
+                                                         sizeof(iio_dev_opaque->event_interface->group.attrs[0]),
                                                          GFP_KERNEL);
-       if (indio_dev->event_interface->group.attrs == NULL) {
+       if (iio_dev_opaque->event_interface->group.attrs == NULL) {
                ret = -ENOMEM;
                goto error_free_setup_event_lines;
        }
        if (indio_dev->info->event_attrs)
-               memcpy(indio_dev->event_interface->group.attrs,
+               memcpy(iio_dev_opaque->event_interface->group.attrs,
                       indio_dev->info->event_attrs->attrs,
-                      sizeof(indio_dev->event_interface->group.attrs[0])
+                      sizeof(iio_dev_opaque->event_interface->group.attrs[0])
                       *attrcount_orig);
        attrn = attrcount_orig;
        /* Add all elements from the list. */
        list_for_each_entry(p,
-                           &indio_dev->event_interface->dev_attr_list,
+                           &iio_dev_opaque->event_interface->dev_attr_list,
                            l)
-               indio_dev->event_interface->group.attrs[attrn++] =
+               iio_dev_opaque->event_interface->group.attrs[attrn++] =
                        &p->dev_attr.attr;
        indio_dev->groups[indio_dev->groupcounter++] =
-               &indio_dev->event_interface->group;
+               &iio_dev_opaque->event_interface->group;
 
        return 0;
 
 error_free_setup_event_lines:
-       iio_free_chan_devattr_list(&indio_dev->event_interface->dev_attr_list);
-       kfree(indio_dev->event_interface);
-       indio_dev->event_interface = NULL;
+       iio_free_chan_devattr_list(&iio_dev_opaque->event_interface->dev_attr_list);
+       kfree(iio_dev_opaque->event_interface);
+       iio_dev_opaque->event_interface = NULL;
        return ret;
 }
 
@@ -539,16 +547,20 @@ error_free_setup_event_lines:
  */
 void iio_device_wakeup_eventset(struct iio_dev *indio_dev)
 {
-       if (indio_dev->event_interface == NULL)
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
+
+       if (iio_dev_opaque->event_interface == NULL)
                return;
-       wake_up(&indio_dev->event_interface->wait);
+       wake_up(&iio_dev_opaque->event_interface->wait);
 }
 
 void iio_device_unregister_eventset(struct iio_dev *indio_dev)
 {
-       if (indio_dev->event_interface == NULL)
+       struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
+
+       if (iio_dev_opaque->event_interface == NULL)
                return;
-       iio_free_chan_devattr_list(&indio_dev->event_interface->dev_attr_list);
-       kfree(indio_dev->event_interface->group.attrs);
-       kfree(indio_dev->event_interface);
+       iio_free_chan_devattr_list(&iio_dev_opaque->event_interface->dev_attr_list);
+       kfree(iio_dev_opaque->event_interface->group.attrs);
+       kfree(iio_dev_opaque->event_interface);
 }
index 53d1931..6f16357 100644 (file)
@@ -239,8 +239,8 @@ static void iio_trigger_put_irq(struct iio_trigger *trig, int irq)
  * the relevant function is in there may be the best option.
  */
 /* Worth protecting against double additions? */
-static int iio_trigger_attach_poll_func(struct iio_trigger *trig,
-                                       struct iio_poll_func *pf)
+int iio_trigger_attach_poll_func(struct iio_trigger *trig,
+                                struct iio_poll_func *pf)
 {
        int ret = 0;
        bool notinuse
@@ -290,8 +290,8 @@ out_put_module:
        return ret;
 }
 
-static int iio_trigger_detach_poll_func(struct iio_trigger *trig,
-                                        struct iio_poll_func *pf)
+int iio_trigger_detach_poll_func(struct iio_trigger *trig,
+                                struct iio_poll_func *pf)
 {
        int ret = 0;
        bool no_other_users
@@ -705,17 +705,3 @@ void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev)
        if (indio_dev->trig)
                iio_trigger_put(indio_dev->trig);
 }
-
-int iio_triggered_buffer_postenable(struct iio_dev *indio_dev)
-{
-       return iio_trigger_attach_poll_func(indio_dev->trig,
-                                           indio_dev->pollfunc);
-}
-EXPORT_SYMBOL(iio_triggered_buffer_postenable);
-
-int iio_triggered_buffer_predisable(struct iio_dev *indio_dev)
-{
-       return iio_trigger_detach_poll_func(indio_dev->trig,
-                                            indio_dev->pollfunc);
-}
-EXPORT_SYMBOL(iio_triggered_buffer_predisable);
index 1eafd0b..2be7180 100644 (file)
@@ -178,7 +178,6 @@ static int acpi_als_add(struct acpi_device *device)
        mutex_init(&als->lock);
 
        indio_dev->name = ACPI_ALS_DEVICE_NAME;
-       indio_dev->dev.parent = &device->dev;
        indio_dev->info = &acpi_als_info;
        indio_dev->modes = INDIO_BUFFER_SOFTWARE;
        indio_dev->channels = acpi_als_channels;
index d3269cd..17dac8d 100644 (file)
@@ -259,7 +259,6 @@ static int adjd_s311_probe(struct i2c_client *client,
        i2c_set_clientdata(client, indio_dev);
        data->client = client;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &adjd_s311_info;
        indio_dev->name = ADJD_S311_DRV_NAME;
        indio_dev->channels = adjd_s311_channels;
index b07797a..9aa2869 100644 (file)
@@ -785,7 +785,6 @@ static int adux1020_probe(struct i2c_client *client,
        if (!indio_dev)
                return -ENOMEM;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &adux1020_info;
        indio_dev->name = ADUX1020_DRV_NAME;
        indio_dev->channels = adux1020_channels;
index b1ed765..b4e9924 100644 (file)
@@ -179,7 +179,6 @@ static int al3010_probe(struct i2c_client *client,
        i2c_set_clientdata(client, indio_dev);
        data->client = client;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &al3010_info;
        indio_dev->name = AL3010_DRV_NAME;
        indio_dev->channels = al3010_channels;
index 20ed0a7..cc1407c 100644 (file)
@@ -202,7 +202,6 @@ static int al3320a_probe(struct i2c_client *client,
        i2c_set_clientdata(client, indio_dev);
        data->client = client;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &al3320a_info;
        indio_dev->name = AL3320A_DRV_NAME;
        indio_dev->channels = al3320a_channels;
index 856b6c4..baaf202 100644 (file)
@@ -419,7 +419,6 @@ static int apds9300_probe(struct i2c_client *client,
 
        mutex_init(&data->mutex);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->channels = apds9300_channels;
        indio_dev->num_channels = ARRAY_SIZE(apds9300_channels);
        indio_dev->name = APDS9300_DRV_NAME;
index 52f86bc..9afb3fc 100644 (file)
@@ -1001,7 +1001,6 @@ static int apds9960_probe(struct i2c_client *client,
 
        iio_device_attach_buffer(indio_dev, buffer);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &apds9960_info;
        indio_dev->name = APDS9960_DRV_NAME;
        indio_dev->channels = apds9960_channels;
index adb5ab9..48484b9 100644 (file)
@@ -254,7 +254,6 @@ static int bh1750_probe(struct i2c_client *client,
                return ret;
 
        mutex_init(&data->lock);
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &bh1750_info;
        indio_dev->name = id->name;
        indio_dev->channels = bh1750_channels;
index 03f2d8d..abbf2e6 100644 (file)
@@ -185,7 +185,6 @@ static int bh1780_probe(struct i2c_client *client,
        pm_runtime_use_autosuspend(&client->dev);
        pm_runtime_put(&client->dev);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &bh1780_info;
        indio_dev->name = "bh1780";
        indio_dev->channels = bh1780_channels;
index 160eb3f..5d8333d 100644 (file)
@@ -465,7 +465,6 @@ static int cm32181_probe(struct i2c_client *client)
        cm32181->dev = dev;
 
        mutex_init(&cm32181->lock);
-       indio_dev->dev.parent = dev;
        indio_dev->channels = cm32181_channels;
        indio_dev->num_channels = ARRAY_SIZE(cm32181_channels);
        indio_dev->info = &cm32181_info;
index 8672008..18a4103 100644 (file)
@@ -340,7 +340,6 @@ static int cm3232_probe(struct i2c_client *client,
        i2c_set_clientdata(client, indio_dev);
        chip->client = client;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->channels = cm3232_channels;
        indio_dev->num_channels = ARRAY_SIZE(cm3232_channels);
        indio_dev->info = &cm3232_info;
index 0443861..6d1b0ff 100644 (file)
@@ -231,7 +231,6 @@ static int cm3323_probe(struct i2c_client *client,
 
        mutex_init(&data->mutex);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &cm3323_info;
        indio_dev->name = CM3323_DRV_NAME;
        indio_dev->channels = cm3323_channels;
index 964ede4..4c83953 100644 (file)
@@ -239,7 +239,6 @@ static int cm3605_probe(struct platform_device *pdev)
        led_trigger_register_simple("cm3605", &cm3605->led);
        led_trigger_event(cm3605->led, LED_FULL);
 
-       indio_dev->dev.parent = dev;
        indio_dev->info = &cm3605_info;
        indio_dev->name = "cm3605";
        indio_dev->channels = cm3605_channels;
index 90e38fc..fd83a19 100644 (file)
@@ -662,7 +662,6 @@ static int cm36651_probe(struct i2c_client *client,
        }
 
        mutex_init(&cm36651->lock);
-       indio_dev->dev.parent = &client->dev;
        indio_dev->channels = cm36651_channels;
        indio_dev->num_channels = ARRAY_SIZE(cm36651_channels);
        indio_dev->info = &cm36651_info;
index 2198b50..fed79ba 100644 (file)
@@ -145,8 +145,11 @@ static int cros_ec_light_prox_write(struct iio_dev *indio_dev,
                break;
        case IIO_CHAN_INFO_CALIBSCALE:
                st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
-               st->core.param.sensor_range.data = (val << 16) | (val2 / 100);
+               st->core.curr_range = (val << 16) | (val2 / 100);
+               st->core.param.sensor_range.data = st->core.curr_range;
                ret = cros_ec_motion_send_host_cmd(&st->core, 0);
+               if (ret == 0)
+                       st->core.range_updated = true;
                break;
        default:
                ret = cros_ec_sensors_core_write(&st->core, chan, val, val2,
@@ -256,6 +259,7 @@ MODULE_DEVICE_TABLE(platform, cros_ec_light_prox_ids);
 static struct platform_driver cros_ec_light_prox_platform_driver = {
        .driver = {
                .name   = "cros-ec-light-prox",
+               .pm     = &cros_ec_sensors_pm_ops,
        },
        .probe          = cros_ec_light_prox_probe,
        .id_table       = cros_ec_light_prox_ids,
index 7a2679b..d5e1cd2 100644 (file)
@@ -596,7 +596,6 @@ static int gp2ap002_probe(struct i2c_client *client,
        pm_runtime_use_autosuspend(dev);
        pm_runtime_put(dev);
 
-       indio_dev->dev.parent = dev;
        indio_dev->info = &gp2ap002_info;
        indio_dev->name = "gp2ap002";
        indio_dev->channels = gp2ap002_channels;
index 070d4cd..e2850c1 100644 (file)
@@ -1390,12 +1390,6 @@ static int gp2ap020a00f_buffer_postenable(struct iio_dev *indio_dev)
 
        mutex_lock(&data->lock);
 
-       err = iio_triggered_buffer_postenable(indio_dev);
-       if (err < 0) {
-               mutex_unlock(&data->lock);
-               return err;
-       }
-
        /*
         * Enable triggers according to the scan_mask. Enabling either
         * LIGHT_CLEAR or LIGHT_IR scan mode results in enabling ALS
@@ -1430,8 +1424,6 @@ static int gp2ap020a00f_buffer_postenable(struct iio_dev *indio_dev)
                err = -ENOMEM;
 
 error_unlock:
-       if (err < 0)
-               iio_triggered_buffer_predisable(indio_dev);
        mutex_unlock(&data->lock);
 
        return err;
@@ -1465,8 +1457,6 @@ static int gp2ap020a00f_buffer_predisable(struct iio_dev *indio_dev)
        if (err == 0)
                kfree(data->buffer);
 
-       iio_triggered_buffer_predisable(indio_dev);
-
        mutex_unlock(&data->lock);
 
        return err;
@@ -1527,7 +1517,6 @@ static int gp2ap020a00f_probe(struct i2c_client *client,
        init_waitqueue_head(&data->data_ready_queue);
 
        mutex_init(&data->lock);
-       indio_dev->dev.parent = &client->dev;
        indio_dev->channels = gp2ap020a00f_channels;
        indio_dev->num_channels = ARRAY_SIZE(gp2ap020a00f_channels);
        indio_dev->info = &gp2ap020a00f_info;
index 81fa2a4..a21c827 100644 (file)
@@ -301,7 +301,6 @@ static int hid_als_probe(struct platform_device *pdev)
 
        indio_dev->num_channels =
                                ARRAY_SIZE(als_channels);
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->info = &als_info;
        indio_dev->name = name;
        indio_dev->modes = INDIO_DIRECT_MODE;
index e9c04df..330cf35 100644 (file)
@@ -279,7 +279,6 @@ static int hid_prox_probe(struct platform_device *pdev)
        }
 
        indio_dev->num_channels = ARRAY_SIZE(prox_channels);
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->info = &prox_info;
        indio_dev->name = name;
        indio_dev->modes = INDIO_DIRECT_MODE;
index b2988a7..004ea89 100644 (file)
@@ -36,6 +36,7 @@
 
 struct iqs621_als_private {
        struct iqs62x_core *iqs62x;
+       struct iio_dev *indio_dev;
        struct notifier_block notifier;
        struct mutex lock;
        bool light_en;
@@ -103,7 +104,7 @@ static int iqs621_als_notifier(struct notifier_block *notifier,
 
        iqs621_als = container_of(notifier, struct iqs621_als_private,
                                  notifier);
-       indio_dev = iio_priv_to_dev(iqs621_als);
+       indio_dev = iqs621_als->indio_dev;
        timestamp = iio_get_time_ns(indio_dev);
 
        mutex_lock(&iqs621_als->lock);
@@ -191,7 +192,7 @@ err_mutex:
 static void iqs621_als_notifier_unregister(void *context)
 {
        struct iqs621_als_private *iqs621_als = context;
-       struct iio_dev *indio_dev = iio_priv_to_dev(iqs621_als);
+       struct iio_dev *indio_dev = iqs621_als->indio_dev;
        int ret;
 
        ret = blocking_notifier_chain_unregister(&iqs621_als->iqs62x->nh,
@@ -551,6 +552,7 @@ static int iqs621_als_probe(struct platform_device *pdev)
 
        iqs621_als = iio_priv(indio_dev);
        iqs621_als->iqs62x = iqs62x;
+       iqs621_als->indio_dev = indio_dev;
 
        if (iqs62x->dev_desc->prod_num == IQS622_PROD_NUM) {
                ret = regmap_read(iqs62x->regmap, IQS622_IR_THRESH_TOUCH,
@@ -580,7 +582,6 @@ static int iqs621_als_probe(struct platform_device *pdev)
        }
 
        indio_dev->modes = INDIO_DIRECT_MODE;
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->name = iqs62x->dev_desc->dev_name;
        indio_dev->info = &iqs621_als_info;
 
index 805a74f..ac8ad0f 100644 (file)
@@ -782,7 +782,6 @@ static int isl29018_probe(struct i2c_client *client,
        indio_dev->channels = isl29018_chip_info_tbl[dev_id].channels;
        indio_dev->num_channels = isl29018_chip_info_tbl[dev_id].num_channels;
        indio_dev->name = name;
-       indio_dev->dev.parent = &client->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
        return devm_iio_device_register(&client->dev, indio_dev);
index 4d220c8..2f8b494 100644 (file)
@@ -620,7 +620,6 @@ static int isl29028_probe(struct i2c_client *client,
        indio_dev->channels = isl29028_channels;
        indio_dev->num_channels = ARRAY_SIZE(isl29028_channels);
        indio_dev->name = id->name;
-       indio_dev->dev.parent = &client->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
        pm_runtime_enable(&client->dev);
index 95611f5..b93b85d 100644 (file)
@@ -216,36 +216,20 @@ static const struct iio_info isl29125_info = {
 static int isl29125_buffer_postenable(struct iio_dev *indio_dev)
 {
        struct isl29125_data *data = iio_priv(indio_dev);
-       int err;
-
-       err = iio_triggered_buffer_postenable(indio_dev);
-       if (err)
-               return err;
 
        data->conf1 |= ISL29125_MODE_RGB;
-       err = i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
+       return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
                data->conf1);
-       if (err) {
-               iio_triggered_buffer_predisable(indio_dev);
-               return err;
-       }
-
-       return 0;
 }
 
 static int isl29125_buffer_predisable(struct iio_dev *indio_dev)
 {
        struct isl29125_data *data = iio_priv(indio_dev);
-       int ret;
 
        data->conf1 &= ~ISL29125_MODE_MASK;
        data->conf1 |= ISL29125_MODE_PD;
-       ret = i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
+       return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
                data->conf1);
-
-       iio_triggered_buffer_predisable(indio_dev);
-
-       return ret;
 }
 
 static const struct iio_buffer_setup_ops isl29125_buffer_setup_ops = {
@@ -268,7 +252,6 @@ static int isl29125_probe(struct i2c_client *client,
        i2c_set_clientdata(client, indio_dev);
        data->client = client;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &isl29125_info;
        indio_dev->name = ISL29125_DRV_NAME;
        indio_dev->channels = isl29125_channels;
index 13deeeb..724a0ec 100644 (file)
@@ -338,7 +338,6 @@ static int jsa1212_probe(struct i2c_client *client,
        if (ret < 0)
                return ret;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->channels = jsa1212_channels;
        indio_dev->num_channels = ARRAY_SIZE(jsa1212_channels);
        indio_dev->name = JSA1212_DRIVER_NAME;
index bc196c2..8a62124 100644 (file)
@@ -852,7 +852,7 @@ static int lm3533_als_probe(struct platform_device *pdev)
        indio_dev->channels = lm3533_als_channels;
        indio_dev->num_channels = ARRAY_SIZE(lm3533_als_channels);
        indio_dev->name = dev_name(&pdev->dev);
-       indio_dev->dev.parent = pdev->dev.parent;
+       iio_device_set_parent(indio_dev, pdev->dev.parent);
        indio_dev->modes = INDIO_DIRECT_MODE;
 
        als = iio_priv(indio_dev);
index 5a3fcb1..4bac064 100644 (file)
@@ -1480,7 +1480,6 @@ static int ltr501_probe(struct i2c_client *client,
        if ((partid >> 4) != data->chip_info->partid)
                return -ENODEV;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = data->chip_info->info;
        indio_dev->channels = data->chip_info->channels;
        indio_dev->num_channels = data->chip_info->no_channels;
index 55b8e28..c2aef88 100644 (file)
@@ -7,7 +7,7 @@
  *
  * 7-bit I2C slave address: 0x13
  *
- * Link to data sheet: http://www.onsemi.com/pub/Collateral/LV0104CS-D.PDF
+ * Link to data sheet: https://www.onsemi.com/pub/Collateral/LV0104CS-D.PDF
  */
 
 #include <linux/kernel.h>
@@ -502,7 +502,6 @@ static int lv0104cs_probe(struct i2c_client *client,
                return ret;
 
        indio_dev->modes = INDIO_DIRECT_MODE;
-       indio_dev->dev.parent = &client->dev;
        indio_dev->channels = lv0104cs_channels;
        indio_dev->num_channels = ARRAY_SIZE(lv0104cs_channels);
        indio_dev->name = client->name;
index d6d8007..aa8ed1e 100644 (file)
@@ -538,7 +538,6 @@ static int max44000_probe(struct i2c_client *client,
 
        i2c_set_clientdata(client, indio_dev);
        mutex_init(&data->lock);
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &max44000_info;
        indio_dev->name = MAX44000_DRV_NAME;
        indio_dev->channels = max44000_channels;
index 00ba154..801e5a0 100644 (file)
@@ -501,7 +501,6 @@ static int max44009_probe(struct i2c_client *client,
        data = iio_priv(indio_dev);
        i2c_set_clientdata(client, indio_dev);
        data->client = client;
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &max44009_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->name = MAX44009_DRV_NAME;
index 5ebfbc5..a308fbc 100644 (file)
@@ -270,7 +270,6 @@ static int noa1305_probe(struct i2c_client *client,
                return ret;
        }
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &noa1305_info;
        indio_dev->channels = noa1305_channels;
        indio_dev->num_channels = ARRAY_SIZE(noa1305_channels);
index 82abfa5..2d48d61 100644 (file)
@@ -2,7 +2,7 @@
 /**
  * opt3001.c - Texas Instruments OPT3001 Light Sensor
  *
- * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
+ * Copyright (C) 2014 Texas Instruments Incorporated - https://www.ti.com
  *
  * Author: Andreas Dannenberg <dannenberg@ti.com>
  * Based on previous work from: Felipe Balbi <balbi@ti.com>
@@ -768,7 +768,6 @@ static int opt3001_probe(struct i2c_client *client,
        iio->name = client->name;
        iio->channels = opt3001_channels;
        iio->num_channels = ARRAY_SIZE(opt3001_channels);
-       iio->dev.parent = dev;
        iio->modes = INDIO_DIRECT_MODE;
        iio->info = &opt3001_info;
 
index 0295783..bfade65 100644 (file)
@@ -362,7 +362,6 @@ static int pa12203001_probe(struct i2c_client *client,
 
        mutex_init(&data->lock);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &pa12203001_info;
        indio_dev->name = PA12203001_DRIVER_NAME;
        indio_dev->channels = pa12203001_channels;
index a0a7aea..aa2972b 100644 (file)
@@ -570,8 +570,6 @@ static int rpr0521_buffer_postdisable(struct iio_dev *indio_dev)
 
 static const struct iio_buffer_setup_ops rpr0521_buffer_setup_ops = {
        .preenable = rpr0521_buffer_preenable,
-       .postenable = iio_triggered_buffer_postenable,
-       .predisable = iio_triggered_buffer_predisable,
        .postdisable = rpr0521_buffer_postdisable,
 };
 
@@ -948,7 +946,6 @@ static int rpr0521_probe(struct i2c_client *client,
 
        mutex_init(&data->lock);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &rpr0521_info;
        indio_dev->name = RPR0521_DRV_NAME;
        indio_dev->channels = rpr0521_channels;
index c1adab2..c280b41 100644 (file)
@@ -1015,7 +1015,6 @@ static int si1133_probe(struct i2c_client *client,
        i2c_set_clientdata(client, iio_dev);
        data->client = client;
 
-       iio_dev->dev.parent = &client->dev;
        iio_dev->name = id->name;
        iio_dev->channels = si1133_channels;
        iio_dev->num_channels = ARRAY_SIZE(si1133_channels);
index 0476c2b..521e8ad 100644 (file)
@@ -1171,8 +1171,6 @@ static bool si1145_validate_scan_mask(struct iio_dev *indio_dev,
 
 static const struct iio_buffer_setup_ops si1145_buffer_setup_ops = {
        .preenable = si1145_buffer_preenable,
-       .postenable = iio_triggered_buffer_postenable,
-       .predisable = iio_triggered_buffer_predisable,
        .validate_scan_mask = si1145_validate_scan_mask,
 };
 
@@ -1307,7 +1305,6 @@ static int si1145_probe(struct i2c_client *client,
                return -ENODEV;
        }
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->name = id->name;
        indio_dev->channels = data->part_info->channels;
        indio_dev->num_channels = data->part_info->num_channels;
index d262c25..a18a82e 100644 (file)
@@ -227,8 +227,6 @@ static int st_uvis25_buffer_postdisable(struct iio_dev *iio_dev)
 
 static const struct iio_buffer_setup_ops st_uvis25_buffer_ops = {
        .preenable = st_uvis25_buffer_preenable,
-       .postenable = iio_triggered_buffer_postenable,
-       .predisable = iio_triggered_buffer_predisable,
        .postdisable = st_uvis25_buffer_postdisable,
 };
 
@@ -303,7 +301,6 @@ int st_uvis25_probe(struct device *dev, int irq, struct regmap *regmap)
                return err;
 
        iio_dev->modes = INDIO_DIRECT_MODE;
-       iio_dev->dev.parent = dev;
        iio_dev->channels = st_uvis25_channels;
        iio_dev->num_channels = ARRAY_SIZE(st_uvis25_channels);
        iio_dev->name = ST_UVIS25_DEV_NAME;
index 185c24a..9e15939 100644 (file)
@@ -487,7 +487,7 @@ static bool stk3310_is_volatile_reg(struct device *dev, unsigned int reg)
        }
 }
 
-static struct regmap_config stk3310_regmap_config = {
+static const struct regmap_config stk3310_regmap_config = {
        .name = STK3310_REGMAP_NAME,
        .reg_bits = 8,
        .val_bits = 8,
@@ -585,7 +585,6 @@ static int stk3310_probe(struct i2c_client *client,
        if (ret < 0)
                return ret;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &stk3310_info;
        indio_dev->name = STK3310_DRIVER_NAME;
        indio_dev->modes = INDIO_DIRECT_MODE;
index b542e56..6fe5d46 100644 (file)
@@ -243,35 +243,19 @@ static const struct iio_info tcs3414_info = {
 static int tcs3414_buffer_postenable(struct iio_dev *indio_dev)
 {
        struct tcs3414_data *data = iio_priv(indio_dev);
-       int ret;
-
-       ret = iio_triggered_buffer_postenable(indio_dev);
-       if (ret)
-               return ret;
 
        data->control |= TCS3414_CONTROL_ADC_EN;
-       ret = i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
+       return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
                data->control);
-       if (ret)
-               iio_triggered_buffer_predisable(indio_dev);
-
-       return ret;
 }
 
 static int tcs3414_buffer_predisable(struct iio_dev *indio_dev)
 {
        struct tcs3414_data *data = iio_priv(indio_dev);
-       int ret, ret2;
 
        data->control &= ~TCS3414_CONTROL_ADC_EN;
-       ret = i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
+       return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
                data->control);
-
-       ret2 = iio_triggered_buffer_predisable(indio_dev);
-       if (!ret)
-               ret = ret2;
-
-       return ret;
 }
 
 static const struct iio_buffer_setup_ops tcs3414_buffer_setup_ops = {
@@ -294,7 +278,6 @@ static int tcs3414_probe(struct i2c_client *client,
        i2c_set_clientdata(client, indio_dev);
        data->client = client;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &tcs3414_info;
        indio_dev->name = TCS3414_DRV_NAME;
        indio_dev->channels = tcs3414_channels;
index 12ad344..a0dc447 100644 (file)
@@ -454,7 +454,6 @@ static int tcs3472_probe(struct i2c_client *client,
        data->client = client;
        mutex_init(&data->lock);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &tcs3472_info;
        indio_dev->name = TCS3472_DRV_NAME;
        indio_dev->channels = tcs3472_channels;
index 27a5c28..abc8d7d 100644 (file)
@@ -713,7 +713,7 @@ static int tsl2563_probe(struct i2c_client *client,
 
        chip = iio_priv(indio_dev);
 
-       i2c_set_clientdata(client, chip);
+       i2c_set_clientdata(client, indio_dev);
        chip->client = client;
 
        err = tsl2563_detect(chip);
@@ -750,7 +750,6 @@ static int tsl2563_probe(struct i2c_client *client,
        indio_dev->name = client->name;
        indio_dev->channels = tsl2563_channels;
        indio_dev->num_channels = ARRAY_SIZE(tsl2563_channels);
-       indio_dev->dev.parent = &client->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
        if (client->irq)
@@ -797,8 +796,8 @@ fail:
 
 static int tsl2563_remove(struct i2c_client *client)
 {
-       struct tsl2563_chip *chip = i2c_get_clientdata(client);
-       struct iio_dev *indio_dev = iio_priv_to_dev(chip);
+       struct iio_dev *indio_dev = i2c_get_clientdata(client);
+       struct tsl2563_chip *chip = iio_priv(indio_dev);
 
        iio_device_unregister(indio_dev);
        if (!chip->int_enabled)
@@ -816,7 +815,8 @@ static int tsl2563_remove(struct i2c_client *client)
 #ifdef CONFIG_PM_SLEEP
 static int tsl2563_suspend(struct device *dev)
 {
-       struct tsl2563_chip *chip = i2c_get_clientdata(to_i2c_client(dev));
+       struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+       struct tsl2563_chip *chip = iio_priv(indio_dev);
        int ret;
 
        mutex_lock(&chip->lock);
@@ -834,7 +834,8 @@ out:
 
 static int tsl2563_resume(struct device *dev)
 {
-       struct tsl2563_chip *chip = i2c_get_clientdata(to_i2c_client(dev));
+       struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+       struct tsl2563_chip *chip = iio_priv(indio_dev);
        int ret;
 
        mutex_lock(&chip->lock);
index a760d14..9e5490b 100644 (file)
@@ -840,7 +840,6 @@ static int tsl2583_probe(struct i2c_client *clientp,
        indio_dev->info = &tsl2583_info;
        indio_dev->channels = tsl2583_channels;
        indio_dev->num_channels = ARRAY_SIZE(tsl2583_channels);
-       indio_dev->dev.parent = &clientp->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->name = chip->client->name;
 
index 9fbde9b..7353994 100644 (file)
@@ -1833,7 +1833,6 @@ static int tsl2772_probe(struct i2c_client *clientp,
                &tsl2772_chip_info_tbl[device_channel_config[id->driver_data]];
 
        indio_dev->info = chip->chip_info->info;
-       indio_dev->dev.parent = &clientp->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->name = chip->client->name;
        indio_dev->num_channels = chip->chip_info->chan_table_elements;
index 0dfc664..70505ba 100644 (file)
@@ -192,7 +192,6 @@ static int tsl4531_probe(struct i2c_client *client,
        if (ret < 0)
                return ret;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &tsl4531_info;
        indio_dev->channels = tsl4531_channels;
        indio_dev->num_channels = ARRAY_SIZE(tsl4531_channels);
index b995f21..2f2e79f 100644 (file)
@@ -851,7 +851,6 @@ static int us5182d_probe(struct i2c_client *client,
 
        mutex_init(&data->lock);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &us5182d_info;
        indio_dev->name = US5182D_DRV_NAME;
        indio_dev->channels = us5182d_channels;
index 2a4b3d3..fff4b36 100644 (file)
@@ -957,50 +957,29 @@ static int vcnl4010_buffer_postenable(struct iio_dev *indio_dev)
        int ret;
        int cmd;
 
-       ret = iio_triggered_buffer_postenable(indio_dev);
-       if (ret)
-               return ret;
-
        /* Do not enable the buffer if we are already capturing events. */
-       if (vcnl4010_is_in_periodic_mode(data)) {
-               ret = -EBUSY;
-               goto end;
-       }
+       if (vcnl4010_is_in_periodic_mode(data))
+               return -EBUSY;
 
        ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL,
                                        VCNL4010_INT_PROX_EN);
        if (ret < 0)
-               goto end;
+               return ret;
 
        cmd = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN;
-       ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, cmd);
-       if (ret < 0)
-               goto end;
-
-       return 0;
-end:
-       iio_triggered_buffer_predisable(indio_dev);
-
-       return ret;
+       return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, cmd);
 }
 
 static int vcnl4010_buffer_predisable(struct iio_dev *indio_dev)
 {
        struct vcnl4000_data *data = iio_priv(indio_dev);
-       int ret, ret_disable;
+       int ret;
 
        ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, 0);
        if (ret < 0)
-               goto end;
-
-       ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 0);
-
-end:
-       ret_disable = iio_triggered_buffer_predisable(indio_dev);
-       if (ret == 0)
-               ret = ret_disable;
+               return ret;
 
-       return ret;
+       return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 0);
 }
 
 static const struct iio_buffer_setup_ops vcnl4010_buffer_ops = {
@@ -1058,7 +1037,6 @@ static int vcnl4000_probe(struct i2c_client *client,
                                     &data->near_level))
                data->near_level = 0;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = data->chip_spec->info;
        indio_dev->channels = data->chip_spec->channels;
        indio_dev->num_channels = data->chip_spec->num_channels;
index cca4db3..765c44a 100644 (file)
@@ -564,7 +564,6 @@ static int vcnl4035_probe(struct i2c_client *client,
        data->client = client;
        data->regmap = regmap;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &vcnl4035_info;
        indio_dev->name = VCNL4035_DRV_NAME;
        indio_dev->channels = vcnl4035_channels;
index aa25b87..de85c9b 100644 (file)
@@ -814,7 +814,6 @@ static int veml6030_probe(struct i2c_client *client,
        data->client = client;
        data->regmap = regmap;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->name = "veml6030";
        indio_dev->channels = veml6030_channels;
        indio_dev->num_channels = ARRAY_SIZE(veml6030_channels);
index 0be553a..1e55e09 100644 (file)
@@ -151,7 +151,6 @@ static int veml6070_probe(struct i2c_client *client,
        data->client1 = client;
        mutex_init(&data->lock);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &veml6070_info;
        indio_dev->channels = veml6070_channels;
        indio_dev->num_channels = ARRAY_SIZE(veml6070_channels);
index ed7b027..4775bd7 100644 (file)
@@ -509,7 +509,6 @@ static int vl6180_probe(struct i2c_client *client,
        data->client = client;
        mutex_init(&data->lock);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &vl6180_info;
        indio_dev->channels = vl6180_channels;
        indio_dev->num_channels = ARRAY_SIZE(vl6180_channels);
index 80ae530..e0bc9df 100644 (file)
@@ -527,7 +527,6 @@ static int zopt2201_probe(struct i2c_client *client,
        data->client = client;
        mutex_init(&data->lock);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &zopt2201_info;
        indio_dev->channels = zopt2201_channels;
        indio_dev->num_channels = ARRAY_SIZE(zopt2201_channels);
index 810fdfd..c2260c8 100644 (file)
@@ -892,7 +892,6 @@ static int ak8974_probe(struct i2c_client *i2c,
        pm_runtime_use_autosuspend(&i2c->dev);
        pm_runtime_put(&i2c->dev);
 
-       indio_dev->dev.parent = &i2c->dev;
        switch (ak8974->variant) {
        case AK8974_WHOAMI_VALUE_AMI306:
        case AK8974_WHOAMI_VALUE_AMI305:
index 3c88154..03d71f7 100644 (file)
@@ -358,6 +358,7 @@ struct ak8975_data {
        u8                      asa[3];
        long                    raw_to_gauss[3];
        struct gpio_desc        *eoc_gpiod;
+       struct gpio_desc        *reset_gpiod;
        int                     eoc_irq;
        wait_queue_head_t       data_ready_queue;
        unsigned long           flags;
@@ -384,10 +385,13 @@ static int ak8975_power_on(const struct ak8975_data *data)
                         "Failed to enable specified Vid supply\n");
                return ret;
        }
+
+       gpiod_set_value_cansleep(data->reset_gpiod, 0);
+
        /*
-        * According to the datasheet the power supply rise time i 200us
+        * According to the datasheet the power supply rise time is 200us
         * and the minimum wait time before mode setting is 100us, in
-        * total 300 us. Add some margin and say minimum 500us here.
+        * total 300us. Add some margin and say minimum 500us here.
         */
        usleep_range(500, 1000);
        return 0;
@@ -396,6 +400,8 @@ static int ak8975_power_on(const struct ak8975_data *data)
 /* Disable attached power regulator if any. */
 static void ak8975_power_off(const struct ak8975_data *data)
 {
+       gpiod_set_value_cansleep(data->reset_gpiod, 1);
+
        regulator_disable(data->vid);
        regulator_disable(data->vdd);
 }
@@ -839,6 +845,7 @@ static int ak8975_probe(struct i2c_client *client,
        struct ak8975_data *data;
        struct iio_dev *indio_dev;
        struct gpio_desc *eoc_gpiod;
+       struct gpio_desc *reset_gpiod;
        const void *match;
        unsigned int i;
        int err;
@@ -856,6 +863,16 @@ static int ak8975_probe(struct i2c_client *client,
        if (eoc_gpiod)
                gpiod_set_consumer_name(eoc_gpiod, "ak_8975");
 
+       /*
+        * According to AK09911 datasheet, if reset GPIO is provided then
+        * deassert reset on ak8975_power_on() and assert reset on
+        * ak8975_power_off().
+        */
+       reset_gpiod = devm_gpiod_get_optional(&client->dev,
+                                             "reset", GPIOD_OUT_HIGH);
+       if (IS_ERR(reset_gpiod))
+               return PTR_ERR(reset_gpiod);
+
        /* Register with IIO */
        indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
        if (indio_dev == NULL)
@@ -866,6 +883,7 @@ static int ak8975_probe(struct i2c_client *client,
 
        data->client = client;
        data->eoc_gpiod = eoc_gpiod;
+       data->reset_gpiod = reset_gpiod;
        data->eoc_irq = 0;
 
        err = iio_read_mount_matrix(&client->dev, "mount-matrix", &data->orientation);
@@ -922,7 +940,6 @@ static int ak8975_probe(struct i2c_client *client,
        }
 
        mutex_init(&data->lock);
-       indio_dev->dev.parent = &client->dev;
        indio_dev->channels = ak8975_channels;
        indio_dev->num_channels = ARRAY_SIZE(ak8975_channels);
        indio_dev->info = &ak8975_info;
index d4de167..fc6840f 100644 (file)
@@ -836,8 +836,6 @@ static int bmc150_magn_buffer_postdisable(struct iio_dev *indio_dev)
 
 static const struct iio_buffer_setup_ops bmc150_magn_buffer_setup_ops = {
        .preenable = bmc150_magn_buffer_preenable,
-       .postenable = iio_triggered_buffer_postenable,
-       .predisable = iio_triggered_buffer_predisable,
        .postdisable = bmc150_magn_buffer_postdisable,
 };
 
@@ -883,7 +881,6 @@ int bmc150_magn_probe(struct device *dev, struct regmap *regmap,
        if (ret < 0)
                return ret;
 
-       indio_dev->dev.parent = dev;
        indio_dev->channels = bmc150_magn_channels;
        indio_dev->num_channels = ARRAY_SIZE(bmc150_magn_channels);
        indio_dev->available_scan_masks = bmc150_magn_scan_masks;
index fb45b63..876e960 100644 (file)
@@ -58,7 +58,8 @@ MODULE_DEVICE_TABLE(i2c, bmc150_magn_i2c_id);
 static const struct of_device_id bmc150_magn_of_match[] = {
        { .compatible = "bosch,bmc150_magn" },
        { .compatible = "bosch,bmc156_magn" },
-       { .compatible = "bosch,bmm150_magn" },
+       { .compatible = "bosch,bmm150_magn" }, /* deprecated compatible */
+       { .compatible = "bosch,bmm150" },
        { }
 };
 MODULE_DEVICE_TABLE(of, bmc150_magn_of_match);
index 0c09daf..97642eb 100644 (file)
@@ -512,7 +512,6 @@ static int hid_magn_3d_probe(struct platform_device *pdev)
 
        indio_dev->channels = channels;
        indio_dev->num_channels = chan_count;
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->info = &magn_3d_info;
        indio_dev->name = name;
        indio_dev->modes = INDIO_DIRECT_MODE;
index c44a429..1474ba6 100644 (file)
@@ -642,7 +642,6 @@ int hmc5843_common_probe(struct device *dev, struct regmap *regmap,
        if (ret)
                return ret;
 
-       indio_dev->dev.parent = dev;
        indio_dev->name = name;
        indio_dev->info = &hmc5843_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index fb16cfd..4d305a2 100644 (file)
@@ -519,7 +519,6 @@ static int mag3110_probe(struct i2c_client *client,
        i2c_set_clientdata(client, indio_dev);
        indio_dev->info = &mag3110_info;
        indio_dev->name = id->name;
-       indio_dev->dev.parent = &client->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = mag3110_channels;
        indio_dev->num_channels = ARRAY_SIZE(mag3110_channels);
index 1787d65..29a08d7 100644 (file)
@@ -459,7 +459,7 @@ static bool mmc35240_is_volatile_reg(struct device *dev, unsigned int reg)
        }
 }
 
-static struct reg_default mmc35240_reg_defaults[] = {
+static const struct reg_default mmc35240_reg_defaults[] = {
        { MMC35240_REG_CTRL0,  0x00 },
        { MMC35240_REG_CTRL1,  0x00 },
 };
@@ -507,7 +507,6 @@ static int mmc35240_probe(struct i2c_client *client,
 
        mutex_init(&data->mutex);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &mmc35240_info;
        indio_dev->name = MMC35240_DRV_NAME;
        indio_dev->channels = mmc35240_channels;
index 43a2e42..7242897 100644 (file)
@@ -463,8 +463,6 @@ static int rm3100_buffer_postdisable(struct iio_dev *indio_dev)
 
 static const struct iio_buffer_setup_ops rm3100_buffer_ops = {
        .preenable = rm3100_buffer_preenable,
-       .postenable = iio_triggered_buffer_postenable,
-       .predisable = iio_triggered_buffer_predisable,
        .postdisable = rm3100_buffer_postdisable,
 };
 
@@ -549,7 +547,6 @@ int rm3100_common_probe(struct device *dev, struct regmap *regmap, int irq)
 
        mutex_init(&data->lock);
 
-       indio_dev->dev.parent = dev;
        indio_dev->name = "rm3100";
        indio_dev->info = &rm3100_info;
        indio_dev->channels = rm3100_channels;
index bb425c1..4917721 100644 (file)
@@ -31,34 +31,12 @@ int st_magn_trig_set_state(struct iio_trigger *trig, bool state)
 
 static int st_magn_buffer_postenable(struct iio_dev *indio_dev)
 {
-       int err;
-
-       err = iio_triggered_buffer_postenable(indio_dev);
-       if (err < 0)
-               return err;
-
-       err = st_sensors_set_enable(indio_dev, true);
-       if (err < 0)
-               goto st_magn_buffer_predisable;
-
-       return 0;
-
-st_magn_buffer_predisable:
-       iio_triggered_buffer_predisable(indio_dev);
-       return err;
+       return st_sensors_set_enable(indio_dev, true);
 }
 
 static int st_magn_buffer_predisable(struct iio_dev *indio_dev)
 {
-       int err, err2;
-
-       err = st_sensors_set_enable(indio_dev, false);
-
-       err2 = iio_triggered_buffer_predisable(indio_dev);
-       if (!err)
-               err = err2;
-
-       return err;
+       return st_sensors_set_enable(indio_dev, false);
 }
 
 static const struct iio_buffer_setup_ops st_magn_buffer_setup_ops = {
index 0422ef5..6910218 100644 (file)
@@ -395,7 +395,6 @@ static int mux_probe(struct platform_device *pdev)
        mux->cached_state = -1;
 
        indio_dev->name = dev_name(dev);
-       indio_dev->dev.parent = dev;
        indio_dev->info = &mux_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = mux->chan;
index 6aac8be..ae132a9 100644 (file)
@@ -339,7 +339,6 @@ static int hid_incl_3d_probe(struct platform_device *pdev)
        }
 
        indio_dev->num_channels = ARRAY_SIZE(incl_3d_channels);
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->info = &incl_3d_info;
        indio_dev->name = name;
        indio_dev->modes = INDIO_DIRECT_MODE;
index b99f412..23bc61a 100644 (file)
@@ -281,7 +281,6 @@ static int hid_dev_rot_probe(struct platform_device *pdev)
        }
 
        indio_dev->num_channels = ARRAY_SIZE(dev_rot_channels);
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->info = &dev_rot_info;
        indio_dev->name = name;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 77096c3..4d74523 100644 (file)
@@ -23,6 +23,7 @@
 
 struct iqs624_pos_private {
        struct iqs62x_core *iqs62x;
+       struct iio_dev *indio_dev;
        struct notifier_block notifier;
        struct mutex lock;
        bool angle_en;
@@ -59,7 +60,7 @@ static int iqs624_pos_notifier(struct notifier_block *notifier,
 
        iqs624_pos = container_of(notifier, struct iqs624_pos_private,
                                  notifier);
-       indio_dev = iio_priv_to_dev(iqs624_pos);
+       indio_dev = iqs624_pos->indio_dev;
        timestamp = iio_get_time_ns(indio_dev);
 
        iqs62x = iqs624_pos->iqs62x;
@@ -98,7 +99,7 @@ static int iqs624_pos_notifier(struct notifier_block *notifier,
 static void iqs624_pos_notifier_unregister(void *context)
 {
        struct iqs624_pos_private *iqs624_pos = context;
-       struct iio_dev *indio_dev = iio_priv_to_dev(iqs624_pos);
+       struct iio_dev *indio_dev = iqs624_pos->indio_dev;
        int ret;
 
        ret = blocking_notifier_chain_unregister(&iqs624_pos->iqs62x->nh,
@@ -243,9 +244,9 @@ static int iqs624_pos_probe(struct platform_device *pdev)
 
        iqs624_pos = iio_priv(indio_dev);
        iqs624_pos->iqs62x = iqs62x;
+       iqs624_pos->indio_dev = indio_dev;
 
        indio_dev->modes = INDIO_DIRECT_MODE;
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->channels = iqs624_pos_channels;
        indio_dev->num_channels = ARRAY_SIZE(iqs624_pos_channels);
        indio_dev->name = iqs62x->dev_desc->dev_name;
index 154f9a5..933afcf 100644 (file)
@@ -3,7 +3,7 @@
  * Analog Devices AD5272 digital potentiometer driver
  * Copyright (C) 2018 Phil Reid <preid@electromag.com.au>
  *
- * Datasheet: http://www.analog.com/media/en/technical-documentation/data-sheets/AD5272_5274.pdf
+ * Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/AD5272_5274.pdf
  *
  * DEVID       #Wipers #Positions      Resistor Opts (kOhm)    i2c address
  * ad5272      1       1024            20, 50, 100             01011xx
@@ -184,7 +184,6 @@ static int ad5272_probe(struct i2c_client *client,
        if (ret < 0)
                return -ENODEV;
 
-       indio_dev->dev.parent = dev;
        indio_dev->info = &ad5272_info;
        indio_dev->channels = &ad5272_channel;
        indio_dev->num_channels = 1;
index d0de782..5c061ab 100644 (file)
@@ -126,7 +126,6 @@ static int ds1803_probe(struct i2c_client *client,
        data->client = client;
        data->cfg = &ds1803_cfg[id->driver_data];
 
-       indio_dev->dev.parent = dev;
        indio_dev->info = &ds1803_info;
        indio_dev->channels = ds1803_channels;
        indio_dev->num_channels = ARRAY_SIZE(ds1803_channels);
index 641b182..280de9c 100644 (file)
@@ -102,7 +102,6 @@ static int max5432_probe(struct i2c_client *client,
        data->client = client;
        data->ohm = (unsigned long)of_device_get_match_data(dev);
 
-       indio_dev->dev.parent = dev;
        indio_dev->info = &max5432_info;
        indio_dev->channels = max5432_channels;
        indio_dev->num_channels = ARRAY_SIZE(max5432_channels);
index 732375b..5f59881 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright 2016 Rockwell Collins
  *
  * Datasheet:
- * http://datasheets.maximintegrated.com/en/ds/MAX5481-MAX5484.pdf
+ * https://datasheets.maximintegrated.com/en/ds/MAX5481-MAX5484.pdf
  */
 
 #include <linux/acpi.h>
@@ -149,7 +149,6 @@ static int max5481_probe(struct spi_device *spi)
                data->cfg = &max5481_cfg[id->driver_data];
 
        indio_dev->name = id->name;
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
        /* variant specific configuration */
index 68ff806..7ec5197 100644 (file)
@@ -100,7 +100,6 @@ static int max5487_spi_probe(struct spi_device *spi)
 
        indio_dev->info = &max5487_info;
        indio_dev->name = id->name;
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = max5487_channels;
        indio_dev->num_channels = ARRAY_SIZE(max5487_channels);
index 62151b2..fd0579a 100644 (file)
@@ -165,7 +165,6 @@ static int mcp4018_probe(struct i2c_client *client)
        if (!data->cfg)
                data->cfg = &mcp4018_cfg[i2c_match_id(mcp4018_id, client)->driver_data];
 
-       indio_dev->dev.parent = dev;
        indio_dev->info = &mcp4018_info;
        indio_dev->channels = &mcp4018_channel;
        indio_dev->num_channels = 1;
index 2368b39..79ccac6 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright (c) 2018 Chris Coffey <cmc@babblebit.net>
  * Based on: Slawomir Stepien's code from mcp4131.c
  *
- * Datasheet: http://ww1.microchip.com/downloads/en/devicedoc/11195c.pdf
+ * Datasheet: https://ww1.microchip.com/downloads/en/devicedoc/11195c.pdf
  *
  * DEVID       #Wipers #Positions      Resistance (kOhm)
  * mcp41010    1       256             10
@@ -152,7 +152,6 @@ static int mcp41010_probe(struct spi_device *spi)
 
        mutex_init(&data->lock);
 
-       indio_dev->dev.parent = dev;
        indio_dev->info = &mcp41010_info;
        indio_dev->channels = mcp41010_channels;
        indio_dev->num_channels = data->cfg->wipers;
index 98df91e..2923ce2 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright (c) 2016 Slawomir Stepien
  * Based on: Peter Rosin's code from mcp4531.c
  *
- * Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/22060b.pdf
+ * Datasheet: https://ww1.microchip.com/downloads/en/DeviceDoc/22060b.pdf
  *
  * DEVID       #Wipers #Positions      Resistor Opts (kOhm)
  * mcp4131     1       129             5, 10, 50, 100
@@ -260,7 +260,6 @@ static int mcp4131_probe(struct spi_device *spi)
 
        mutex_init(&data->lock);
 
-       indio_dev->dev.parent = dev;
        indio_dev->info = &mcp4131_info;
        indio_dev->channels = mcp4131_channels;
        indio_dev->num_channels = data->cfg->wipers;
index d71a22d..95efc4b 100644 (file)
@@ -375,7 +375,6 @@ static int mcp4531_probe(struct i2c_client *client)
        if (!data->cfg)
                data->cfg = &mcp4531_cfg[i2c_match_id(mcp4531_id, client)->driver_data];
 
-       indio_dev->dev.parent = dev;
        indio_dev->info = &mcp4531_info;
        indio_dev->channels = mcp4531_channels;
        indio_dev->num_channels = data->cfg->wipers;
index a0a07e4..d996dc3 100644 (file)
@@ -140,7 +140,6 @@ static int tpl0102_probe(struct i2c_client *client,
                return PTR_ERR(data->regmap);
        }
 
-       indio_dev->dev.parent = dev;
        indio_dev->info = &tpl0102_info;
        indio_dev->channels = tpl0102_channels;
        indio_dev->num_channels = data->cfg->wipers;
index 2cb11da..67ae635 100644 (file)
@@ -278,17 +278,8 @@ static const struct iio_trigger_ops lmp91000_trigger_ops = {
 static int lmp91000_buffer_postenable(struct iio_dev *indio_dev)
 {
        struct lmp91000_data *data = iio_priv(indio_dev);
-       int err;
 
-       err = iio_triggered_buffer_postenable(indio_dev);
-       if (err)
-               return err;
-
-       err = iio_channel_start_all_cb(data->cb_buffer);
-       if (err)
-               iio_triggered_buffer_predisable(indio_dev);
-
-       return err;
+       return iio_channel_start_all_cb(data->cb_buffer);
 }
 
 static int lmp91000_buffer_predisable(struct iio_dev *indio_dev)
@@ -297,7 +288,7 @@ static int lmp91000_buffer_predisable(struct iio_dev *indio_dev)
 
        iio_channel_stop_all_cb(data->cb_buffer);
 
-       return iio_triggered_buffer_predisable(indio_dev);
+       return 0;
 }
 
 static const struct iio_buffer_setup_ops lmp91000_buffer_setup_ops = {
@@ -321,7 +312,6 @@ static int lmp91000_probe(struct i2c_client *client,
        indio_dev->channels = lmp91000_channels;
        indio_dev->num_channels = ARRAY_SIZE(lmp91000_channels);
        indio_dev->name = LMP91000_DRV_NAME;
-       indio_dev->dev.parent = &client->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
        i2c_set_clientdata(client, indio_dev);
 
index 267aad8..e1c3bdb 100644 (file)
@@ -194,7 +194,6 @@ static int abp060mg_probe(struct i2c_client *client,
 
        abp060mg_init_device(indio_dev, cfg_id);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->name = dev_name(&client->dev);
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &abp060mg_info;
index 126a56d..6b7da40 100644 (file)
@@ -1004,7 +1004,6 @@ int bmp280_common_probe(struct device *dev,
        mutex_init(&data->lock);
        data->dev = dev;
 
-       indio_dev->dev.parent = dev;
        indio_dev->name = name;
        indio_dev->channels = bmp280_channels;
        indio_dev->info = &bmp280_info;
index c079b89..f0938b6 100644 (file)
@@ -96,8 +96,11 @@ static int cros_ec_baro_write(struct iio_dev *indio_dev,
                /* Always roundup, so caller gets at least what it asks for. */
                st->core.param.sensor_range.roundup = 1;
 
-               if (cros_ec_motion_send_host_cmd(&st->core, 0))
-                       ret = -EIO;
+               ret = cros_ec_motion_send_host_cmd(&st->core, 0);
+               if (ret == 0) {
+                       st->core.range_updated = true;
+                       st->core.curr_range = val;
+               }
                break;
        default:
                ret = cros_ec_sensors_core_write(&st->core, chan, val, val2,
@@ -199,6 +202,7 @@ MODULE_DEVICE_TABLE(platform, cros_ec_baro_ids);
 static struct platform_driver cros_ec_baro_platform_driver = {
        .driver = {
                .name   = "cros-ec-baro",
+               .pm     = &cros_ec_sensors_pm_ops,
        },
        .probe          = cros_ec_baro_probe,
        .id_table       = cros_ec_baro_ids,
index b8c99e7..ade7326 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright (c) 2019 AVL DiTEST GmbH
  *   Tomislav Denis <tomislav.denis@avl.com>
  *
- * Datasheet: http://www.allsensors.com/cad/DS-0355_Rev_B.PDF
+ * Datasheet: https://www.allsensors.com/cad/DS-0355_Rev_B.PDF
  */
 
 #include <linux/module.h>
@@ -311,8 +311,6 @@ static int dlh_probe(struct i2c_client *client,
        st->use_interrupt = false;
 
        indio_dev->name = id->name;
-       indio_dev->dev.parent = &client->dev;
-       indio_dev->dev.of_node = client->dev.of_node;
        indio_dev->info = &dlh_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels =  dlh_channels;
index 2c1943b..0730380 100644 (file)
@@ -732,7 +732,6 @@ static int dps310_probe(struct i2c_client *client,
        data->client = client;
        mutex_init(&data->lock);
 
-       iio->dev.parent = &client->dev;
        iio->name = id->name;
        iio->channels = dps310_channels;
        iio->num_channels = ARRAY_SIZE(dps310_channels);
index 5e6663f..5c45878 100644 (file)
@@ -283,7 +283,6 @@ static int hid_press_probe(struct platform_device *pdev)
 
        indio_dev->num_channels =
                                ARRAY_SIZE(press_channels);
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->info = &press_info;
        indio_dev->name = name;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 026ba15..e40b1d7 100644 (file)
@@ -224,7 +224,6 @@ static int hp03_probe(struct i2c_client *client,
        priv->client = client;
        mutex_init(&priv->lock);
 
-       indio_dev->dev.parent = dev;
        indio_dev->name = id->name;
        indio_dev->channels = hp03_channels;
        indio_dev->num_channels = ARRAY_SIZE(hp03_channels);
index 1f931f5..986b7a5 100644 (file)
@@ -378,7 +378,6 @@ static int hp206c_probe(struct i2c_client *client,
 
        indio_dev->info = &hp206c_info;
        indio_dev->name = id->name;
-       indio_dev->dev.parent = &client->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = hp206c_channels;
        indio_dev->num_channels = ARRAY_SIZE(hp206c_channels);
index 06cb5b6..90c0df0 100644 (file)
@@ -545,7 +545,6 @@ static int icp10100_probe(struct i2c_client *client,
                return -ENOMEM;
 
        i2c_set_clientdata(client, indio_dev);
-       indio_dev->dev.parent = &client->dev;
        indio_dev->name = client->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = icp10100_channels;
index ca81a3d..81f2883 100644 (file)
@@ -160,7 +160,6 @@ int mpl115_probe(struct device *dev, const char *name,
 
        indio_dev->info = &mpl115_info;
        indio_dev->name = name;
-       indio_dev->dev.parent = dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = mpl115_channels;
        indio_dev->num_channels = ARRAY_SIZE(mpl115_channels);
index d066f3c..ccdb0b7 100644 (file)
@@ -241,7 +241,6 @@ static int mpl3115_probe(struct i2c_client *client,
        i2c_set_clientdata(client, indio_dev);
        indio_dev->info = &mpl3115_info;
        indio_dev->name = id->name;
-       indio_dev->dev.parent = &client->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = mpl3115_channels;
        indio_dev->num_channels = ARRAY_SIZE(mpl3115_channels);
index 2f598ad..d451bb9 100644 (file)
@@ -435,7 +435,6 @@ int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,
        st->pressure_osr =
                &ms5611_avail_pressure_osr[ARRAY_SIZE(ms5611_avail_pressure_osr)
                                           - 1];
-       indio_dev->dev.parent = dev;
        indio_dev->name = name;
        indio_dev->info = &ms5611_info;
        indio_dev->channels = ms5611_channels;
index f49c700..05e0ef7 100644 (file)
@@ -152,7 +152,6 @@ static int ms5637_probe(struct i2c_client *client,
 
        indio_dev->info = &ms5637_info;
        indio_dev->name = id->name;
-       indio_dev->dev.parent = &client->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = ms5637_channels;
        indio_dev->num_channels = ARRAY_SIZE(ms5637_channels);
index 418dbf9..7cf6f06 100644 (file)
@@ -31,34 +31,12 @@ int st_press_trig_set_state(struct iio_trigger *trig, bool state)
 
 static int st_press_buffer_postenable(struct iio_dev *indio_dev)
 {
-       int err;
-
-       err = iio_triggered_buffer_postenable(indio_dev);
-       if (err < 0)
-               return err;
-
-       err = st_sensors_set_enable(indio_dev, true);
-       if (err < 0)
-               goto st_press_buffer_predisable;
-
-       return 0;
-
-st_press_buffer_predisable:
-       iio_triggered_buffer_predisable(indio_dev);
-       return err;
+       return st_sensors_set_enable(indio_dev, true);
 }
 
 static int st_press_buffer_predisable(struct iio_dev *indio_dev)
 {
-       int err, err2;
-
-       err = st_sensors_set_enable(indio_dev, false);
-
-       err2 = iio_triggered_buffer_predisable(indio_dev);
-       if (!err)
-               err = err2;
-
-       return err;
+       return st_sensors_set_enable(indio_dev, false);
 }
 
 static const struct iio_buffer_setup_ops st_press_buffer_setup_ops = {
index 22abd28..685fcf6 100644 (file)
@@ -236,7 +236,6 @@ static int t5403_probe(struct i2c_client *client,
        i2c_set_clientdata(client, indio_dev);
        indio_dev->info = &t5403_info;
        indio_dev->name = id->name;
-       indio_dev->dev.parent = &client->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = t5403_channels;
        indio_dev->num_channels = ARRAY_SIZE(t5403_channels);
index 37fe851..2b8796e 100644 (file)
@@ -1242,19 +1242,17 @@ static int zpa2326_postenable_buffer(struct iio_dev *indio_dev)
        const struct zpa2326_private *priv = iio_priv(indio_dev);
        int                           err;
 
-       /* Plug our own trigger event handler. */
-       err = iio_triggered_buffer_postenable(indio_dev);
-       if (err)
-               goto err;
-
        if (!priv->waken) {
                /*
                 * We were already power supplied. Just clear hardware FIFO to
                 * get rid of samples acquired during previous rounds (if any).
                 */
                err = zpa2326_clear_fifo(indio_dev, 0);
-               if (err)
-                       goto err_buffer_predisable;
+               if (err) {
+                       zpa2326_err(indio_dev,
+                                   "failed to enable buffering (%d)", err);
+                       return err;
+               }
        }
 
        if (!iio_trigger_using_own(indio_dev) && priv->waken) {
@@ -1263,18 +1261,14 @@ static int zpa2326_postenable_buffer(struct iio_dev *indio_dev)
                 * powered up: reconfigure one-shot mode.
                 */
                err = zpa2326_config_oneshot(indio_dev, priv->irq);
-               if (err)
-                       goto err_buffer_predisable;
+               if (err) {
+                       zpa2326_err(indio_dev,
+                                   "failed to enable buffering (%d)", err);
+                       return err;
+               }
        }
 
        return 0;
-
-err_buffer_predisable:
-       iio_triggered_buffer_predisable(indio_dev);
-err:
-       zpa2326_err(indio_dev, "failed to enable buffering (%d)", err);
-
-       return err;
 }
 
 static int zpa2326_postdisable_buffer(struct iio_dev *indio_dev)
@@ -1287,7 +1281,6 @@ static int zpa2326_postdisable_buffer(struct iio_dev *indio_dev)
 static const struct iio_buffer_setup_ops zpa2326_buffer_setup_ops = {
        .preenable   = zpa2326_preenable_buffer,
        .postenable  = zpa2326_postenable_buffer,
-       .predisable  = iio_triggered_buffer_predisable,
        .postdisable = zpa2326_postdisable_buffer
 };
 
@@ -1601,7 +1594,6 @@ static struct iio_dev *zpa2326_create_managed_iiodev(struct device *device,
 
        /* Setup for userspace synchronous on demand sampling. */
        indio_dev->modes = INDIO_DIRECT_MODE;
-       indio_dev->dev.parent = device;
        indio_dev->channels = zpa2326_channels;
        indio_dev->num_channels = ARRAY_SIZE(zpa2326_channels);
        indio_dev->name = name;
index bac9a43..c339e73 100644 (file)
@@ -399,7 +399,6 @@ static int as3935_probe(struct spi_device *spi)
                return -EINVAL;
        }
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->channels = as3935_channels;
        indio_dev->num_channels = ARRAY_SIZE(as3935_channels);
index 5ae5490..90e7645 100644 (file)
@@ -972,7 +972,6 @@ static int isl29501_probe(struct i2c_client *client,
                return ret;
 
        indio_dev->modes = INDIO_DIRECT_MODE;
-       indio_dev->dev.parent = &client->dev;
        indio_dev->channels = isl29501_channels;
        indio_dev->num_channels = ARRAY_SIZE(isl29501_channels);
        indio_dev->name = client->name;
index 166b3e6..654564c 100644 (file)
@@ -200,7 +200,6 @@ static int mb1232_probe(struct i2c_client *client,
 
        indio_dev->info = &mb1232_info;
        indio_dev->name = id->name;
-       indio_dev->dev.parent = dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = mb1232_channels;
        indio_dev->num_channels = ARRAY_SIZE(mb1232_channels);
index 2e99eeb..1283ac1 100644 (file)
@@ -309,7 +309,6 @@ static int ping_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, indio_dev);
 
        indio_dev->name = "ping";
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->info = &ping_iio_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = ping_chan_spec;
index 5b36964..a8e716d 100644 (file)
@@ -270,7 +270,6 @@ static int lidar_probe(struct i2c_client *client,
        indio_dev->name = LIDAR_DRV_NAME;
        indio_dev->channels = lidar_channels;
        indio_dev->num_channels = ARRAY_SIZE(lidar_channels);
-       indio_dev->dev.parent = &client->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
        i2c_set_clientdata(client, indio_dev);
index 36480c0..7a04723 100644 (file)
@@ -274,7 +274,6 @@ static int rfd77402_probe(struct i2c_client *client,
        data->client = client;
        mutex_init(&data->lock);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &rfd77402_info;
        indio_dev->channels = rfd77402_channels;
        indio_dev->num_channels = ARRAY_SIZE(rfd77402_channels);
index 568b76e..420c37c 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright (c) 2017 Andreas Klinger <ak@it-klinger.de>
  *
  * For details about the device see:
- * http://www.robot-electronics.co.uk/htm/srf04tech.htm
+ * https://www.robot-electronics.co.uk/htm/srf04tech.htm
  *
  * the measurement cycle as timing diagram looks like:
  *
@@ -317,7 +317,6 @@ static int srf04_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, indio_dev);
 
        indio_dev->name = "srf04";
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->info = &srf04_iio_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = srf04_chan_spec;
index b23ce44..70beac5 100644 (file)
@@ -7,9 +7,9 @@
  * Copyright (c) 2016, 2017 Andreas Klinger <ak@it-klinger.de>
  *
  * For details about the device see:
- * http://www.robot-electronics.co.uk/htm/srf08tech.html
- * http://www.robot-electronics.co.uk/htm/srf10tech.htm
- * http://www.robot-electronics.co.uk/htm/srf02tech.htm
+ * https://www.robot-electronics.co.uk/htm/srf08tech.html
+ * https://www.robot-electronics.co.uk/htm/srf10tech.htm
+ * https://www.robot-electronics.co.uk/htm/srf02tech.htm
  */
 
 #include <linux/err.h>
@@ -483,7 +483,6 @@ static int srf08_probe(struct i2c_client *client,
        }
 
        indio_dev->name = id->name;
-       indio_dev->dev.parent = &client->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = srf08_channels;
        indio_dev->num_channels = ARRAY_SIZE(srf08_channels);
index d161f30..dc2e11b 100644 (file)
@@ -736,8 +736,6 @@ static int sx9310_buffer_postdisable(struct iio_dev *indio_dev)
 
 static const struct iio_buffer_setup_ops sx9310_buffer_setup_ops = {
        .preenable = sx9310_buffer_preenable,
-       .postenable = iio_triggered_buffer_postenable,
-       .predisable = iio_triggered_buffer_predisable,
        .postdisable = sx9310_buffer_postdisable,
 };
 
@@ -931,7 +929,6 @@ static int sx9310_probe(struct i2c_client *client,
                return ret;
 
        ACPI_COMPANION_SET(&indio_dev->dev, ACPI_COMPANION(&client->dev));
-       indio_dev->dev.parent = &client->dev;
        indio_dev->channels = sx9310_channels;
        indio_dev->num_channels = ARRAY_SIZE(sx9310_channels);
        indio_dev->info = &sx9310_info;
index 287d288..acb821c 100644 (file)
@@ -680,10 +680,6 @@ static int sx9500_buffer_postenable(struct iio_dev *indio_dev)
        struct sx9500_data *data = iio_priv(indio_dev);
        int ret = 0, i;
 
-       ret = iio_triggered_buffer_postenable(indio_dev);
-       if (ret)
-               return ret;
-
        mutex_lock(&data->mutex);
 
        for (i = 0; i < SX9500_NUM_CHANNELS; i++)
@@ -700,9 +696,6 @@ static int sx9500_buffer_postenable(struct iio_dev *indio_dev)
 
        mutex_unlock(&data->mutex);
 
-       if (ret)
-               iio_triggered_buffer_predisable(indio_dev);
-
        return ret;
 }
 
@@ -727,8 +720,6 @@ static int sx9500_buffer_predisable(struct iio_dev *indio_dev)
 
        mutex_unlock(&data->mutex);
 
-       iio_triggered_buffer_predisable(indio_dev);
-
        return ret;
 }
 
@@ -931,7 +922,6 @@ static int sx9500_probe(struct i2c_client *client,
        if (IS_ERR(data->regmap))
                return PTR_ERR(data->regmap);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->name = SX9500_DRIVER_NAME;
        indio_dev->channels = sx9500_channels;
        indio_dev->num_channels = ARRAY_SIZE(sx9500_channels);
index 9ff1a16..37264f8 100644 (file)
@@ -226,7 +226,6 @@ static int vcnl3020_probe(struct i2c_client *client)
        if (rc)
                return rc;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &vcnl3020_info;
        indio_dev->channels = vcnl3020_channels;
        indio_dev->num_channels = ARRAY_SIZE(vcnl3020_channels);
index b48216c..5fbda94 100644 (file)
@@ -134,7 +134,6 @@ static int vl53l0x_probe(struct i2c_client *client)
                                     I2C_FUNC_SMBUS_BYTE_DATA))
                return -EOPNOTSUPP;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->name = "vl53l0x";
        indio_dev->info = &vl53l0x_info;
        indio_dev->channels = vl53l0x_channels;
index a391f46..6007aba 100644 (file)
@@ -157,7 +157,6 @@ static int ad2s1200_probe(struct spi_device *spi)
                return PTR_ERR(st->rdvel);
        }
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &ad2s1200_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = ad2s1200_channels;
index a41f5cb..d6a91f1 100644 (file)
@@ -94,7 +94,6 @@ static int ad2s90_probe(struct spi_device *spi)
 
        mutex_init(&st->lock);
        st->sdev = spi;
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &ad2s90_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = &ad2s90_chan;
index 8d1f434..81688f1 100644 (file)
@@ -223,7 +223,6 @@ static int hid_temperature_probe(struct platform_device *pdev)
 
        indio_dev->channels = temp_chans;
        indio_dev->num_channels = ARRAY_SIZE(temperature_channels);
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->info = &temperature_info;
        indio_dev->name = name;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 3fd52b3..fe126e1 100644 (file)
@@ -74,7 +74,6 @@ static int iqs620_temp_probe(struct platform_device *pdev)
        iio_device_set_drvdata(indio_dev, iqs62x);
 
        indio_dev->modes = INDIO_DIRECT_MODE;
-       indio_dev->dev.parent = &pdev->dev;
        indio_dev->channels = iqs620_temp_channels;
        indio_dev->num_channels = ARRAY_SIZE(iqs620_temp_channels);
        indio_dev->name = iqs62x->dev_desc->dev_name;
index 8976e8d..55ff28a 100644 (file)
@@ -1500,7 +1500,6 @@ static int ltc2983_probe(struct spi_device *spi)
        if (ret)
                return ret;
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = name;
        indio_dev->num_channels = st->iio_channels;
        indio_dev->channels = st->iio_chan;
index b4c49a5..1954322 100644 (file)
@@ -417,8 +417,6 @@ static int max31856_probe(struct spi_device *spi)
        spi_set_drvdata(spi, indio_dev);
 
        indio_dev->info = &max31856_info;
-       indio_dev->dev.parent = &spi->dev;
-       indio_dev->dev.of_node = spi->dev.of_node;
        indio_dev->name = id->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = max31856_channels;
index 8d21116..0297e21 100644 (file)
@@ -244,7 +244,6 @@ static int maxim_thermocouple_probe(struct spi_device *spi)
        indio_dev->available_scan_masks = chip->scan_masks;
        indio_dev->num_channels = chip->num_channels;
        indio_dev->modes = INDIO_DIRECT_MODE;
-       indio_dev->dev.parent = &spi->dev;
 
        data = iio_priv(indio_dev);
        data->spi = spi;
index b7c56dd..ef0fec9 100644 (file)
@@ -525,7 +525,6 @@ static int mlx90614_probe(struct i2c_client *client,
 
        mlx90614_wakeup(data);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->name = id->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &mlx90614_info;
index eaca6ba..ef94ad8 100644 (file)
@@ -645,7 +645,6 @@ static int mlx90632_probe(struct i2c_client *client,
        mlx90632->regmap = regmap;
 
        mutex_init(&mlx90632->lock);
-       indio_dev->dev.parent = &client->dev;
        indio_dev->name = id->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &mlx90632_info;
index cc45d83..54976c7 100644 (file)
@@ -216,7 +216,6 @@ static int tmp006_probe(struct i2c_client *client,
        i2c_set_clientdata(client, indio_dev);
        data->client = client;
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->name = dev_name(&client->dev);
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &tmp006_info;
index 7df234d..f90fe9e 100644 (file)
@@ -463,7 +463,6 @@ static int tmp007_probe(struct i2c_client *client,
        data->client = client;
        mutex_init(&data->lock);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->name = "tmp007";
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &tmp007_info;
index d41f050..2c631a1 100644 (file)
@@ -160,7 +160,6 @@ static int tsys01_probe(struct iio_dev *indio_dev, struct device *dev)
 
        indio_dev->info = &tsys01_info;
        indio_dev->name = dev->driver->name;
-       indio_dev->dev.parent = dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = tsys01_channels;
        indio_dev->num_channels = ARRAY_SIZE(tsys01_channels);
index 6735af4..fc96e5f 100644 (file)
@@ -149,7 +149,6 @@ static int tsys02d_probe(struct i2c_client *client,
 
        indio_dev->info = &tsys02d_info;
        indio_dev->name = id->name;
-       indio_dev->dev.parent = &client->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = tsys02d_channels;
        indio_dev->num_channels = ARRAY_SIZE(tsys02d_channels);
index 7d8962d..3aa9e8b 100644 (file)
@@ -723,12 +723,10 @@ static struct stm32_timer_trigger *stm32_setup_counter_device(struct device *dev
                return NULL;
 
        indio_dev->name = dev_name(dev);
-       indio_dev->dev.parent = dev;
        indio_dev->info = &stm32_trigger_info;
        indio_dev->modes = INDIO_HARDWARE_TRIGGERED;
        indio_dev->num_channels = 1;
        indio_dev->channels = &stm32_trigger_channel;
-       indio_dev->dev.of_node = dev->of_node;
 
        ret = devm_iio_device_register(dev, indio_dev);
        if (ret)
index 3b0e3fa..752eb7f 100644 (file)
@@ -119,7 +119,6 @@ int tsc2007_iio_configure(struct tsc2007 *ts)
        iio->ts = ts;
 
        indio_dev->name = "tsc2007";
-       indio_dev->dev.parent = &ts->client->dev;
        indio_dev->info = &tsc2007_iio_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = tsc2007_iio_channel;
index 1ddab5a..36fff00 100644 (file)
@@ -3114,7 +3114,7 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
 
        toshiba_accelerometer_available(dev);
        if (dev->accelerometer_supported) {
-               dev->indio_dev = iio_device_alloc(sizeof(*dev));
+               dev->indio_dev = iio_device_alloc(&acpi_dev->dev, sizeof(*dev));
                if (!dev->indio_dev) {
                        pr_err("Unable to allocate iio device\n");
                        goto iio_error;
@@ -3124,7 +3124,6 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
 
                dev->indio_dev->info = &toshiba_iio_accel_info;
                dev->indio_dev->name = "Toshiba accelerometer";
-               dev->indio_dev->dev.parent = &acpi_dev->dev;
                dev->indio_dev->modes = INDIO_DIRECT_MODE;
                dev->indio_dev->channels = toshiba_iio_accel_channels;
                dev->indio_dev->num_channels =
index ec42544..0d1275b 100644 (file)
@@ -8,7 +8,7 @@ The crucial structure for device drivers in iio is iio_dev.
 
 First allocate one using:
 
-struct iio_dev *indio_dev = iio_device_alloc(sizeof(struct chip_state));
+struct iio_dev *indio_dev = iio_device_alloc(parent, sizeof(struct chip_state));
 where chip_state is a structure of local state data for this instance of
 the chip.
 
@@ -16,8 +16,6 @@ That data can be accessed using iio_priv(struct iio_dev *).
 
 Then fill in the following:
 
-- indio_dev->dev.parent
-       Struct device associated with the underlying hardware.
 - indio_dev->name
        Name of the device being driven - made available as the name
        attribute in sysfs.
index fef52d9..c779890 100644 (file)
@@ -277,7 +277,6 @@ static int adis16203_probe(struct spi_device *spi)
        spi_set_drvdata(spi, indio_dev);
 
        indio_dev->name = spi->dev.driver->name;
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->channels = adis16203_channels;
        indio_dev->num_channels = ARRAY_SIZE(adis16203_channels);
        indio_dev->info = &adis16203_info;
index 8bd35c6..38ec40b 100644 (file)
@@ -400,7 +400,6 @@ static int adis16240_probe(struct spi_device *spi)
        spi_set_drvdata(spi, indio_dev);
 
        indio_dev->name = spi->dev.driver->name;
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &adis16240_info;
        indio_dev->channels = adis16240_channels;
        indio_dev->num_channels = ARRAY_SIZE(adis16240_channels);
index bef6bd1..fef0055 100644 (file)
@@ -978,7 +978,6 @@ static int ad7280_probe(struct spi_device *spi)
        st->readback_delay_us += 5; /* Add tWAIT */
 
        indio_dev->name = spi_get_device_id(spi)->name;
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
        ret = ad7280_channel_init(st);
index a9985a7..6c14d7b 100644 (file)
@@ -394,7 +394,6 @@ static int ad7816_probe(struct spi_device *spi_dev)
        }
 
        indio_dev->name = spi_get_device_id(spi_dev)->name;
-       indio_dev->dev.parent = &spi_dev->dev;
        indio_dev->info = &ad7816_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
 
index 9cb3d0e..ccbafca 100644 (file)
@@ -2171,7 +2171,6 @@ int adt7316_probe(struct device *dev, struct adt7316_bus *bus,
        if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
                chip->int_mask |= ADT7516_AIN_INT_MASK;
 
-       indio_dev->dev.parent = dev;
        if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
                indio_dev->info = &adt7516_info;
        else
index f4954d8..48132ab 100644 (file)
@@ -590,8 +590,6 @@ static int ad7150_probe(struct i2c_client *client,
        indio_dev->name = id->name;
        indio_dev->channels = ad7150_channels;
        indio_dev->num_channels = ARRAY_SIZE(ad7150_channels);
-       /* Establish that the iio_dev is a child of the i2c device */
-       indio_dev->dev.parent = &client->dev;
 
        indio_dev->info = &ad7150_info;
 
index 21527d8..dfd71e9 100644 (file)
@@ -693,9 +693,7 @@ static int ad7746_probe(struct i2c_client *client,
        chip->client = client;
        chip->capdac_set = -1;
 
-       /* Establish that the iio_dev is a child of the i2c device */
        indio_dev->name = id->name;
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &ad7746_info;
        indio_dev->channels = ad7746_channels;
        if (id->driver_data == 7746)
index 74308a2..447937e 100644 (file)
@@ -348,7 +348,6 @@ static int ad9832_probe(struct spi_device *spi)
        st->spi = spi;
        mutex_init(&st->lock);
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->info = &ad9832_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 2302697..77f77a2 100644 (file)
@@ -431,7 +431,6 @@ static int ad9834_probe(struct spi_device *spi)
        st->spi = spi;
        st->devid = spi_get_device_id(spi)->driver_data;
        st->reg = reg;
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->name = spi_get_device_id(spi)->name;
        switch (st->devid) {
        case ID_AD9833:
index c468355..dba7889 100644 (file)
@@ -759,7 +759,6 @@ static int ad5933_probe(struct i2c_client *client,
        INIT_DELAYED_WORK(&st->work, ad5933_work);
        st->poll_time_jiffies = msecs_to_jiffies(AD5933_POLL_TIME_ms);
 
-       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &ad5933_info;
        indio_dev->name = id->name;
        indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
index ed40435..74adb82 100644 (file)
@@ -671,7 +671,6 @@ static int ad2s1210_probe(struct spi_device *spi)
        st->resolution = 12;
        st->fexcit = AD2S1210_DEF_EXCIT;
 
-       indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &ad2s1210_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = ad2s1210_channels;
diff --git a/include/dt-bindings/iio/qcom,spmi-adc7-pm8350.h b/include/dt-bindings/iio/qcom,spmi-adc7-pm8350.h
new file mode 100644 (file)
index 0000000..9426f27
--- /dev/null
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_QCOM_SPMI_VADC_PM8350_H
+#define _DT_BINDINGS_QCOM_SPMI_VADC_PM8350_H
+
+#ifndef PM8350_SID
+#define PM8350_SID                                     1
+#endif
+
+/* ADC channels for PM8350_ADC for PMIC7 */
+#define PM8350_ADC7_REF_GND                    (PM8350_SID << 8 | 0x0)
+#define PM8350_ADC7_1P25VREF                   (PM8350_SID << 8 | 0x01)
+#define PM8350_ADC7_VREF_VADC                  (PM8350_SID << 8 | 0x02)
+#define PM8350_ADC7_DIE_TEMP                   (PM8350_SID << 8 | 0x03)
+
+#define PM8350_ADC7_AMUX_THM1                  (PM8350_SID << 8 | 0x04)
+#define PM8350_ADC7_AMUX_THM2                  (PM8350_SID << 8 | 0x05)
+#define PM8350_ADC7_AMUX_THM3                  (PM8350_SID << 8 | 0x06)
+#define PM8350_ADC7_AMUX_THM4                  (PM8350_SID << 8 | 0x07)
+#define PM8350_ADC7_AMUX_THM5                  (PM8350_SID << 8 | 0x08)
+#define PM8350_ADC7_GPIO1                      (PM8350_SID << 8 | 0x0a)
+#define PM8350_ADC7_GPIO2                      (PM8350_SID << 8 | 0x0b)
+#define PM8350_ADC7_GPIO3                      (PM8350_SID << 8 | 0x0c)
+#define PM8350_ADC7_GPIO4                      (PM8350_SID << 8 | 0x0d)
+
+/* 30k pull-up1 */
+#define PM8350_ADC7_AMUX_THM1_30K_PU           (PM8350_SID << 8 | 0x24)
+#define PM8350_ADC7_AMUX_THM2_30K_PU           (PM8350_SID << 8 | 0x25)
+#define PM8350_ADC7_AMUX_THM3_30K_PU           (PM8350_SID << 8 | 0x26)
+#define PM8350_ADC7_AMUX_THM4_30K_PU           (PM8350_SID << 8 | 0x27)
+#define PM8350_ADC7_AMUX_THM5_30K_PU           (PM8350_SID << 8 | 0x28)
+#define PM8350_ADC7_GPIO1_30K_PU               (PM8350_SID << 8 | 0x2a)
+#define PM8350_ADC7_GPIO2_30K_PU               (PM8350_SID << 8 | 0x2b)
+#define PM8350_ADC7_GPIO3_30K_PU               (PM8350_SID << 8 | 0x2c)
+#define PM8350_ADC7_GPIO4_30K_PU               (PM8350_SID << 8 | 0x2d)
+
+/* 100k pull-up2 */
+#define PM8350_ADC7_AMUX_THM1_100K_PU          (PM8350_SID << 8 | 0x44)
+#define PM8350_ADC7_AMUX_THM2_100K_PU          (PM8350_SID << 8 | 0x45)
+#define PM8350_ADC7_AMUX_THM3_100K_PU          (PM8350_SID << 8 | 0x46)
+#define PM8350_ADC7_AMUX_THM4_100K_PU          (PM8350_SID << 8 | 0x47)
+#define PM8350_ADC7_AMUX_THM5_100K_PU          (PM8350_SID << 8 | 0x48)
+#define PM8350_ADC7_GPIO1_100K_PU              (PM8350_SID << 8 | 0x4a)
+#define PM8350_ADC7_GPIO2_100K_PU              (PM8350_SID << 8 | 0x4b)
+#define PM8350_ADC7_GPIO3_100K_PU              (PM8350_SID << 8 | 0x4c)
+#define PM8350_ADC7_GPIO4_100K_PU              (PM8350_SID << 8 | 0x4d)
+
+/* 400k pull-up3 */
+#define PM8350_ADC7_AMUX_THM1_400K_PU          (PM8350_SID << 8 | 0x64)
+#define PM8350_ADC7_AMUX_THM2_400K_PU          (PM8350_SID << 8 | 0x65)
+#define PM8350_ADC7_AMUX_THM3_400K_PU          (PM8350_SID << 8 | 0x66)
+#define PM8350_ADC7_AMUX_THM4_400K_PU          (PM8350_SID << 8 | 0x67)
+#define PM8350_ADC7_AMUX_THM5_400K_PU          (PM8350_SID << 8 | 0x68)
+#define PM8350_ADC7_GPIO1_400K_PU              (PM8350_SID << 8 | 0x6a)
+#define PM8350_ADC7_GPIO2_400K_PU              (PM8350_SID << 8 | 0x6b)
+#define PM8350_ADC7_GPIO3_400K_PU              (PM8350_SID << 8 | 0x6c)
+#define PM8350_ADC7_GPIO4_400K_PU              (PM8350_SID << 8 | 0x6d)
+
+/* 1/3 Divider */
+#define PM8350_ADC7_GPIO4_DIV3                 (PM8350_SID << 8 | 0x8d)
+
+#define PM8350_ADC7_VPH_PWR                    (PM8350_SID << 8 | 0x8e)
+
+#endif /* _DT_BINDINGS_QCOM_SPMI_VADC_PM8350_H */
diff --git a/include/dt-bindings/iio/qcom,spmi-adc7-pm8350b.h b/include/dt-bindings/iio/qcom,spmi-adc7-pm8350b.h
new file mode 100644 (file)
index 0000000..dc2497c
--- /dev/null
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_QCOM_SPMI_VADC_PM8350B_H
+#define _DT_BINDINGS_QCOM_SPMI_VADC_PM8350B_H
+
+#ifndef PM8350B_SID
+#define PM8350B_SID                                    3
+#endif
+
+/* ADC channels for PM8350B_ADC for PMIC7 */
+#define PM8350B_ADC7_REF_GND                   (PM8350B_SID << 8 | 0x0)
+#define PM8350B_ADC7_1P25VREF                  (PM8350B_SID << 8 | 0x01)
+#define PM8350B_ADC7_VREF_VADC                 (PM8350B_SID << 8 | 0x02)
+#define PM8350B_ADC7_DIE_TEMP                  (PM8350B_SID << 8 | 0x03)
+
+#define PM8350B_ADC7_AMUX_THM1                 (PM8350B_SID << 8 | 0x04)
+#define PM8350B_ADC7_AMUX_THM2                 (PM8350B_SID << 8 | 0x05)
+#define PM8350B_ADC7_AMUX_THM3                 (PM8350B_SID << 8 | 0x06)
+#define PM8350B_ADC7_AMUX_THM4                 (PM8350B_SID << 8 | 0x07)
+#define PM8350B_ADC7_AMUX_THM5                 (PM8350B_SID << 8 | 0x08)
+#define PM8350B_ADC7_AMUX_THM6                 (PM8350B_SID << 8 | 0x09)
+#define PM8350B_ADC7_GPIO1                     (PM8350B_SID << 8 | 0x0a)
+#define PM8350B_ADC7_GPIO2                     (PM8350B_SID << 8 | 0x0b)
+#define PM8350B_ADC7_GPIO3                     (PM8350B_SID << 8 | 0x0c)
+#define PM8350B_ADC7_GPIO4                     (PM8350B_SID << 8 | 0x0d)
+
+#define PM8350B_ADC7_CHG_TEMP                  (PM8350B_SID << 8 | 0x10)
+#define PM8350B_ADC7_USB_IN_V_16               (PM8350B_SID << 8 | 0x11)
+#define PM8350B_ADC7_VDC_16                    (PM8350B_SID << 8 | 0x12)
+#define PM8350B_ADC7_CC1_ID                    (PM8350B_SID << 8 | 0x13)
+#define PM8350B_ADC7_VREF_BAT_THERM            (PM8350B_SID << 8 | 0x15)
+#define PM8350B_ADC7_IIN_FB                    (PM8350B_SID << 8 | 0x17)
+
+/* 30k pull-up1 */
+#define PM8350B_ADC7_AMUX_THM1_30K_PU          (PM8350B_SID << 8 | 0x24)
+#define PM8350B_ADC7_AMUX_THM2_30K_PU          (PM8350B_SID << 8 | 0x25)
+#define PM8350B_ADC7_AMUX_THM3_30K_PU          (PM8350B_SID << 8 | 0x26)
+#define PM8350B_ADC7_AMUX_THM4_30K_PU          (PM8350B_SID << 8 | 0x27)
+#define PM8350B_ADC7_AMUX_THM5_30K_PU          (PM8350B_SID << 8 | 0x28)
+#define PM8350B_ADC7_AMUX_THM6_30K_PU          (PM8350B_SID << 8 | 0x29)
+#define PM8350B_ADC7_GPIO1_30K_PU              (PM8350B_SID << 8 | 0x2a)
+#define PM8350B_ADC7_GPIO2_30K_PU              (PM8350B_SID << 8 | 0x2b)
+#define PM8350B_ADC7_GPIO3_30K_PU              (PM8350B_SID << 8 | 0x2c)
+#define PM8350B_ADC7_GPIO4_30K_PU              (PM8350B_SID << 8 | 0x2d)
+#define PM8350B_ADC7_CC1_ID_30K_PU             (PM8350B_SID << 8 | 0x33)
+
+/* 100k pull-up2 */
+#define PM8350B_ADC7_AMUX_THM1_100K_PU         (PM8350B_SID << 8 | 0x44)
+#define PM8350B_ADC7_AMUX_THM2_100K_PU         (PM8350B_SID << 8 | 0x45)
+#define PM8350B_ADC7_AMUX_THM3_100K_PU         (PM8350B_SID << 8 | 0x46)
+#define PM8350B_ADC7_AMUX_THM4_100K_PU         (PM8350B_SID << 8 | 0x47)
+#define PM8350B_ADC7_AMUX_THM5_100K_PU         (PM8350B_SID << 8 | 0x48)
+#define PM8350B_ADC7_AMUX_THM6_100K_PU         (PM8350B_SID << 8 | 0x49)
+#define PM8350B_ADC7_GPIO1_100K_PU             (PM8350B_SID << 8 | 0x4a)
+#define PM8350B_ADC7_GPIO2_100K_PU             (PM8350B_SID << 8 | 0x4b)
+#define PM8350B_ADC7_GPIO3_100K_PU             (PM8350B_SID << 8 | 0x4c)
+#define PM8350B_ADC7_GPIO4_100K_PU             (PM8350B_SID << 8 | 0x4d)
+#define PM8350B_ADC7_CC1_ID_100K_PU            (PM8350B_SID << 8 | 0x53)
+
+/* 400k pull-up3 */
+#define PM8350B_ADC7_AMUX_THM1_400K_PU         (PM8350B_SID << 8 | 0x64)
+#define PM8350B_ADC7_AMUX_THM2_400K_PU         (PM8350B_SID << 8 | 0x65)
+#define PM8350B_ADC7_AMUX_THM3_400K_PU         (PM8350B_SID << 8 | 0x66)
+#define PM8350B_ADC7_AMUX_THM4_400K_PU         (PM8350B_SID << 8 | 0x67)
+#define PM8350B_ADC7_AMUX_THM5_400K_PU         (PM8350B_SID << 8 | 0x68)
+#define PM8350B_ADC7_AMUX_THM6_400K_PU         (PM8350B_SID << 8 | 0x69)
+#define PM8350B_ADC7_GPIO1_400K_PU             (PM8350B_SID << 8 | 0x6a)
+#define PM8350B_ADC7_GPIO2_400K_PU             (PM8350B_SID << 8 | 0x6b)
+#define PM8350B_ADC7_GPIO3_400K_PU             (PM8350B_SID << 8 | 0x6c)
+#define PM8350B_ADC7_GPIO4_400K_PU             (PM8350B_SID << 8 | 0x6d)
+#define PM8350B_ADC7_CC1_ID_400K_PU            (PM8350B_SID << 8 | 0x73)
+
+/* 1/3 Divider */
+#define PM8350B_ADC7_GPIO1_DIV3                        (PM8350B_SID << 8 | 0x8a)
+#define PM8350B_ADC7_GPIO2_DIV3                        (PM8350B_SID << 8 | 0x8b)
+#define PM8350B_ADC7_GPIO3_DIV3                        (PM8350B_SID << 8 | 0x8c)
+#define PM8350B_ADC7_GPIO4_DIV3                        (PM8350B_SID << 8 | 0x8d)
+
+#define PM8350B_ADC7_VPH_PWR                   (PM8350B_SID << 8 | 0x8e)
+#define PM8350B_ADC7_VBAT_SNS                  (PM8350B_SID << 8 | 0x8f)
+
+#define PM8350B_ADC7_SBUx                      (PM8350B_SID << 8 | 0x94)
+#define PM8350B_ADC7_VBAT_2S_MID               (PM8350B_SID << 8 | 0x96)
+
+#endif /* _DT_BINDINGS_QCOM_SPMI_VADC_PM8350B_H */
diff --git a/include/dt-bindings/iio/qcom,spmi-adc7-pmk8350.h b/include/dt-bindings/iio/qcom,spmi-adc7-pmk8350.h
new file mode 100644 (file)
index 0000000..6c29687
--- /dev/null
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_QCOM_SPMI_VADC_PMK8350_H
+#define _DT_BINDINGS_QCOM_SPMI_VADC_PMK8350_H
+
+#ifndef PMK8350_SID
+#define PMK8350_SID                                    0
+#endif
+
+/* ADC channels for PMK8350_ADC for PMIC7 */
+#define PMK8350_ADC7_REF_GND                   (PMK8350_SID << 8 | 0x0)
+#define PMK8350_ADC7_1P25VREF                  (PMK8350_SID << 8 | 0x01)
+#define PMK8350_ADC7_VREF_VADC                 (PMK8350_SID << 8 | 0x02)
+#define PMK8350_ADC7_DIE_TEMP                  (PMK8350_SID << 8 | 0x03)
+
+#define PMK8350_ADC7_AMUX_THM1                 (PMK8350_SID << 8 | 0x04)
+#define PMK8350_ADC7_AMUX_THM2                 (PMK8350_SID << 8 | 0x05)
+#define PMK8350_ADC7_AMUX_THM3                 (PMK8350_SID << 8 | 0x06)
+#define PMK8350_ADC7_AMUX_THM4                 (PMK8350_SID << 8 | 0x07)
+#define PMK8350_ADC7_AMUX_THM5                 (PMK8350_SID << 8 | 0x08)
+
+/* 30k pull-up1 */
+#define PMK8350_ADC7_AMUX_THM1_30K_PU          (PMK8350_SID << 8 | 0x24)
+#define PMK8350_ADC7_AMUX_THM2_30K_PU          (PMK8350_SID << 8 | 0x25)
+#define PMK8350_ADC7_AMUX_THM3_30K_PU          (PMK8350_SID << 8 | 0x26)
+#define PMK8350_ADC7_AMUX_THM4_30K_PU          (PMK8350_SID << 8 | 0x27)
+#define PMK8350_ADC7_AMUX_THM5_30K_PU          (PMK8350_SID << 8 | 0x28)
+
+/* 100k pull-up2 */
+#define PMK8350_ADC7_AMUX_THM1_100K_PU         (PMK8350_SID << 8 | 0x44)
+#define PMK8350_ADC7_AMUX_THM2_100K_PU         (PMK8350_SID << 8 | 0x45)
+#define PMK8350_ADC7_AMUX_THM3_100K_PU         (PMK8350_SID << 8 | 0x46)
+#define PMK8350_ADC7_AMUX_THM4_100K_PU         (PMK8350_SID << 8 | 0x47)
+#define PMK8350_ADC7_AMUX_THM5_100K_PU         (PMK8350_SID << 8 | 0x48)
+
+/* 400k pull-up3 */
+#define PMK8350_ADC7_AMUX_THM1_400K_PU         (PMK8350_SID << 8 | 0x64)
+#define PMK8350_ADC7_AMUX_THM2_400K_PU         (PMK8350_SID << 8 | 0x65)
+#define PMK8350_ADC7_AMUX_THM3_400K_PU         (PMK8350_SID << 8 | 0x66)
+#define PMK8350_ADC7_AMUX_THM4_400K_PU         (PMK8350_SID << 8 | 0x67)
+#define PMK8350_ADC7_AMUX_THM5_400K_PU         (PMK8350_SID << 8 | 0x68)
+
+#endif /* _DT_BINDINGS_QCOM_SPMI_VADC_PMK8350_H */
diff --git a/include/dt-bindings/iio/qcom,spmi-adc7-pmr735a.h b/include/dt-bindings/iio/qcom,spmi-adc7-pmr735a.h
new file mode 100644 (file)
index 0000000..d6df1b1
--- /dev/null
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_QCOM_SPMI_VADC_PMR735A_H
+#define _DT_BINDINGS_QCOM_SPMI_VADC_PMR735A_H
+
+#ifndef PMR735A_SID
+#define PMR735A_SID                                    4
+#endif
+
+/* ADC channels for PMR735A_ADC for PMIC7 */
+#define PMR735A_ADC7_REF_GND                   (PMR735A_SID << 8 | 0x0)
+#define PMR735A_ADC7_1P25VREF                  (PMR735A_SID << 8 | 0x01)
+#define PMR735A_ADC7_VREF_VADC                 (PMR735A_SID << 8 | 0x02)
+#define PMR735A_ADC7_DIE_TEMP                  (PMR735A_SID << 8 | 0x03)
+
+#define PMR735A_ADC7_GPIO1                     (PMR735A_SID << 8 | 0x0a)
+#define PMR735A_ADC7_GPIO2                     (PMR735A_SID << 8 | 0x0b)
+#define PMR735A_ADC7_GPIO3                     (PMR735A_SID << 8 | 0x0c)
+
+/* 100k pull-up2 */
+#define PMR735A_ADC7_GPIO1_100K_PU             (PMR735A_SID << 8 | 0x4a)
+#define PMR735A_ADC7_GPIO2_100K_PU             (PMR735A_SID << 8 | 0x4b)
+#define PMR735A_ADC7_GPIO3_100K_PU             (PMR735A_SID << 8 | 0x4c)
+
+#endif /* _DT_BINDINGS_QCOM_SPMI_VADC_PMR735A_H */
diff --git a/include/dt-bindings/iio/qcom,spmi-adc7-pmr735b.h b/include/dt-bindings/iio/qcom,spmi-adc7-pmr735b.h
new file mode 100644 (file)
index 0000000..8da0e7d
--- /dev/null
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_QCOM_SPMI_VADC_PMR735B_H
+#define _DT_BINDINGS_QCOM_SPMI_VADC_PMR735B_H
+
+#ifndef PMR735B_SID
+#define PMR735B_SID                                    5
+#endif
+
+/* ADC channels for PMR735B_ADC for PMIC7 */
+#define PMR735B_ADC7_REF_GND                   (PMR735B_SID << 8 | 0x0)
+#define PMR735B_ADC7_1P25VREF                  (PMR735B_SID << 8 | 0x01)
+#define PMR735B_ADC7_VREF_VADC                 (PMR735B_SID << 8 | 0x02)
+#define PMR735B_ADC7_DIE_TEMP                  (PMR735B_SID << 8 | 0x03)
+
+#define PMR735B_ADC7_GPIO1                     (PMR735B_SID << 8 | 0x0a)
+#define PMR735B_ADC7_GPIO2                     (PMR735B_SID << 8 | 0x0b)
+#define PMR735B_ADC7_GPIO3                     (PMR735B_SID << 8 | 0x0c)
+
+/* 100k pull-up2 */
+#define PMR735B_ADC7_GPIO1_100K_PU             (PMR735B_SID << 8 | 0x4a)
+#define PMR735B_ADC7_GPIO2_100K_PU             (PMR735B_SID << 8 | 0x4b)
+#define PMR735B_ADC7_GPIO3_100K_PU             (PMR735B_SID << 8 | 0x4c)
+
+#endif /* _DT_BINDINGS_QCOM_SPMI_VADC_PMR735B_H */
index 61d556d..08adfe2 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
- * Copyright (c) 2012-2014,2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014,2018,2020 The Linux Foundation. All rights reserved.
  */
 
 #ifndef _DT_BINDINGS_QCOM_SPMI_VADC_H
 
 #define ADC5_MAX_CHANNEL                       0xc0
 
+/* ADC channels for ADC for PMIC7 */
+
+#define ADC7_REF_GND                           0x00
+#define ADC7_1P25VREF                          0x01
+#define ADC7_VREF_VADC                         0x02
+#define ADC7_DIE_TEMP                          0x03
+
+#define ADC7_AMUX_THM1                         0x04
+#define ADC7_AMUX_THM2                         0x05
+#define ADC7_AMUX_THM3                         0x06
+#define ADC7_AMUX_THM4                         0x07
+#define ADC7_AMUX_THM5                         0x08
+#define ADC7_AMUX_THM6                         0x09
+#define ADC7_GPIO1                             0x0a
+#define ADC7_GPIO2                             0x0b
+#define ADC7_GPIO3                             0x0c
+#define ADC7_GPIO4                             0x0d
+
+#define ADC7_CHG_TEMP                          0x10
+#define ADC7_USB_IN_V_16                       0x11
+#define ADC7_VDC_16                            0x12
+#define ADC7_CC1_ID                            0x13
+#define ADC7_VREF_BAT_THERM                    0x15
+#define ADC7_IIN_FB                            0x17
+
+/* 30k pull-up1 */
+#define ADC7_AMUX_THM1_30K_PU                  0x24
+#define ADC7_AMUX_THM2_30K_PU                  0x25
+#define ADC7_AMUX_THM3_30K_PU                  0x26
+#define ADC7_AMUX_THM4_30K_PU                  0x27
+#define ADC7_AMUX_THM5_30K_PU                  0x28
+#define ADC7_AMUX_THM6_30K_PU                  0x29
+#define ADC7_GPIO1_30K_PU                      0x2a
+#define ADC7_GPIO2_30K_PU                      0x2b
+#define ADC7_GPIO3_30K_PU                      0x2c
+#define ADC7_GPIO4_30K_PU                      0x2d
+#define ADC7_CC1_ID_30K_PU                     0x33
+
+/* 100k pull-up2 */
+#define ADC7_AMUX_THM1_100K_PU                 0x44
+#define ADC7_AMUX_THM2_100K_PU                 0x45
+#define ADC7_AMUX_THM3_100K_PU                 0x46
+#define ADC7_AMUX_THM4_100K_PU                 0x47
+#define ADC7_AMUX_THM5_100K_PU                 0x48
+#define ADC7_AMUX_THM6_100K_PU                 0x49
+#define ADC7_GPIO1_100K_PU                     0x4a
+#define ADC7_GPIO2_100K_PU                     0x4b
+#define ADC7_GPIO3_100K_PU                     0x4c
+#define ADC7_GPIO4_100K_PU                     0x4d
+#define ADC7_CC1_ID_100K_PU                    0x53
+
+/* 400k pull-up3 */
+#define ADC7_AMUX_THM1_400K_PU                 0x64
+#define ADC7_AMUX_THM2_400K_PU                 0x65
+#define ADC7_AMUX_THM3_400K_PU                 0x66
+#define ADC7_AMUX_THM4_400K_PU                 0x67
+#define ADC7_AMUX_THM5_400K_PU                 0x68
+#define ADC7_AMUX_THM6_400K_PU                 0x69
+#define ADC7_GPIO1_400K_PU                     0x6a
+#define ADC7_GPIO2_400K_PU                     0x6b
+#define ADC7_GPIO3_400K_PU                     0x6c
+#define ADC7_GPIO4_400K_PU                     0x6d
+#define ADC7_CC1_ID_400K_PU                    0x73
+
+/* 1/3 Divider */
+#define ADC7_GPIO1_DIV3                                0x8a
+#define ADC7_GPIO2_DIV3                                0x8b
+#define ADC7_GPIO3_DIV3                                0x8c
+#define ADC7_GPIO4_DIV3                                0x8d
+
+#define ADC7_VPH_PWR                           0x8e
+#define ADC7_VBAT_SNS                          0x8f
+
+#define ADC7_SBUx                              0x94
+#define ADC7_VBAT_2S_MID                       0x96
+
 #endif /* _DT_BINDINGS_QCOM_SPMI_VADC_H */
index 7bc961d..caa8bb2 100644 (file)
@@ -42,6 +42,10 @@ typedef irqreturn_t (*cros_ec_sensors_capture_t)(int irq, void *p);
  * @resp:                      motion sensor response structure
  * @type:                      type of motion sensor
  * @loc:                       location where the motion sensor is placed
+ * @range_updated:             True if the range of the sensor has been
+ *                             updated.
+ * @curr_range:                        If updated, the current range value.
+ *                             It will be reapplied at every resume.
  * @calib:                     calibration parameters. Note that trigger
  *                             captured data will always provide the calibrated
  *                             data
@@ -65,6 +69,9 @@ struct cros_ec_sensors_core_state {
        enum motionsensor_type type;
        enum motionsensor_location loc;
 
+       bool range_updated;
+       int curr_range;
+
        struct calib_data {
                s16 offset;
                u16 scale;
@@ -114,7 +121,9 @@ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st,
                               struct iio_chan_spec const *chan,
                               int val, int val2, long mask);
 
-/* List of extended channel specification for all sensors */
+extern const struct dev_pm_ops cros_ec_sensors_pm_ops;
+
+/* List of extended channel specification for all sensors. */
 extern const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[];
 extern const struct attribute *cros_ec_sensor_fifo_attributes[];
 
diff --git a/include/linux/iio/iio-opaque.h b/include/linux/iio/iio-opaque.h
new file mode 100644 (file)
index 0000000..f2e9419
--- /dev/null
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _INDUSTRIAL_IO_OPAQUE_H_
+#define _INDUSTRIAL_IO_OPAQUE_H_
+
+/**
+ * struct iio_dev_opaque - industrial I/O device opaque information
+ * @indio_dev:                 public industrial I/O device information
+ * @event_interface:           event chrdevs associated with interrupt lines
+ * @buffer_list:               list of all buffers currently attached
+ * @channel_attr_list:         keep track of automatically created channel
+ *                             attributes
+ * @chan_attr_group:           group for all attrs in base directory
+ * @debugfs_dentry:            device specific debugfs dentry
+ * @cached_reg_addr:           cached register address for debugfs reads
+ * @read_buf:                  read buffer to be used for the initial reg read
+ * @read_buf_len:              data length in @read_buf
+ */
+struct iio_dev_opaque {
+       struct iio_dev                  indio_dev;
+       struct iio_event_interface      *event_interface;
+       struct list_head                buffer_list;
+       struct list_head                channel_attr_list;
+       struct attribute_group          chan_attr_group;
+#if defined(CONFIG_DEBUG_FS)
+       struct dentry                   *debugfs_dentry;
+       unsigned                        cached_reg_addr;
+       char                            read_buf[20];
+       unsigned int                    read_buf_len;
+#endif
+};
+
+#define to_iio_dev_opaque(indio_dev)           \
+       container_of(indio_dev, struct iio_dev_opaque, indio_dev)
+
+#endif
index a1be82e..e2df67a 100644 (file)
@@ -488,9 +488,7 @@ struct iio_buffer_setup_ops {
  * @currentmode:       [DRIVER] current operating mode
  * @dev:               [DRIVER] device structure, should be assigned a parent
  *                     and owner
- * @event_interface:   [INTERN] event chrdevs associated with interrupt lines
  * @buffer:            [DRIVER] any buffer present
- * @buffer_list:       [INTERN] list of all buffers currently attached
  * @scan_bytes:                [INTERN] num bytes captured to be fed to buffer demux
  * @mlock:             [INTERN] lock used to prevent simultaneous device state
  *                     changes
@@ -506,9 +504,6 @@ struct iio_buffer_setup_ops {
  * @pollfunc_event:    [DRIVER] function run on events trigger being received
  * @channels:          [DRIVER] channel specification structure table
  * @num_channels:      [DRIVER] number of channels specified in @channels.
- * @channel_attr_list: [INTERN] keep track of automatically created channel
- *                     attributes
- * @chan_attr_group:   [INTERN] group for all attrs in base directory
  * @name:              [DRIVER] name of the device.
  * @label:              [DRIVER] unique name to identify which device this is
  * @info:              [DRIVER] callbacks and constant info from driver
@@ -520,8 +515,8 @@ struct iio_buffer_setup_ops {
  * @groups:            [INTERN] attribute groups
  * @groupcounter:      [INTERN] index of next attribute group
  * @flags:             [INTERN] file ops related flags including busy flag.
- * @debugfs_dentry:    [INTERN] device specific debugfs dentry.
- * @cached_reg_addr:   [INTERN] cached register address for debugfs reads.
+ * @priv:              [DRIVER] reference to driver's private information
+ *                     **MUST** be accessed **ONLY** via iio_priv() helper
  */
 struct iio_dev {
        int                             id;
@@ -531,10 +526,7 @@ struct iio_dev {
        int                             currentmode;
        struct device                   dev;
 
-       struct iio_event_interface      *event_interface;
-
        struct iio_buffer               *buffer;
-       struct list_head                buffer_list;
        int                             scan_bytes;
        struct mutex                    mlock;
 
@@ -551,8 +543,6 @@ struct iio_dev {
        struct iio_chan_spec const      *channels;
        int                             num_channels;
 
-       struct list_head                channel_attr_list;
-       struct attribute_group          chan_attr_group;
        const char                      *name;
        const char                      *label;
        const struct iio_info           *info;
@@ -565,12 +555,7 @@ struct iio_dev {
        int                             groupcounter;
 
        unsigned long                   flags;
-#if defined(CONFIG_DEBUG_FS)
-       struct dentry                   *debugfs_dentry;
-       unsigned                        cached_reg_addr;
-       char                            read_buf[20];
-       unsigned int                    read_buf_len;
-#endif
+       void                            *priv;
 };
 
 const struct iio_chan_spec
@@ -649,6 +634,26 @@ static inline struct iio_dev *iio_device_get(struct iio_dev *indio_dev)
        return indio_dev ? dev_to_iio_dev(get_device(&indio_dev->dev)) : NULL;
 }
 
+/**
+ * iio_device_set_parent() - assign parent device to the IIO device object
+ * @indio_dev:                 IIO device structure
+ * @parent:            reference to parent device object
+ *
+ * This utility must be called between IIO device allocation
+ * (via devm_iio_device_alloc()) & IIO device registration
+ * (via {devm_}iio_device_register()).
+ * By default, the device allocation will also assign a parent device to
+ * the IIO device object. In cases where devm_iio_device_alloc() is used,
+ * sometimes the parent device must be different than the device used to
+ * manage the allocation.
+ * In that case, this helper should be used to change the parent, hence the
+ * requirement to call this between allocation & registration.
+ **/
+static inline void iio_device_set_parent(struct iio_dev *indio_dev,
+                                        struct device *parent)
+{
+       indio_dev->dev.parent = parent;
+}
 
 /**
  * iio_device_set_drvdata() - Set device driver data
@@ -669,28 +674,23 @@ static inline void iio_device_set_drvdata(struct iio_dev *indio_dev, void *data)
  *
  * Returns the data previously set with iio_device_set_drvdata()
  */
-static inline void *iio_device_get_drvdata(struct iio_dev *indio_dev)
+static inline void *iio_device_get_drvdata(const struct iio_dev *indio_dev)
 {
        return dev_get_drvdata(&indio_dev->dev);
 }
 
 /* Can we make this smaller? */
 #define IIO_ALIGN L1_CACHE_BYTES
-struct iio_dev *iio_device_alloc(int sizeof_priv);
+struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv);
 
+/* The information at the returned address is guaranteed to be cacheline aligned */
 static inline void *iio_priv(const struct iio_dev *indio_dev)
 {
-       return (char *)indio_dev + ALIGN(sizeof(struct iio_dev), IIO_ALIGN);
-}
-
-static inline struct iio_dev *iio_priv_to_dev(void *priv)
-{
-       return (struct iio_dev *)((char *)priv -
-                                 ALIGN(sizeof(struct iio_dev), IIO_ALIGN));
+       return indio_dev->priv;
 }
 
 void iio_device_free(struct iio_dev *indio_dev);
-struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv);
+struct iio_dev *devm_iio_device_alloc(struct device *parent, int sizeof_priv);
 struct iio_trigger *devm_iio_trigger_alloc(struct device *dev,
                                                const char *fmt, ...);
 /**
@@ -709,10 +709,7 @@ static inline bool iio_buffer_enabled(struct iio_dev *indio_dev)
  * @indio_dev:         IIO device structure for device
  **/
 #if defined(CONFIG_DEBUG_FS)
-static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev)
-{
-       return indio_dev->debugfs_dentry;
-}
+struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev);
 #else
 static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev)
 {
index c3c6ba5..3aa2f13 100644 (file)
@@ -50,11 +50,4 @@ irqreturn_t iio_pollfunc_store_time(int irq, void *p);
 
 void iio_trigger_notify_done(struct iio_trigger *trig);
 
-/*
- * Two functions for common case where all that happens is a pollfunc
- * is attached and detached from a trigger
- */
-int iio_triggered_buffer_postenable(struct iio_dev *indio_dev);
-int iio_triggered_buffer_predisable(struct iio_dev *indio_dev);
-
 #endif