summaryrefslogtreecommitdiff
path: root/drivers/iio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio')
-rw-r--r--drivers/iio/accel/Kconfig18
-rw-r--r--drivers/iio/accel/Makefile1
-rw-r--r--drivers/iio/accel/adis16201.c1
-rw-r--r--drivers/iio/accel/adis16209.c1
-rw-r--r--drivers/iio/accel/adxl345_core.c3
-rw-r--r--drivers/iio/accel/adxl372.c21
-rw-r--r--drivers/iio/accel/bma180.c209
-rw-r--r--drivers/iio/accel/bma220_spi.c3
-rw-r--r--drivers/iio/accel/bma400_core.c1
-rw-r--r--drivers/iio/accel/bma400_spi.c120
-rw-r--r--drivers/iio/accel/bmc150-accel-core.c20
-rw-r--r--drivers/iio/accel/cros_ec_accel_legacy.c46
-rw-r--r--drivers/iio/accel/da280.c1
-rw-r--r--drivers/iio/accel/da311.c1
-rw-r--r--drivers/iio/accel/dmard06.c4
-rw-r--r--drivers/iio/accel/dmard09.c1
-rw-r--r--drivers/iio/accel/dmard10.c1
-rw-r--r--drivers/iio/accel/hid-sensor-accel-3d.c19
-rw-r--r--drivers/iio/accel/kxcjk-1013.c3
-rw-r--r--drivers/iio/accel/kxsd9-i2c.c11
-rw-r--r--drivers/iio/accel/kxsd9.c19
-rw-r--r--drivers/iio/accel/mc3230.c1
-rw-r--r--drivers/iio/accel/mma7455_core.c17
-rw-r--r--drivers/iio/accel/mma7660.c1
-rw-r--r--drivers/iio/accel/mma8452.c19
-rw-r--r--drivers/iio/accel/mma9551.c1
-rw-r--r--drivers/iio/accel/mma9553.c1
-rw-r--r--drivers/iio/accel/mxc4005.c7
-rw-r--r--drivers/iio/accel/mxc6255.c1
-rw-r--r--drivers/iio/accel/sca3000.c13
-rw-r--r--drivers/iio/accel/ssp_accel_sensor.c2
-rw-r--r--drivers/iio/accel/st_accel.h2
-rw-r--r--drivers/iio/accel/st_accel_buffer.c23
-rw-r--r--drivers/iio/accel/st_accel_core.c83
-rw-r--r--drivers/iio/accel/st_accel_i2c.c5
-rw-r--r--drivers/iio/accel/stk8312.c3
-rw-r--r--drivers/iio/accel/stk8ba50.c3
-rw-r--r--drivers/iio/adc/Kconfig60
-rw-r--r--drivers/iio/adc/Makefile4
-rw-r--r--drivers/iio/adc/ab8500-gpadc.c4
-rw-r--r--drivers/iio/adc/ad7091r-base.c1
-rw-r--r--drivers/iio/adc/ad7124.c74
-rw-r--r--drivers/iio/adc/ad7192.c19
-rw-r--r--drivers/iio/adc/ad7266.c4
-rw-r--r--drivers/iio/adc/ad7291.c2
-rw-r--r--drivers/iio/adc/ad7292.c1
-rw-r--r--drivers/iio/adc/ad7298.c10
-rw-r--r--drivers/iio/adc/ad7476.c62
-rw-r--r--drivers/iio/adc/ad7606.c4
-rw-r--r--drivers/iio/adc/ad7766.c3
-rw-r--r--drivers/iio/adc/ad7768-1.c9
-rw-r--r--drivers/iio/adc/ad7780.c30
-rw-r--r--drivers/iio/adc/ad7791.c66
-rw-r--r--drivers/iio/adc/ad7793.c146
-rw-r--r--drivers/iio/adc/ad7887.c7
-rw-r--r--drivers/iio/adc/ad7923.c10
-rw-r--r--drivers/iio/adc/ad7949.c4
-rw-r--r--drivers/iio/adc/ad799x.c4
-rw-r--r--drivers/iio/adc/ad9467.c422
-rw-r--r--drivers/iio/adc/ad_sigma_delta.c20
-rw-r--r--drivers/iio/adc/adi-axi-adc.c481
-rw-r--r--drivers/iio/adc/aspeed_adc.c1
-rw-r--r--drivers/iio/adc/at91-sama5d2_adc.c256
-rw-r--r--drivers/iio/adc/at91_adc.c38
-rw-r--r--drivers/iio/adc/axp20x_adc.c2
-rw-r--r--drivers/iio/adc/axp288_adc.c1
-rw-r--r--drivers/iio/adc/bcm_iproc_adc.c2
-rw-r--r--drivers/iio/adc/berlin2-adc.c1
-rw-r--r--drivers/iio/adc/cc10001_adc.c1
-rw-r--r--drivers/iio/adc/cpcap-adc.c32
-rw-r--r--drivers/iio/adc/da9150-gpadc.c2
-rw-r--r--drivers/iio/adc/dln2-adc.c13
-rw-r--r--drivers/iio/adc/envelope-detector.c2
-rw-r--r--drivers/iio/adc/ep93xx_adc.c1
-rw-r--r--drivers/iio/adc/exynos_adc.c19
-rw-r--r--drivers/iio/adc/fsl-imx25-gcq.c5
-rw-r--r--drivers/iio/adc/hi8435.c8
-rw-r--r--drivers/iio/adc/hx711.c1
-rw-r--r--drivers/iio/adc/imx7d_adc.c1
-rw-r--r--drivers/iio/adc/ina2xx-adc.c15
-rw-r--r--drivers/iio/adc/ingenic-adc.c397
-rw-r--r--drivers/iio/adc/intel_mrfld_adc.c7
-rw-r--r--drivers/iio/adc/lp8788_adc.c2
-rw-r--r--drivers/iio/adc/lpc18xx_adc.c1
-rw-r--r--drivers/iio/adc/lpc32xx_adc.c6
-rw-r--r--drivers/iio/adc/ltc2471.c1
-rw-r--r--drivers/iio/adc/ltc2485.c1
-rw-r--r--drivers/iio/adc/ltc2496.c4
-rw-r--r--drivers/iio/adc/ltc2497-core.c1
-rw-r--r--drivers/iio/adc/ltc2497.c4
-rw-r--r--drivers/iio/adc/max1027.c7
-rw-r--r--drivers/iio/adc/max11100.c7
-rw-r--r--drivers/iio/adc/max1118.c18
-rw-r--r--drivers/iio/adc/max1241.c226
-rw-r--r--drivers/iio/adc/max1363.c47
-rw-r--r--drivers/iio/adc/max9611.c6
-rw-r--r--drivers/iio/adc/mcp320x.c15
-rw-r--r--drivers/iio/adc/mcp3422.c33
-rw-r--r--drivers/iio/adc/mcp3911.c2
-rw-r--r--drivers/iio/adc/men_z188_adc.c1
-rw-r--r--drivers/iio/adc/meson_saradc.c4
-rw-r--r--drivers/iio/adc/mp2629_adc.c208
-rw-r--r--drivers/iio/adc/mt6577_auxadc.c1
-rw-r--r--drivers/iio/adc/mxs-lradc-adc.c3
-rw-r--r--drivers/iio/adc/nau7802.c2
-rw-r--r--drivers/iio/adc/npcm_adc.c1
-rw-r--r--drivers/iio/adc/palmas_gpadc.c4
-rw-r--r--drivers/iio/adc/qcom-pm8xxx-xoadc.c5
-rw-r--r--drivers/iio/adc/qcom-spmi-adc5.c246
-rw-r--r--drivers/iio/adc/qcom-spmi-iadc.c2
-rw-r--r--drivers/iio/adc/qcom-spmi-vadc.c2
-rw-r--r--drivers/iio/adc/qcom-vadc-common.c262
-rw-r--r--drivers/iio/adc/qcom-vadc-common.h15
-rw-r--r--drivers/iio/adc/rcar-gyroadc.c2
-rw-r--r--drivers/iio/adc/rn5t618-adc.c1
-rw-r--r--drivers/iio/adc/rockchip_saradc.c221
-rw-r--r--drivers/iio/adc/sc27xx_adc.c1
-rw-r--r--drivers/iio/adc/sd_adc_modulator.c7
-rw-r--r--drivers/iio/adc/spear_adc.c1
-rw-r--r--drivers/iio/adc/stm32-adc-core.c34
-rw-r--r--drivers/iio/adc/stm32-adc.c155
-rw-r--r--drivers/iio/adc/stm32-dfsdm-adc.c105
-rw-r--r--drivers/iio/adc/stmpe-adc.c1
-rw-r--r--drivers/iio/adc/stx104.c1
-rw-r--r--drivers/iio/adc/sun4i-gpadc-iio.c6
-rw-r--r--drivers/iio/adc/ti-adc081c.c25
-rw-r--r--drivers/iio/adc/ti-adc0832.c11
-rw-r--r--drivers/iio/adc/ti-adc084s021.c19
-rw-r--r--drivers/iio/adc/ti-adc108s102.c1
-rw-r--r--drivers/iio/adc/ti-adc12138.c1
-rw-r--r--drivers/iio/adc/ti-adc128s052.c8
-rw-r--r--drivers/iio/adc/ti-adc161s626.c5
-rw-r--r--drivers/iio/adc/ti-ads1015.c14
-rw-r--r--drivers/iio/adc/ti-ads124s08.c11
-rw-r--r--drivers/iio/adc/ti-ads7950.c3
-rw-r--r--drivers/iio/adc/ti-ads8344.c4
-rw-r--r--drivers/iio/adc/ti-ads8688.c2
-rw-r--r--drivers/iio/adc/ti-tlc4541.c10
-rw-r--r--drivers/iio/adc/ti_am335x_adc.c46
-rw-r--r--drivers/iio/adc/twl4030-madc.c18
-rw-r--r--drivers/iio/adc/twl6030-gpadc.c5
-rw-r--r--drivers/iio/adc/vf610_adc.c9
-rw-r--r--drivers/iio/adc/viperboard_adc.c1
-rw-r--r--drivers/iio/adc/xilinx-xadc-core.c8
-rw-r--r--drivers/iio/adc/xilinx-xadc-events.c2
-rw-r--r--drivers/iio/adc/xilinx-xadc.h2
-rw-r--r--drivers/iio/afe/iio-rescale.c1
-rw-r--r--drivers/iio/amplifiers/ad8366.c8
-rw-r--r--drivers/iio/amplifiers/hmc425a.c1
-rw-r--r--drivers/iio/buffer/industrialio-buffer-dma.c1
-rw-r--r--drivers/iio/buffer/industrialio-buffer-dmaengine.c41
-rw-r--r--drivers/iio/buffer/industrialio-hw-consumer.c31
-rw-r--r--drivers/iio/buffer/industrialio-triggered-buffer.c21
-rw-r--r--drivers/iio/buffer/kfifo_buf.c22
-rw-r--r--drivers/iio/chemical/Kconfig44
-rw-r--r--drivers/iio/chemical/Makefile4
-rw-r--r--drivers/iio/chemical/ams-iaq-core.c1
-rw-r--r--drivers/iio/chemical/atlas-ezo-sensor.c176
-rw-r--r--drivers/iio/chemical/atlas-sensor.c43
-rw-r--r--drivers/iio/chemical/bme680_core.c37
-rw-r--r--drivers/iio/chemical/ccs811.c126
-rw-r--r--drivers/iio/chemical/pms7003.c18
-rw-r--r--drivers/iio/chemical/scd30.h78
-rw-r--r--drivers/iio/chemical/scd30_core.c771
-rw-r--r--drivers/iio/chemical/scd30_i2c.c139
-rw-r--r--drivers/iio/chemical/scd30_serial.c263
-rw-r--r--drivers/iio/chemical/sgp30.c1
-rw-r--r--drivers/iio/chemical/sps30.c12
-rw-r--r--drivers/iio/chemical/vz89x.c1
-rw-r--r--drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c5
-rw-r--r--drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c29
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-trigger.c18
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-trigger.h3
-rw-r--r--drivers/iio/common/ms_sensors/ms_sensors_i2c.c2
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_core.c13
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_i2c.c5
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_spi.c7
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_trigger.c13
-rw-r--r--drivers/iio/dac/Kconfig8
-rw-r--r--drivers/iio/dac/ad5064.c3
-rw-r--r--drivers/iio/dac/ad5360.c18
-rw-r--r--drivers/iio/dac/ad5380.c11
-rw-r--r--drivers/iio/dac/ad5421.c22
-rw-r--r--drivers/iio/dac/ad5446.c29
-rw-r--r--drivers/iio/dac/ad5449.c13
-rw-r--r--drivers/iio/dac/ad5504.c8
-rw-r--r--drivers/iio/dac/ad5592r-base.c45
-rw-r--r--drivers/iio/dac/ad5592r-base.h1
-rw-r--r--drivers/iio/dac/ad5592r.c4
-rw-r--r--drivers/iio/dac/ad5593r.c2
-rw-r--r--drivers/iio/dac/ad5624r_spi.c9
-rw-r--r--drivers/iio/dac/ad5686.c11
-rw-r--r--drivers/iio/dac/ad5686.h2
-rw-r--r--drivers/iio/dac/ad5755.c23
-rw-r--r--drivers/iio/dac/ad5758.c19
-rw-r--r--drivers/iio/dac/ad5761.c17
-rw-r--r--drivers/iio/dac/ad5764.c16
-rw-r--r--drivers/iio/dac/ad5770r.c1
-rw-r--r--drivers/iio/dac/ad5791.c11
-rw-r--r--drivers/iio/dac/ad7303.c1
-rw-r--r--drivers/iio/dac/ad8801.c1
-rw-r--r--drivers/iio/dac/cio-dac.c1
-rw-r--r--drivers/iio/dac/dpot-dac.c6
-rw-r--r--drivers/iio/dac/ds4424.c2
-rw-r--r--drivers/iio/dac/lpc18xx_dac.c1
-rw-r--r--drivers/iio/dac/ltc1660.c1
-rw-r--r--drivers/iio/dac/ltc2632.c74
-rw-r--r--drivers/iio/dac/m62332.c3
-rw-r--r--drivers/iio/dac/max517.c3
-rw-r--r--drivers/iio/dac/max5821.c1
-rw-r--r--drivers/iio/dac/mcp4725.c1
-rw-r--r--drivers/iio/dac/mcp4922.c1
-rw-r--r--drivers/iio/dac/stm32-dac.c1
-rw-r--r--drivers/iio/dac/ti-dac082s085.c13
-rw-r--r--drivers/iio/dac/ti-dac5571.c20
-rw-r--r--drivers/iio/dac/ti-dac7311.c4
-rw-r--r--drivers/iio/dac/ti-dac7612.c5
-rw-r--r--drivers/iio/dac/vf610_dac.c13
-rw-r--r--drivers/iio/dummy/iio_dummy_evgen.c31
-rw-r--r--drivers/iio/dummy/iio_simple_dummy.c21
-rw-r--r--drivers/iio/dummy/iio_simple_dummy_buffer.c18
-rw-r--r--drivers/iio/dummy/iio_simple_dummy_events.c4
-rw-r--r--drivers/iio/frequency/ad9523.c1
-rw-r--r--drivers/iio/frequency/adf4350.c1
-rw-r--r--drivers/iio/frequency/adf4371.c1
-rw-r--r--drivers/iio/gyro/Kconfig2
-rw-r--r--drivers/iio/gyro/adis16080.c1
-rw-r--r--drivers/iio/gyro/adis16130.c5
-rw-r--r--drivers/iio/gyro/adis16136.c11
-rw-r--r--drivers/iio/gyro/adis16260.c1
-rw-r--r--drivers/iio/gyro/adxrs450.c1
-rw-r--r--drivers/iio/gyro/bmg160_core.c3
-rw-r--r--drivers/iio/gyro/bmg160_i2c.c6
-rw-r--r--drivers/iio/gyro/bmg160_spi.c5
-rw-r--r--drivers/iio/gyro/fxas21002c.h66
-rw-r--r--drivers/iio/gyro/fxas21002c_core.c67
-rw-r--r--drivers/iio/gyro/hid-sensor-gyro-3d.c19
-rw-r--r--drivers/iio/gyro/itg3200_core.c1
-rw-r--r--drivers/iio/gyro/mpu3050-core.c3
-rw-r--r--drivers/iio/gyro/mpu3050-i2c.c4
-rw-r--r--drivers/iio/gyro/ssp_gyro_sensor.c1
-rw-r--r--drivers/iio/gyro/st_gyro_buffer.c22
-rw-r--r--drivers/iio/gyro/st_gyro_core.c9
-rw-r--r--drivers/iio/health/afe4403.c24
-rw-r--r--drivers/iio/health/afe4404.c11
-rw-r--r--drivers/iio/health/afe440x.h2
-rw-r--r--drivers/iio/health/max30100.c8
-rw-r--r--drivers/iio/health/max30102.c5
-rw-r--r--drivers/iio/humidity/am2315.c1
-rw-r--r--drivers/iio/humidity/dht11.c1
-rw-r--r--drivers/iio/humidity/hdc100x.c33
-rw-r--r--drivers/iio/humidity/hid-sensor-humidity.c13
-rw-r--r--drivers/iio/humidity/hts221.h11
-rw-r--r--drivers/iio/humidity/hts221_buffer.c26
-rw-r--r--drivers/iio/humidity/hts221_core.c5
-rw-r--r--drivers/iio/humidity/hts221_i2c.c6
-rw-r--r--drivers/iio/humidity/hts221_spi.c6
-rw-r--r--drivers/iio/humidity/htu21.c1
-rw-r--r--drivers/iio/humidity/si7005.c1
-rw-r--r--drivers/iio/humidity/si7020.c1
-rw-r--r--drivers/iio/iio_core_trigger.h17
-rw-r--r--drivers/iio/imu/Kconfig14
-rw-r--r--drivers/iio/imu/Makefile2
-rw-r--r--drivers/iio/imu/adis.c33
-rw-r--r--drivers/iio/imu/adis16400.c22
-rw-r--r--drivers/iio/imu/adis16460.c26
-rw-r--r--drivers/iio/imu/adis16475.c1337
-rw-r--r--drivers/iio/imu/adis16480.c23
-rw-r--r--drivers/iio/imu/adis_buffer.c58
-rw-r--r--drivers/iio/imu/adis_trigger.c72
-rw-r--r--drivers/iio/imu/bmi160/bmi160.h3
-rw-r--r--drivers/iio/imu/bmi160/bmi160_core.c47
-rw-r--r--drivers/iio/imu/bmi160/bmi160_i2c.c4
-rw-r--r--drivers/iio/imu/bmi160/bmi160_spi.c4
-rw-r--r--drivers/iio/imu/fxos8700_core.c1
-rw-r--r--drivers/iio/imu/inv_icm42600/Kconfig29
-rw-r--r--drivers/iio/imu/inv_icm42600/Makefile15
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600.h395
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c787
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c601
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h98
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_core.c786
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c798
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c101
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c100
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c84
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h30
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c195
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h85
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c14
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_core.c38
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c4
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c2
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c4
-rw-r--r--drivers/iio/imu/kmx61.c15
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h10
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c23
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c24
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c105
-rw-r--r--drivers/iio/industrialio-buffer.c149
-rw-r--r--drivers/iio/industrialio-core.c258
-rw-r--r--drivers/iio/industrialio-event.c68
-rw-r--r--drivers/iio/industrialio-trigger.c75
-rw-r--r--drivers/iio/inkern.c27
-rw-r--r--drivers/iio/light/Kconfig2
-rw-r--r--drivers/iio/light/acpi-als.c1
-rw-r--r--drivers/iio/light/adjd_s311.c1
-rw-r--r--drivers/iio/light/adux1020.c1
-rw-r--r--drivers/iio/light/al3010.c1
-rw-r--r--drivers/iio/light/al3320a.c1
-rw-r--r--drivers/iio/light/apds9300.c1
-rw-r--r--drivers/iio/light/apds9960.c1
-rw-r--r--drivers/iio/light/bh1750.c1
-rw-r--r--drivers/iio/light/bh1780.c7
-rw-r--r--drivers/iio/light/cm32181.c270
-rw-r--r--drivers/iio/light/cm3232.c4
-rw-r--r--drivers/iio/light/cm3323.c1
-rw-r--r--drivers/iio/light/cm3605.c1
-rw-r--r--drivers/iio/light/cm36651.c1
-rw-r--r--drivers/iio/light/cros_ec_light_prox.c6
-rw-r--r--drivers/iio/light/gp2ap002.c20
-rw-r--r--drivers/iio/light/gp2ap020a00f.c17
-rw-r--r--drivers/iio/light/hid-sensor-als.c19
-rw-r--r--drivers/iio/light/hid-sensor-prox.c19
-rw-r--r--drivers/iio/light/iqs621-als.c7
-rw-r--r--drivers/iio/light/isl29018.c1
-rw-r--r--drivers/iio/light/isl29028.c1
-rw-r--r--drivers/iio/light/isl29125.c11
-rw-r--r--drivers/iio/light/jsa1212.c1
-rw-r--r--drivers/iio/light/lm3533-als.c2
-rw-r--r--drivers/iio/light/ltr501.c57
-rw-r--r--drivers/iio/light/lv0104cs.c3
-rw-r--r--drivers/iio/light/max44000.c13
-rw-r--r--drivers/iio/light/max44009.c1
-rw-r--r--drivers/iio/light/noa1305.c1
-rw-r--r--drivers/iio/light/opt3001.c6
-rw-r--r--drivers/iio/light/pa12203001.c1
-rw-r--r--drivers/iio/light/rpr0521.c3
-rw-r--r--drivers/iio/light/si1133.c19
-rw-r--r--drivers/iio/light/si1145.c11
-rw-r--r--drivers/iio/light/st_uvis25_core.c3
-rw-r--r--drivers/iio/light/st_uvis25_i2c.c7
-rw-r--r--drivers/iio/light/st_uvis25_spi.c7
-rw-r--r--drivers/iio/light/stk3310.c5
-rw-r--r--drivers/iio/light/tcs3414.c21
-rw-r--r--drivers/iio/light/tcs3472.c1
-rw-r--r--drivers/iio/light/tsl2563.c15
-rw-r--r--drivers/iio/light/tsl2583.c1
-rw-r--r--drivers/iio/light/tsl2772.c7
-rw-r--r--drivers/iio/light/tsl4531.c1
-rw-r--r--drivers/iio/light/us5182d.c9
-rw-r--r--drivers/iio/light/vcnl4000.c726
-rw-r--r--drivers/iio/light/vcnl4035.c1
-rw-r--r--drivers/iio/light/veml6030.c1
-rw-r--r--drivers/iio/light/veml6070.c1
-rw-r--r--drivers/iio/light/vl6180.c4
-rw-r--r--drivers/iio/light/zopt2201.c5
-rw-r--r--drivers/iio/magnetometer/ak8974.c234
-rw-r--r--drivers/iio/magnetometer/ak8975.c39
-rw-r--r--drivers/iio/magnetometer/bmc150_magn.c3
-rw-r--r--drivers/iio/magnetometer/bmc150_magn_i2c.c3
-rw-r--r--drivers/iio/magnetometer/bmc150_magn_spi.c4
-rw-r--r--drivers/iio/magnetometer/hid-sensor-magn-3d.c19
-rw-r--r--drivers/iio/magnetometer/hmc5843.h6
-rw-r--r--drivers/iio/magnetometer/hmc5843_core.c1
-rw-r--r--drivers/iio/magnetometer/mag3110.c1
-rw-r--r--drivers/iio/magnetometer/mmc35240.c9
-rw-r--r--drivers/iio/magnetometer/rm3100-core.c8
-rw-r--r--drivers/iio/magnetometer/st_magn_buffer.c26
-rw-r--r--drivers/iio/magnetometer/st_magn_core.c3
-rw-r--r--drivers/iio/multiplexer/iio-mux.c1
-rw-r--r--drivers/iio/orientation/hid-sensor-incl-3d.c19
-rw-r--r--drivers/iio/orientation/hid-sensor-rotation.c19
-rw-r--r--drivers/iio/position/iqs624-pos.c7
-rw-r--r--drivers/iio/potentiometer/ad5272.c3
-rw-r--r--drivers/iio/potentiometer/ds1803.c1
-rw-r--r--drivers/iio/potentiometer/max5432.c1
-rw-r--r--drivers/iio/potentiometer/max5481.c3
-rw-r--r--drivers/iio/potentiometer/max5487.c1
-rw-r--r--drivers/iio/potentiometer/mcp4018.c1
-rw-r--r--drivers/iio/potentiometer/mcp41010.c3
-rw-r--r--drivers/iio/potentiometer/mcp4131.c3
-rw-r--r--drivers/iio/potentiometer/mcp4531.c1
-rw-r--r--drivers/iio/potentiometer/tpl0102.c1
-rw-r--r--drivers/iio/potentiostat/lmp91000.c14
-rw-r--r--drivers/iio/pressure/abp060mg.c1
-rw-r--r--drivers/iio/pressure/bmp280-core.c101
-rw-r--r--drivers/iio/pressure/cros_ec_baro.c8
-rw-r--r--drivers/iio/pressure/dlhl60d.c4
-rw-r--r--drivers/iio/pressure/dps310.c1
-rw-r--r--drivers/iio/pressure/hid-sensor-press.c19
-rw-r--r--drivers/iio/pressure/hp03.c1
-rw-r--r--drivers/iio/pressure/hp206c.c9
-rw-r--r--drivers/iio/pressure/icp10100.c1
-rw-r--r--drivers/iio/pressure/mpl115.c1
-rw-r--r--drivers/iio/pressure/mpl3115.c1
-rw-r--r--drivers/iio/pressure/ms5611_core.c12
-rw-r--r--drivers/iio/pressure/ms5611_i2c.c4
-rw-r--r--drivers/iio/pressure/ms5611_spi.c4
-rw-r--r--drivers/iio/pressure/ms5637.c1
-rw-r--r--drivers/iio/pressure/st_pressure_buffer.c26
-rw-r--r--drivers/iio/pressure/st_pressure_core.c7
-rw-r--r--drivers/iio/pressure/t5403.c1
-rw-r--r--drivers/iio/pressure/zpa2326.c41
-rw-r--r--drivers/iio/proximity/Kconfig24
-rw-r--r--drivers/iio/proximity/Makefile2
-rw-r--r--drivers/iio/proximity/as3935.c1
-rw-r--r--drivers/iio/proximity/isl29501.c1
-rw-r--r--drivers/iio/proximity/mb1232.c18
-rw-r--r--drivers/iio/proximity/ping.c8
-rw-r--r--drivers/iio/proximity/pulsedlight-lidar-lite-v2.c1
-rw-r--r--drivers/iio/proximity/rfd77402.c1
-rw-r--r--drivers/iio/proximity/srf04.c3
-rw-r--r--drivers/iio/proximity/srf08.c7
-rw-r--r--drivers/iio/proximity/sx9310.c1066
-rw-r--r--drivers/iio/proximity/sx9500.c10
-rw-r--r--drivers/iio/proximity/vcnl3020.c257
-rw-r--r--drivers/iio/proximity/vl53l0x-i2c.c1
-rw-r--r--drivers/iio/resolver/ad2s1200.c1
-rw-r--r--drivers/iio/resolver/ad2s90.c1
-rw-r--r--drivers/iio/temperature/hid-sensor-temperature.c13
-rw-r--r--drivers/iio/temperature/iqs620at-temp.c1
-rw-r--r--drivers/iio/temperature/ltc2983.c5
-rw-r--r--drivers/iio/temperature/max31856.c7
-rw-r--r--drivers/iio/temperature/maxim_thermocouple.c1
-rw-r--r--drivers/iio/temperature/mlx90614.c1
-rw-r--r--drivers/iio/temperature/mlx90632.c5
-rw-r--r--drivers/iio/temperature/tmp006.c1
-rw-r--r--drivers/iio/temperature/tmp007.c1
-rw-r--r--drivers/iio/temperature/tsys01.c1
-rw-r--r--drivers/iio/temperature/tsys02d.c1
-rw-r--r--drivers/iio/trigger/iio-trig-hrtimer.c2
-rw-r--r--drivers/iio/trigger/stm32-timer-trigger.c2
433 files changed, 14827 insertions, 2838 deletions
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 5d91a6dda894..2e0c62c39155 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -89,13 +89,13 @@ config ADXL372_I2C
module will be called adxl372_i2c.
config BMA180
- tristate "Bosch BMA180/BMA25x 3-Axis Accelerometer Driver"
- depends on I2C
+ tristate "Bosch BMA023/BMA1x0/BMA25x 3-Axis Accelerometer Driver"
+ depends on I2C && INPUT_BMA150=n
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
- Say Y here if you want to build a driver for the Bosch BMA180 or
- BMA25x triaxial acceleration sensor.
+ Say Y here if you want to build a driver for the Bosch BMA023, BMA150
+ BMA180, SMB380, or BMA25x triaxial acceleration sensor.
To compile this driver as a module, choose M here: the
module will be called bma180.
@@ -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
@@ -238,7 +244,7 @@ config IIO_ST_ACCEL_3AXIS
Say yes here to build support for STMicroelectronics accelerometers:
LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC,
LIS331DLH, LSM303DL, LSM303DLM, LSM330, LIS2DH12, H3LIS331DL,
- LNG2DM, LIS3DE, LIS2DE12
+ LNG2DM, LIS3DE, LIS2DE12, LIS2HH12
This driver can also be built as a module. If so, these modules
will be created:
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
index 3a051cf37f40..4f6c1ebe13b0 100644
--- a/drivers/iio/accel/Makefile
+++ b/drivers/iio/accel/Makefile
@@ -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
diff --git a/drivers/iio/accel/adis16201.c b/drivers/iio/accel/adis16201.c
index 4154e7396bbe..59a24c355a1a 100644
--- a/drivers/iio/accel/adis16201.c
+++ b/drivers/iio/accel/adis16201.c
@@ -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;
diff --git a/drivers/iio/accel/adis16209.c b/drivers/iio/accel/adis16209.c
index 31d45e7c5485..3d5538e2f76e 100644
--- a/drivers/iio/accel/adis16209.c
+++ b/drivers/iio/accel/adis16209.c
@@ -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);
diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c
index 9c269799e6c1..312866530065 100644
--- a/drivers/iio/accel/adxl345_core.c
+++ b/drivers/iio/accel/adxl345_core.c
@@ -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;
diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index 60daf04ce188..e7e316b75e87 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -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;
diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c
index fcd91d5f05fd..5b7a467c7b27 100644
--- a/drivers/iio/accel/bma180.c
+++ b/drivers/iio/accel/bma180.c
@@ -7,6 +7,7 @@
* Support for BMA250 (c) Peter Meerwald <pmeerw@pmeerw.net>
*
* SPI is not supported by driver
+ * BMA023/BMA150/SMB380: 7-bit I2C slave address 0x38
* BMA180: 7-bit I2C slave address 0x40 or 0x41
* BMA250: 7-bit I2C slave address 0x18 or 0x19
* BMA254: 7-bit I2C slave address 0x18 or 0x19
@@ -33,6 +34,8 @@
#define BMA180_IRQ_NAME "bma180_event"
enum chip_ids {
+ BMA023,
+ BMA150,
BMA180,
BMA250,
BMA254,
@@ -48,7 +51,7 @@ struct bma180_part_info {
unsigned int num_scales;
const int *bw_table;
unsigned int num_bw;
- int center_temp;
+ int temp_offset;
u8 int_reset_reg, int_reset_mask;
u8 sleep_reg, sleep_mask;
@@ -57,13 +60,25 @@ struct bma180_part_info {
u8 power_reg, power_mask, lowpower_val;
u8 int_enable_reg, int_enable_mask;
u8 int_map_reg, int_enable_dataready_int1_mask;
- u8 softreset_reg;
+ u8 softreset_reg, softreset_val;
int (*chip_config)(struct bma180_data *data);
void (*chip_disable)(struct bma180_data *data);
};
/* Register set */
+#define BMA023_CTRL_REG0 0x0a
+#define BMA023_CTRL_REG1 0x0b
+#define BMA023_CTRL_REG2 0x14
+#define BMA023_CTRL_REG3 0x15
+
+#define BMA023_RANGE_MASK GENMASK(4, 3) /* Range of accel values */
+#define BMA023_BW_MASK GENMASK(2, 0) /* Accel bandwidth */
+#define BMA023_SLEEP BIT(0)
+#define BMA023_INT_RESET_MASK BIT(6)
+#define BMA023_NEW_DATA_INT BIT(5) /* Intr every new accel data is ready */
+#define BMA023_RESET_VAL BIT(1)
+
#define BMA180_CHIP_ID 0x00 /* Need to distinguish BMA180 from other */
#define BMA180_ACC_X_LSB 0x02 /* First of 6 registers of accel data */
#define BMA180_TEMP 0x08
@@ -94,6 +109,7 @@ struct bma180_part_info {
/* We have to write this value in reset register to do soft reset */
#define BMA180_RESET_VAL 0xb6
+#define BMA023_ID_REG_VAL 0x02
#define BMA180_ID_REG_VAL 0x03
#define BMA250_ID_REG_VAL 0x03
#define BMA254_ID_REG_VAL 0xfa /* 250 decimal */
@@ -156,6 +172,9 @@ enum bma180_chan {
TEMP
};
+static int bma023_bw_table[] = { 25, 50, 100, 190, 375, 750, 1500 }; /* Hz */
+static int bma023_scale_table[] = { 2452, 4903, 9709, };
+
static int bma180_bw_table[] = { 10, 20, 40, 75, 150, 300 }; /* Hz */
static int bma180_scale_table[] = { 1275, 1863, 2452, 3727, 4903, 9709, 19417 };
@@ -319,7 +338,8 @@ static int bma180_set_pmode(struct bma180_data *data, bool mode)
static int bma180_soft_reset(struct bma180_data *data)
{
int ret = i2c_smbus_write_byte_data(data->client,
- data->part_info->softreset_reg, BMA180_RESET_VAL);
+ data->part_info->softreset_reg,
+ data->part_info->softreset_val);
if (ret)
dev_err(&data->client->dev, "failed to reset the chip\n");
@@ -349,11 +369,28 @@ static int bma180_chip_init(struct bma180_data *data)
*/
msleep(20);
- ret = bma180_set_new_data_intr_state(data, false);
+ return bma180_set_new_data_intr_state(data, false);
+}
+
+static int bma023_chip_config(struct bma180_data *data)
+{
+ int ret = bma180_chip_init(data);
+
if (ret)
- return ret;
+ goto err;
+
+ ret = bma180_set_bw(data, 50); /* 50 Hz */
+ if (ret)
+ goto err;
+ ret = bma180_set_scale(data, 2452); /* 2 G */
+ if (ret)
+ goto err;
- return bma180_set_pmode(data, false);
+ return 0;
+
+err:
+ dev_err(&data->client->dev, "failed to config the chip\n");
+ return ret;
}
static int bma180_chip_config(struct bma180_data *data)
@@ -362,6 +399,9 @@ static int bma180_chip_config(struct bma180_data *data)
if (ret)
goto err;
+ ret = bma180_set_pmode(data, false);
+ if (ret)
+ goto err;
ret = bma180_set_bits(data, BMA180_CTRL_REG0, BMA180_DIS_WAKE_UP, 1);
if (ret)
goto err;
@@ -391,6 +431,9 @@ static int bma25x_chip_config(struct bma180_data *data)
if (ret)
goto err;
+ ret = bma180_set_pmode(data, false);
+ if (ret)
+ goto err;
ret = bma180_set_bw(data, 16); /* 16 Hz */
if (ret)
goto err;
@@ -413,6 +456,17 @@ err:
return ret;
}
+static void bma023_chip_disable(struct bma180_data *data)
+{
+ if (bma180_set_sleep_state(data, true))
+ goto err;
+
+ return;
+
+err:
+ dev_err(&data->client->dev, "failed to disable the chip\n");
+}
+
static void bma180_chip_disable(struct bma180_data *data)
{
if (bma180_set_new_data_intr_state(data, false))
@@ -512,8 +566,12 @@ static int bma180_read_raw(struct iio_dev *indio_dev,
iio_device_release_direct_mode(indio_dev);
if (ret < 0)
return ret;
- *val = sign_extend32(ret >> chan->scan_type.shift,
- chan->scan_type.realbits - 1);
+ if (chan->scan_type.sign == 's') {
+ *val = sign_extend32(ret >> chan->scan_type.shift,
+ chan->scan_type.realbits - 1);
+ } else {
+ *val = ret;
+ }
return IIO_VAL_INT;
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
*val = data->bw;
@@ -531,7 +589,7 @@ static int bma180_read_raw(struct iio_dev *indio_dev,
return -EINVAL;
}
case IIO_CHAN_INFO_OFFSET:
- *val = data->part_info->center_temp;
+ *val = data->part_info->temp_offset;
return IIO_VAL_INT;
default:
return -EINVAL;
@@ -609,6 +667,11 @@ static const struct iio_enum bma180_power_mode_enum = {
.set = bma180_set_power_mode,
};
+static const struct iio_chan_spec_ext_info bma023_ext_info[] = {
+ IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, bma180_accel_get_mount_matrix),
+ { }
+};
+
static const struct iio_chan_spec_ext_info bma180_ext_info[] = {
IIO_ENUM("power_mode", true, &bma180_power_mode_enum),
IIO_ENUM_AVAILABLE("power_mode", &bma180_power_mode_enum),
@@ -616,6 +679,35 @@ static const struct iio_chan_spec_ext_info bma180_ext_info[] = {
{ }
};
+#define BMA023_ACC_CHANNEL(_axis, _bits) { \
+ .type = IIO_ACCEL, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##_axis, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
+ .scan_index = AXIS_##_axis, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = _bits, \
+ .storagebits = 16, \
+ .shift = 16 - _bits, \
+ }, \
+ .ext_info = bma023_ext_info, \
+}
+
+#define BMA150_TEMP_CHANNEL { \
+ .type = IIO_TEMP, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET), \
+ .scan_index = TEMP, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 8, \
+ .storagebits = 16, \
+ }, \
+}
+
#define BMA180_ACC_CHANNEL(_axis, _bits) { \
.type = IIO_ACCEL, \
.modified = 1, \
@@ -645,6 +737,21 @@ static const struct iio_chan_spec_ext_info bma180_ext_info[] = {
}, \
}
+static const struct iio_chan_spec bma023_channels[] = {
+ BMA023_ACC_CHANNEL(X, 10),
+ BMA023_ACC_CHANNEL(Y, 10),
+ BMA023_ACC_CHANNEL(Z, 10),
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+};
+
+static const struct iio_chan_spec bma150_channels[] = {
+ BMA023_ACC_CHANNEL(X, 10),
+ BMA023_ACC_CHANNEL(Y, 10),
+ BMA023_ACC_CHANNEL(Z, 10),
+ BMA150_TEMP_CHANNEL,
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+};
+
static const struct iio_chan_spec bma180_channels[] = {
BMA180_ACC_CHANNEL(X, 14),
BMA180_ACC_CHANNEL(Y, 14),
@@ -670,6 +777,63 @@ static const struct iio_chan_spec bma254_channels[] = {
};
static const struct bma180_part_info bma180_part_info[] = {
+ [BMA023] = {
+ .chip_id = BMA023_ID_REG_VAL,
+ .channels = bma023_channels,
+ .num_channels = ARRAY_SIZE(bma023_channels),
+ .scale_table = bma023_scale_table,
+ .num_scales = ARRAY_SIZE(bma023_scale_table),
+ .bw_table = bma023_bw_table,
+ .num_bw = ARRAY_SIZE(bma023_bw_table),
+ /* No temperature channel */
+ .temp_offset = 0,
+ .int_reset_reg = BMA023_CTRL_REG0,
+ .int_reset_mask = BMA023_INT_RESET_MASK,
+ .sleep_reg = BMA023_CTRL_REG0,
+ .sleep_mask = BMA023_SLEEP,
+ .bw_reg = BMA023_CTRL_REG2,
+ .bw_mask = BMA023_BW_MASK,
+ .scale_reg = BMA023_CTRL_REG2,
+ .scale_mask = BMA023_RANGE_MASK,
+ /* No power mode on bma023 */
+ .power_reg = 0,
+ .power_mask = 0,
+ .lowpower_val = 0,
+ .int_enable_reg = BMA023_CTRL_REG3,
+ .int_enable_mask = BMA023_NEW_DATA_INT,
+ .softreset_reg = BMA023_CTRL_REG0,
+ .softreset_val = BMA023_RESET_VAL,
+ .chip_config = bma023_chip_config,
+ .chip_disable = bma023_chip_disable,
+ },
+ [BMA150] = {
+ .chip_id = BMA023_ID_REG_VAL,
+ .channels = bma150_channels,
+ .num_channels = ARRAY_SIZE(bma150_channels),
+ .scale_table = bma023_scale_table,
+ .num_scales = ARRAY_SIZE(bma023_scale_table),
+ .bw_table = bma023_bw_table,
+ .num_bw = ARRAY_SIZE(bma023_bw_table),
+ .temp_offset = -60, /* 0 LSB @ -30 degree C */
+ .int_reset_reg = BMA023_CTRL_REG0,
+ .int_reset_mask = BMA023_INT_RESET_MASK,
+ .sleep_reg = BMA023_CTRL_REG0,
+ .sleep_mask = BMA023_SLEEP,
+ .bw_reg = BMA023_CTRL_REG2,
+ .bw_mask = BMA023_BW_MASK,
+ .scale_reg = BMA023_CTRL_REG2,
+ .scale_mask = BMA023_RANGE_MASK,
+ /* No power mode on bma150 */
+ .power_reg = 0,
+ .power_mask = 0,
+ .lowpower_val = 0,
+ .int_enable_reg = BMA023_CTRL_REG3,
+ .int_enable_mask = BMA023_NEW_DATA_INT,
+ .softreset_reg = BMA023_CTRL_REG0,
+ .softreset_val = BMA023_RESET_VAL,
+ .chip_config = bma023_chip_config,
+ .chip_disable = bma023_chip_disable,
+ },
[BMA180] = {
.chip_id = BMA180_ID_REG_VAL,
.channels = bma180_channels,
@@ -678,7 +842,7 @@ static const struct bma180_part_info bma180_part_info[] = {
.num_scales = ARRAY_SIZE(bma180_scale_table),
.bw_table = bma180_bw_table,
.num_bw = ARRAY_SIZE(bma180_bw_table),
- .center_temp = 48, /* 0 LSB @ 24 degree C */
+ .temp_offset = 48, /* 0 LSB @ 24 degree C */
.int_reset_reg = BMA180_CTRL_REG0,
.int_reset_mask = BMA180_RESET_INT,
.sleep_reg = BMA180_CTRL_REG0,
@@ -693,6 +857,7 @@ static const struct bma180_part_info bma180_part_info[] = {
.int_enable_reg = BMA180_CTRL_REG3,
.int_enable_mask = BMA180_NEW_DATA_INT,
.softreset_reg = BMA180_RESET,
+ .softreset_val = BMA180_RESET_VAL,
.chip_config = bma180_chip_config,
.chip_disable = bma180_chip_disable,
},
@@ -704,7 +869,7 @@ static const struct bma180_part_info bma180_part_info[] = {
.num_scales = ARRAY_SIZE(bma25x_scale_table),
.bw_table = bma25x_bw_table,
.num_bw = ARRAY_SIZE(bma25x_bw_table),
- .center_temp = 48, /* 0 LSB @ 24 degree C */
+ .temp_offset = 48, /* 0 LSB @ 24 degree C */
.int_reset_reg = BMA250_INT_RESET_REG,
.int_reset_mask = BMA250_INT_RESET_MASK,
.sleep_reg = BMA250_POWER_REG,
@@ -721,6 +886,7 @@ static const struct bma180_part_info bma180_part_info[] = {
.int_map_reg = BMA250_INT_MAP_REG,
.int_enable_dataready_int1_mask = BMA250_INT1_DATA_MASK,
.softreset_reg = BMA250_RESET_REG,
+ .softreset_val = BMA180_RESET_VAL,
.chip_config = bma25x_chip_config,
.chip_disable = bma25x_chip_disable,
},
@@ -732,7 +898,7 @@ static const struct bma180_part_info bma180_part_info[] = {
.num_scales = ARRAY_SIZE(bma25x_scale_table),
.bw_table = bma25x_bw_table,
.num_bw = ARRAY_SIZE(bma25x_bw_table),
- .center_temp = 46, /* 0 LSB @ 23 degree C */
+ .temp_offset = 46, /* 0 LSB @ 23 degree C */
.int_reset_reg = BMA254_INT_RESET_REG,
.int_reset_mask = BMA254_INT_RESET_MASK,
.sleep_reg = BMA254_POWER_REG,
@@ -749,6 +915,7 @@ static const struct bma180_part_info bma180_part_info[] = {
.int_map_reg = BMA254_INT_MAP_REG,
.int_enable_dataready_int1_mask = BMA254_INT1_DATA_MASK,
.softreset_reg = BMA254_RESET_REG,
+ .softreset_val = BMA180_RESET_VAL,
.chip_config = bma25x_chip_config,
.chip_disable = bma25x_chip_disable,
},
@@ -871,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;
@@ -990,9 +1156,12 @@ static SIMPLE_DEV_PM_OPS(bma180_pm_ops, bma180_suspend, bma180_resume);
#endif
static const struct i2c_device_id bma180_ids[] = {
+ { "bma023", BMA023 },
+ { "bma150", BMA150 },
{ "bma180", BMA180 },
{ "bma250", BMA250 },
{ "bma254", BMA254 },
+ { "smb380", BMA150 },
{ }
};
@@ -1000,6 +1169,14 @@ MODULE_DEVICE_TABLE(i2c, bma180_ids);
static const struct of_device_id bma180_of_match[] = {
{
+ .compatible = "bosch,bma023",
+ .data = (void *)BMA023
+ },
+ {
+ .compatible = "bosch,bma150",
+ .data = (void *)BMA150
+ },
+ {
.compatible = "bosch,bma180",
.data = (void *)BMA180
},
@@ -1011,6 +1188,10 @@ static const struct of_device_id bma180_of_match[] = {
.compatible = "bosch,bma254",
.data = (void *)BMA254
},
+ {
+ .compatible = "bosch,smb380",
+ .data = (void *)BMA150
+ },
{ }
};
MODULE_DEVICE_TABLE(of, bma180_of_match);
@@ -1030,5 +1211,5 @@ module_i2c_driver(bma180_driver);
MODULE_AUTHOR("Kravchenko Oleksandr <x0199363@ti.com>");
MODULE_AUTHOR("Texas Instruments, Inc.");
-MODULE_DESCRIPTION("Bosch BMA180/BMA25x triaxial acceleration sensor");
+MODULE_DESCRIPTION("Bosch BMA023/BMA1x0/BMA25x triaxial acceleration sensor");
MODULE_LICENSE("GPL");
diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c
index cae905039cb6..da8b36cc8628 100644
--- a/drivers/iio/accel/bma220_spi.c
+++ b/drivers/iio/accel/bma220_spi.c
@@ -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;
@@ -309,12 +308,14 @@ static const struct spi_device_id bma220_spi_id[] = {
{}
};
+#ifdef CONFIG_ACPI
static const struct acpi_device_id bma220_acpi_id[] = {
{"BMA0220", 0},
{}
};
MODULE_DEVICE_TABLE(spi, bma220_spi_id);
+#endif
static struct spi_driver bma220_driver = {
.driver = {
diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
index cc77f89c048b..7eeba80e32cb 100644
--- a/drivers/iio/accel/bma400_core.c
+++ b/drivers/iio/accel/bma400_core.c
@@ -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
index 000000000000..7c2825904e08
--- /dev/null
+++ b/drivers/iio/accel/bma400_spi.c
@@ -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");
diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c
index 121b4e89f038..48435865fdaf 100644
--- a/drivers/iio/accel/bmc150-accel-core.c
+++ b/drivers/iio/accel/bmc150-accel-core.c
@@ -189,6 +189,14 @@ struct bmc150_accel_data {
struct mutex mutex;
u8 fifo_mode, watermark;
s16 buffer[8];
+ /*
+ * Ensure there is sufficient space and correct alignment for
+ * the timestamp if enabled
+ */
+ struct {
+ __le16 channels[3];
+ s64 ts __aligned(8);
+ } scan;
u8 bw_bits;
u32 slope_dur;
u32 slope_thres;
@@ -922,15 +930,16 @@ static int __bmc150_accel_fifo_flush(struct iio_dev *indio_dev,
* now.
*/
for (i = 0; i < count; i++) {
- u16 sample[8];
int j, bit;
j = 0;
for_each_set_bit(bit, indio_dev->active_scan_mask,
indio_dev->masklength)
- memcpy(&sample[j++], &buffer[i * 3 + bit], 2);
+ memcpy(&data->scan.channels[j++], &buffer[i * 3 + bit],
+ sizeof(data->scan.channels[0]));
- iio_push_to_buffers_with_timestamp(indio_dev, sample, tstamp);
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
+ tstamp);
tstamp += sample_period;
}
@@ -1411,7 +1420,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 +1452,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 +1583,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;
diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c b/drivers/iio/accel/cros_ec_accel_legacy.c
index 2532b9ad3384..b6f3471b62dc 100644
--- a/drivers/iio/accel/cros_ec_accel_legacy.c
+++ b/drivers/iio/accel/cros_ec_accel_legacy.c
@@ -33,6 +33,11 @@
*/
#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', \
diff --git a/drivers/iio/accel/da280.c b/drivers/iio/accel/da280.c
index 227bea2d738b..4472dde6899e 100644
--- a/drivers/iio/accel/da280.c
+++ b/drivers/iio/accel/da280.c
@@ -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;
diff --git a/drivers/iio/accel/da311.c b/drivers/iio/accel/da311.c
index c20979249a48..3b3df620ba27 100644
--- a/drivers/iio/accel/da311.c
+++ b/drivers/iio/accel/da311.c
@@ -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;
diff --git a/drivers/iio/accel/dmard06.c b/drivers/iio/accel/dmard06.c
index 2bf210fa4ba6..de2868c28d95 100644
--- a/drivers/iio/accel/dmard06.c
+++ b/drivers/iio/accel/dmard06.c
@@ -6,6 +6,7 @@
*/
#include <linux/module.h>
+#include <linux/mod_devicetable.h>
#include <linux/i2c.h>
#include <linux/iio/iio.h>
@@ -160,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;
@@ -226,7 +226,7 @@ static struct i2c_driver dmard06_driver = {
.id_table = dmard06_id,
.driver = {
.name = DMARD06_DRV_NAME,
- .of_match_table = of_match_ptr(dmard06_of_match),
+ .of_match_table = dmard06_of_match,
.pm = DMARD06_PM_OPS,
},
};
diff --git a/drivers/iio/accel/dmard09.c b/drivers/iio/accel/dmard09.c
index 2d666cd69b29..e6e28c964777 100644
--- a/drivers/iio/accel/dmard09.c
+++ b/drivers/iio/accel/dmard09.c
@@ -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;
diff --git a/drivers/iio/accel/dmard10.c b/drivers/iio/accel/dmard10.c
index 71c852b8bb3e..90206f015857 100644
--- a/drivers/iio/accel/dmard10.c
+++ b/drivers/iio/accel/dmard10.c
@@ -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;
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
index 0d9e2def2b25..4c5e594024f8 100644
--- a/drivers/iio/accel/hid-sensor-accel-3d.c
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -14,8 +14,6 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
-#include <linux/iio/trigger_consumer.h>
-#include <linux/iio/triggered_buffer.h>
#include "../common/hid-sensors/hid-sensor-trigger.h"
enum accel_3d_channel {
@@ -386,23 +384,17 @@ 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;
- ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
- NULL, NULL);
- if (ret) {
- dev_err(&pdev->dev, "failed to initialize trigger buffer\n");
- goto error_free_dev_mem;
- }
atomic_set(&accel_state->common_attributes.data_ready, 0);
+
ret = hid_sensor_setup_trigger(indio_dev, name,
&accel_state->common_attributes);
if (ret < 0) {
dev_err(&pdev->dev, "trigger setup failed\n");
- goto error_unreg_buffer_funcs;
+ goto error_free_dev_mem;
}
ret = iio_device_register(indio_dev);
@@ -426,9 +418,7 @@ static int hid_accel_3d_probe(struct platform_device *pdev)
error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
- hid_sensor_remove_trigger(&accel_state->common_attributes);
-error_unreg_buffer_funcs:
- iio_triggered_buffer_cleanup(indio_dev);
+ hid_sensor_remove_trigger(indio_dev, &accel_state->common_attributes);
error_free_dev_mem:
kfree(indio_dev->channels);
return ret;
@@ -443,8 +433,7 @@ static int hid_accel_3d_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, hsdev->usage);
iio_device_unregister(indio_dev);
- hid_sensor_remove_trigger(&accel_state->common_attributes);
- iio_triggered_buffer_cleanup(indio_dev);
+ hid_sensor_remove_trigger(indio_dev, &accel_state->common_attributes);
kfree(indio_dev->channels);
return 0;
diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c
index c9924a65c32a..beb38d9d607d 100644
--- a/drivers/iio/accel/kxcjk-1013.c
+++ b/drivers/iio/accel/kxcjk-1013.c
@@ -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;
diff --git a/drivers/iio/accel/kxsd9-i2c.c b/drivers/iio/accel/kxsd9-i2c.c
index 38411e1c155b..b580d605f848 100644
--- a/drivers/iio/accel/kxsd9-i2c.c
+++ b/drivers/iio/accel/kxsd9-i2c.c
@@ -2,6 +2,7 @@
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/mod_devicetable.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/delay.h>
@@ -21,8 +22,8 @@ static int kxsd9_i2c_probe(struct i2c_client *i2c,
regmap = devm_regmap_init_i2c(i2c, &config);
if (IS_ERR(regmap)) {
- dev_err(&i2c->dev, "Failed to register i2c regmap %d\n",
- (int)PTR_ERR(regmap));
+ dev_err(&i2c->dev, "Failed to register i2c regmap: %pe\n",
+ regmap);
return PTR_ERR(regmap);
}
@@ -36,15 +37,11 @@ static int kxsd9_i2c_remove(struct i2c_client *client)
return kxsd9_common_remove(&client->dev);
}
-#ifdef CONFIG_OF
static const struct of_device_id kxsd9_of_match[] = {
{ .compatible = "kionix,kxsd9", },
{ },
};
MODULE_DEVICE_TABLE(of, kxsd9_of_match);
-#else
-#define kxsd9_of_match NULL
-#endif
static const struct i2c_device_id kxsd9_i2c_id[] = {
{"kxsd9", 0},
@@ -55,7 +52,7 @@ MODULE_DEVICE_TABLE(i2c, kxsd9_i2c_id);
static struct i2c_driver kxsd9_i2c_driver = {
.driver = {
.name = "kxsd9",
- .of_match_table = of_match_ptr(kxsd9_of_match),
+ .of_match_table = kxsd9_of_match,
.pm = &kxsd9_dev_pm_ops,
},
.probe = kxsd9_i2c_probe,
diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c
index 0b876b2dc5bd..0e18b92e2099 100644
--- a/drivers/iio/accel/kxsd9.c
+++ b/drivers/iio/accel/kxsd9.c
@@ -209,14 +209,20 @@ static irqreturn_t kxsd9_trigger_handler(int irq, void *p)
const struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct kxsd9_state *st = iio_priv(indio_dev);
+ /*
+ * Ensure correct positioning and alignment of timestamp.
+ * No need to zero initialize as all elements written.
+ */
+ struct {
+ __be16 chan[4];
+ s64 ts __aligned(8);
+ } hw_values;
int ret;
- /* 4 * 16bit values AND timestamp */
- __be16 hw_values[8];
ret = regmap_bulk_read(st->map,
KXSD9_REG_X,
- &hw_values,
- 8);
+ hw_values.chan,
+ sizeof(hw_values.chan));
if (ret) {
dev_err(st->dev,
"error reading data\n");
@@ -224,7 +230,7 @@ static irqreturn_t kxsd9_trigger_handler(int irq, void *p)
}
iio_push_to_buffers_with_timestamp(indio_dev,
- hw_values,
+ &hw_values,
iio_get_time_ns(indio_dev));
iio_trigger_notify_done(indio_dev->trig);
@@ -252,8 +258,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 +415,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;
diff --git a/drivers/iio/accel/mc3230.c b/drivers/iio/accel/mc3230.c
index 02b3d25b3d96..46e4283fc037 100644
--- a/drivers/iio/accel/mc3230.c
+++ b/drivers/iio/accel/mc3230.c
@@ -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;
diff --git a/drivers/iio/accel/mma7455_core.c b/drivers/iio/accel/mma7455_core.c
index 8b5a6aff9bf4..922bd38ff6ea 100644
--- a/drivers/iio/accel/mma7455_core.c
+++ b/drivers/iio/accel/mma7455_core.c
@@ -52,6 +52,14 @@
struct mma7455_data {
struct regmap *regmap;
+ /*
+ * Used to reorganize data. Will ensure correct alignment of
+ * the timestamp if present
+ */
+ struct {
+ __le16 channels[3];
+ s64 ts __aligned(8);
+ } scan;
};
static int mma7455_drdy(struct mma7455_data *mma7455)
@@ -82,19 +90,19 @@ static irqreturn_t mma7455_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct mma7455_data *mma7455 = iio_priv(indio_dev);
- u8 buf[16]; /* 3 x 16-bit channels + padding + ts */
int ret;
ret = mma7455_drdy(mma7455);
if (ret)
goto done;
- ret = regmap_bulk_read(mma7455->regmap, MMA7455_REG_XOUTL, buf,
- sizeof(__le16) * 3);
+ ret = regmap_bulk_read(mma7455->regmap, MMA7455_REG_XOUTL,
+ mma7455->scan.channels,
+ sizeof(mma7455->scan.channels));
if (ret)
goto done;
- iio_push_to_buffers_with_timestamp(indio_dev, buf,
+ iio_push_to_buffers_with_timestamp(indio_dev, &mma7455->scan,
iio_get_time_ns(indio_dev));
done:
@@ -260,7 +268,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);
diff --git a/drivers/iio/accel/mma7660.c b/drivers/iio/accel/mma7660.c
index 7faf6d8657ae..b3c9136d51ec 100644
--- a/drivers/iio/accel/mma7660.c
+++ b/drivers/iio/accel/mma7660.c
@@ -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;
diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c
index 00e100fc845a..853febc29488 100644
--- a/drivers/iio/accel/mma8452.c
+++ b/drivers/iio/accel/mma8452.c
@@ -110,6 +110,12 @@ struct mma8452_data {
int sleep_val;
struct regulator *vdd_reg;
struct regulator *vddio_reg;
+
+ /* Ensure correct alignment of time stamp when present */
+ struct {
+ __be16 channels[3];
+ s64 ts __aligned(8);
+ } buffer;
};
/**
@@ -1091,14 +1097,13 @@ static irqreturn_t mma8452_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct mma8452_data *data = iio_priv(indio_dev);
- u8 buffer[16]; /* 3 16-bit channels + padding + ts */
int ret;
- ret = mma8452_read(data, (__be16 *)buffer);
+ ret = mma8452_read(data, data->buffer.channels);
if (ret < 0)
goto done;
- iio_push_to_buffers_with_timestamp(indio_dev, buffer,
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer,
iio_get_time_ns(indio_dev));
done:
@@ -1580,7 +1585,7 @@ static int mma8452_probe(struct i2c_client *client,
case FXLS8471_DEVICE_ID:
if (ret == data->chip_info->chip_id)
break;
- /* fall through */
+ fallthrough;
default:
ret = -ENODEV;
goto disable_regulators;
@@ -1592,7 +1597,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;
@@ -1685,10 +1689,13 @@ static int mma8452_probe(struct i2c_client *client,
ret = mma8452_set_freefall_mode(data, false);
if (ret < 0)
- goto buffer_cleanup;
+ goto unregister_device;
return 0;
+unregister_device:
+ iio_device_unregister(indio_dev);
+
buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);
diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c
index 99e4a21ca942..08a2303cc9df 100644
--- a/drivers/iio/accel/mma9551.c
+++ b/drivers/iio/accel/mma9551.c
@@ -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;
diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c
index 312070dcf035..c15908faa381 100644
--- a/drivers/iio/accel/mma9553.c
+++ b/drivers/iio/accel/mma9553.c
@@ -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;
diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c
index 3d5bea651923..f877263dc6ef 100644
--- a/drivers/iio/accel/mxc4005.c
+++ b/drivers/iio/accel/mxc4005.c
@@ -135,7 +135,7 @@ static int mxc4005_read_xyz(struct mxc4005_data *data)
int ret;
ret = regmap_bulk_read(data->regmap, MXC4005_REG_XOUT_UPPER,
- (u8 *) data->buffer, sizeof(data->buffer));
+ data->buffer, sizeof(data->buffer));
if (ret < 0) {
dev_err(data->dev, "failed to read axes\n");
return ret;
@@ -150,7 +150,7 @@ static int mxc4005_read_axis(struct mxc4005_data *data,
__be16 reg;
int ret;
- ret = regmap_bulk_read(data->regmap, addr, (u8 *) &reg, sizeof(reg));
+ ret = regmap_bulk_read(data->regmap, addr, &reg, sizeof(reg));
if (ret < 0) {
dev_err(data->dev, "failed to read reg %02x\n", addr);
return ret;
@@ -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);
diff --git a/drivers/iio/accel/mxc6255.c b/drivers/iio/accel/mxc6255.c
index f532f8643aa4..9aeeadc420d3 100644
--- a/drivers/iio/accel/mxc6255.c
+++ b/drivers/iio/accel/mxc6255.c
@@ -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;
diff --git a/drivers/iio/accel/sca3000.c b/drivers/iio/accel/sca3000.c
index 6e429072e44a..194738660523 100644
--- a/drivers/iio/accel/sca3000.c
+++ b/drivers/iio/accel/sca3000.c
@@ -186,9 +186,9 @@ struct sca3000_state {
* @option_mode_2_freq: option mode 2 sampling frequency
* @option_mode_2_3db_freq: 3db cutoff frequency of the low pass filter for
* the second option mode.
- * @mod_det_mult_xz: Bit wise multipliers to calculate the threshold
+ * @mot_det_mult_xz: Bit wise multipliers to calculate the threshold
* for motion detection in the x and z axis.
- * @mod_det_mult_y: Bit wise multipliers to calculate the threshold
+ * @mot_det_mult_y: Bit wise multipliers to calculate the threshold
* for motion detection in the y axis.
*
* This structure is used to hold information about the functionality of a given
@@ -859,9 +859,9 @@ error_ret:
*/
static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(sca3000_read_av_freq);
-/**
+/*
* sca3000_read_event_value() - query of a threshold or period
- **/
+ */
static int sca3000_read_event_value(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
@@ -1100,9 +1100,9 @@ done:
return IRQ_HANDLED;
}
-/**
+/*
* sca3000_read_event_config() what events are enabled
- **/
+ */
static int sca3000_read_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
@@ -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) {
diff --git a/drivers/iio/accel/ssp_accel_sensor.c b/drivers/iio/accel/ssp_accel_sensor.c
index c32647abce20..474477e91b5e 100644
--- a/drivers/iio/accel/ssp_accel_sensor.c
+++ b/drivers/iio/accel/ssp_accel_sensor.c
@@ -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;
diff --git a/drivers/iio/accel/st_accel.h b/drivers/iio/accel/st_accel.h
index 5b13e293cade..5d356288e001 100644
--- a/drivers/iio/accel/st_accel.h
+++ b/drivers/iio/accel/st_accel.h
@@ -35,6 +35,7 @@ enum st_accel_type {
LIS2DW12,
LIS3DHH,
LIS2DE12,
+ LIS2HH12,
ST_ACCEL_MAX,
};
@@ -59,6 +60,7 @@ enum st_accel_type {
#define LIS3DHH_ACCEL_DEV_NAME "lis3dhh"
#define LIS3DE_ACCEL_DEV_NAME "lis3de"
#define LIS2DE12_ACCEL_DEV_NAME "lis2de12"
+#define LIS2HH12_ACCEL_DEV_NAME "lis2hh12"
/**
* struct st_sensors_platform_data - default accel platform data
diff --git a/drivers/iio/accel/st_accel_buffer.c b/drivers/iio/accel/st_accel_buffer.c
index 9f2b40474b8e..492263589e04 100644
--- a/drivers/iio/accel/st_accel_buffer.c
+++ b/drivers/iio/accel/st_accel_buffer.c
@@ -33,15 +33,10 @@ static int st_accel_buffer_postenable(struct iio_dev *indio_dev)
{
int err;
- err = iio_triggered_buffer_postenable(indio_dev);
+ err = st_sensors_set_axis_enable(indio_dev, indio_dev->active_scan_mask[0]);
if (err < 0)
return err;
- err = st_sensors_set_axis_enable(indio_dev,
- (u8)indio_dev->active_scan_mask[0]);
- if (err < 0)
- goto st_accel_buffer_predisable;
-
err = st_sensors_set_enable(indio_dev, true);
if (err < 0)
goto st_accel_buffer_enable_all_axis;
@@ -50,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 = {
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
index 7320275c7e56..43c50167d220 100644
--- a/drivers/iio/accel/st_accel_core.c
+++ b/drivers/iio/accel/st_accel_core.c
@@ -904,6 +904,83 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
.multi_read_bit = true,
.bootime = 2,
},
+ {
+ .wai = 0x41,
+ .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
+ .sensors_supported = {
+ [0] = LIS2HH12_ACCEL_DEV_NAME,
+ },
+ .ch = (struct iio_chan_spec *)st_accel_16bit_channels,
+ .odr = {
+ .addr = 0x20,
+ .mask = 0x70,
+ .odr_avl = {
+ { .hz = 10, .value = 0x01, },
+ { .hz = 50, .value = 0x02, },
+ { .hz = 100, .value = 0x03, },
+ { .hz = 200, .value = 0x04, },
+ { .hz = 400, .value = 0x05, },
+ { .hz = 800, .value = 0x06, },
+ },
+ },
+ .pw = {
+ .addr = 0x20,
+ .mask = 0x70,
+ .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
+ },
+ .enable_axis = {
+ .addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
+ .mask = ST_SENSORS_DEFAULT_AXIS_MASK,
+ },
+ .fs = {
+ .addr = 0x23,
+ .mask = 0x30,
+ .fs_avl = {
+ [0] = {
+ .num = ST_ACCEL_FS_AVL_2G,
+ .value = 0x00,
+ .gain = IIO_G_TO_M_S_2(61),
+ },
+ [1] = {
+ .num = ST_ACCEL_FS_AVL_4G,
+ .value = 0x02,
+ .gain = IIO_G_TO_M_S_2(122),
+ },
+ [2] = {
+ .num = ST_ACCEL_FS_AVL_8G,
+ .value = 0x03,
+ .gain = IIO_G_TO_M_S_2(244),
+ },
+ },
+ },
+ .bdu = {
+ .addr = 0x20,
+ .mask = 0x08,
+ },
+ .drdy_irq = {
+ .int1 = {
+ .addr = 0x22,
+ .mask = 0x01,
+ },
+ .int2 = {
+ .addr = 0x25,
+ .mask = 0x01,
+ },
+ .addr_ihl = 0x24,
+ .mask_ihl = 0x02,
+ .stat_drdy = {
+ .addr = ST_SENSORS_DEFAULT_STAT_ADDR,
+ .mask = 0x07,
+ },
+ },
+ .sim = {
+ .addr = 0x23,
+ .value = BIT(0),
+ },
+ .multi_read_bit = true,
+ .bootime = 2,
+ },
+
};
static int st_accel_read_raw(struct iio_dev *indio_dev,
@@ -1170,8 +1247,7 @@ EXPORT_SYMBOL(st_accel_get_settings);
int st_accel_common_probe(struct iio_dev *indio_dev)
{
struct st_sensor_data *adata = iio_priv(indio_dev);
- struct st_sensors_platform_data *pdata =
- (struct st_sensors_platform_data *)adata->dev->platform_data;
+ struct st_sensors_platform_data *pdata = dev_get_platdata(adata->dev);
struct iio_chan_spec *channels;
size_t channels_size;
int err;
@@ -1204,8 +1280,7 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
"failed to apply ACPI orientation data: %d\n", err);
indio_dev->channels = channels;
- adata->current_fullscale = (struct st_sensor_fullscale_avl *)
- &adata->sensor_settings->fs.fs_avl[0];
+ adata->current_fullscale = &adata->sensor_settings->fs.fs_avl[0];
adata->odr = adata->sensor_settings->odr.odr_avl[0].hz;
if (!pdata)
diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c
index 6b283be26ebc..360e16f2cadb 100644
--- a/drivers/iio/accel/st_accel_i2c.c
+++ b/drivers/iio/accel/st_accel_i2c.c
@@ -104,6 +104,10 @@ static const struct of_device_id st_accel_of_match[] = {
.compatible = "st,lis2de12",
.data = LIS2DE12_ACCEL_DEV_NAME,
},
+ {
+ .compatible = "st,lis2hh12",
+ .data = LIS2HH12_ACCEL_DEV_NAME,
+ },
{},
};
MODULE_DEVICE_TABLE(of, st_accel_of_match);
@@ -138,6 +142,7 @@ static const struct i2c_device_id st_accel_id_table[] = {
{ LIS2DW12_ACCEL_DEV_NAME },
{ LIS3DE_ACCEL_DEV_NAME },
{ LIS2DE12_ACCEL_DEV_NAME },
+ { LIS2HH12_ACCEL_DEV_NAME },
{},
};
MODULE_DEVICE_TABLE(i2c, st_accel_id_table);
diff --git a/drivers/iio/accel/stk8312.c b/drivers/iio/accel/stk8312.c
index 58c160ccdee7..3b59887a8581 100644
--- a/drivers/iio/accel/stk8312.c
+++ b/drivers/iio/accel/stk8312.c
@@ -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;
diff --git a/drivers/iio/accel/stk8ba50.c b/drivers/iio/accel/stk8ba50.c
index c70ddec29eb4..3ead378b02c9 100644
--- a/drivers/iio/accel/stk8ba50.c
+++ b/drivers/iio/accel/stk8ba50.c
@@ -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;
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 12bb8b7ca1ff..d94dc800b842 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -246,6 +246,41 @@ config AD799X
To compile this driver as a module, choose M here: the module will be
called ad799x.
+config AD9467
+ tristate "Analog Devices AD9467 High Speed ADC driver"
+ depends on SPI
+ select ADI_AXI_ADC
+ help
+ Say yes here to build support for Analog Devices:
+ * AD9467 16-Bit, 200 MSPS/250 MSPS Analog-to-Digital Converter
+
+ The driver requires the assistance of the AXI ADC IP core to operate,
+ since SPI is used for configuration only, while data has to be
+ streamed into memory via DMA.
+
+ To compile this driver as a module, choose M here: the module will be
+ called ad9467.
+
+config ADI_AXI_ADC
+ tristate "Analog Devices Generic AXI ADC IP core driver"
+ select IIO_BUFFER
+ select IIO_BUFFER_HW_CONSUMER
+ select IIO_BUFFER_DMAENGINE
+ help
+ Say yes here to build support for Analog Devices Generic
+ AXI ADC IP core. The IP core is used for interfacing with
+ analog-to-digital (ADC) converters that require either a high-speed
+ serial interface (JESD204B/C) or a source synchronous parallel
+ interface (LVDS/CMOS).
+ Typically (for such devices) SPI will be used for configuration only,
+ while this IP core handles the streaming of data into memory via DMA.
+
+ Link: https://wiki.analog.com/resources/fpga/docs/axi_adc_ip
+ If unsure, say N (but it's safe to say "Y").
+
+ To compile this driver as a module, choose M here: the
+ module will be called adi-axi-adc.
+
config ASPEED_ADC
tristate "Aspeed ADC"
depends on ARCH_ASPEED || COMPILE_TEST
@@ -259,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
@@ -465,6 +500,7 @@ config INA2XX_ADC
config INGENIC_ADC
tristate "Ingenic JZ47xx SoCs ADC driver"
depends on MIPS || COMPILE_TEST
+ select IIO_BUFFER
help
Say yes here to build support for the Ingenic JZ47xx SoCs ADC unit.
@@ -595,6 +631,16 @@ config MAX1118
To compile this driver as a module, choose M here: the module will be
called max1118.
+config MAX1241
+ tristate "Maxim max1241 ADC driver"
+ depends on SPI_MASTER
+ help
+ Say yes here to build support for Maxim max1241 12-bit, single-channel
+ ADC.
+
+ To compile this driver as a module, choose M here: the module will be
+ called max1241.
+
config MAX1363
tristate "Maxim max1363 ADC driver"
depends on I2C
@@ -692,6 +738,16 @@ config MESON_SARADC
To compile this driver as a module, choose M here: the
module will be called meson_saradc.
+config MP2629_ADC
+ tristate "Monolithic MP2629 ADC driver"
+ depends on MFD_MP2629
+ help
+ Say yes to have support for battery charger IC MP2629 ADC device
+ accessed over I2C.
+
+ This driver provides ADC conversion of system, input power supply
+ and battery voltage & current information.
+
config NAU7802
tristate "Nuvoton NAU7802 ADC driver"
depends on I2C
@@ -809,6 +865,8 @@ config ROCKCHIP_SARADC
tristate "Rockchip SARADC driver"
depends on ARCH_ROCKCHIP || (ARM && COMPILE_TEST)
depends on RESET_CONTROLLER
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
help
Say yes here to build support for the SARADC found in SoCs from
Rockchip.
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 637807861112..90f94ada7b30 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -26,6 +26,8 @@ obj-$(CONFIG_AD7793) += ad7793.o
obj-$(CONFIG_AD7887) += ad7887.o
obj-$(CONFIG_AD7949) += ad7949.o
obj-$(CONFIG_AD799X) += ad799x.o
+obj-$(CONFIG_AD9467) += ad9467.o
+obj-$(CONFIG_ADI_AXI_ADC) += adi-axi-adc.o
obj-$(CONFIG_ASPEED_ADC) += aspeed_adc.o
obj-$(CONFIG_AT91_ADC) += at91_adc.o
obj-$(CONFIG_AT91_SAMA5D2_ADC) += at91-sama5d2_adc.o
@@ -57,6 +59,7 @@ obj-$(CONFIG_LTC2497) += ltc2497.o ltc2497-core.o
obj-$(CONFIG_MAX1027) += max1027.o
obj-$(CONFIG_MAX11100) += max11100.o
obj-$(CONFIG_MAX1118) += max1118.o
+obj-$(CONFIG_MAX1241) += max1241.o
obj-$(CONFIG_MAX1363) += max1363.o
obj-$(CONFIG_MAX9611) += max9611.o
obj-$(CONFIG_MCP320X) += mcp320x.o
@@ -65,6 +68,7 @@ obj-$(CONFIG_MCP3911) += mcp3911.o
obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o
obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
obj-$(CONFIG_MESON_SARADC) += meson_saradc.o
+obj-$(CONFIG_MP2629_ADC) += mp2629_adc.o
obj-$(CONFIG_MXS_LRADC_ADC) += mxs-lradc-adc.o
obj-$(CONFIG_NAU7802) += nau7802.o
obj-$(CONFIG_NPCM_ADC) += npcm_adc.o
diff --git a/drivers/iio/adc/ab8500-gpadc.c b/drivers/iio/adc/ab8500-gpadc.c
index fd5b18d7f0c2..1bb987a4acba 100644
--- a/drivers/iio/adc/ab8500-gpadc.c
+++ b/drivers/iio/adc/ab8500-gpadc.c
@@ -484,7 +484,7 @@ static int ab8500_gpadc_read(struct ab8500_gpadc *gpadc,
delay_max = 10000; /* large range optimises sleepmode */
break;
}
- /* Fall through */
+ fallthrough;
default:
ctrl1 |= AB8500_GPADC_CTRL1_BUF_ENA;
break;
@@ -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;
diff --git a/drivers/iio/adc/ad7091r-base.c b/drivers/iio/adc/ad7091r-base.c
index 33c40357bd5e..63b4d6ea4566 100644
--- a/drivers/iio/adc/ad7091r-base.c
+++ b/drivers/iio/adc/ad7091r-base.c
@@ -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;
diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c
index a3c0647a5391..766c73333604 100644
--- a/drivers/iio/adc/ad7124.c
+++ b/drivers/iio/adc/ad7124.c
@@ -12,6 +12,7 @@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/of_device.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
@@ -47,6 +48,15 @@
#define AD7124_ADC_CTRL_MODE_MSK GENMASK(5, 2)
#define AD7124_ADC_CTRL_MODE(x) FIELD_PREP(AD7124_ADC_CTRL_MODE_MSK, x)
+/* AD7124 ID */
+#define AD7124_DEVICE_ID_MSK GENMASK(7, 4)
+#define AD7124_DEVICE_ID_GET(x) FIELD_GET(AD7124_DEVICE_ID_MSK, x)
+#define AD7124_SILICON_REV_MSK GENMASK(3, 0)
+#define AD7124_SILICON_REV_GET(x) FIELD_GET(AD7124_SILICON_REV_MSK, x)
+
+#define CHIPID_AD7124_4 0x0
+#define CHIPID_AD7124_8 0x1
+
/* AD7124_CHANNEL_X */
#define AD7124_CHANNEL_EN_MSK BIT(15)
#define AD7124_CHANNEL_EN(x) FIELD_PREP(AD7124_CHANNEL_EN_MSK, x)
@@ -120,6 +130,8 @@ static const char * const ad7124_ref_names[] = {
};
struct ad7124_chip_info {
+ const char *name;
+ unsigned int chip_id;
unsigned int num_inputs;
};
@@ -165,9 +177,13 @@ static const struct iio_chan_spec ad7124_channel_template = {
static struct ad7124_chip_info ad7124_chip_info_tbl[] = {
[ID_AD7124_4] = {
+ .name = "ad7124-4",
+ .chip_id = CHIPID_AD7124_4,
.num_inputs = 8,
},
[ID_AD7124_8] = {
+ .name = "ad7124-8",
+ .chip_id = CHIPID_AD7124_8,
.num_inputs = 16,
},
};
@@ -503,6 +519,34 @@ static int ad7124_soft_reset(struct ad7124_state *st)
return -EIO;
}
+static int ad7124_check_chip_id(struct ad7124_state *st)
+{
+ unsigned int readval, chip_id, silicon_rev;
+ int ret;
+
+ ret = ad_sd_read_reg(&st->sd, AD7124_ID, 1, &readval);
+ if (ret < 0)
+ return ret;
+
+ chip_id = AD7124_DEVICE_ID_GET(readval);
+ silicon_rev = AD7124_SILICON_REV_GET(readval);
+
+ if (chip_id != st->chip_info->chip_id) {
+ dev_err(&st->sd.spi->dev,
+ "Chip ID mismatch: expected %u, got %u\n",
+ st->chip_info->chip_id, chip_id);
+ return -ENODEV;
+ }
+
+ if (silicon_rev == 0) {
+ dev_err(&st->sd.spi->dev,
+ "Silicon revision empty. Chip may not be present\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
static int ad7124_init_channel_vref(struct ad7124_state *st,
unsigned int channel_number)
{
@@ -665,26 +709,28 @@ static int ad7124_setup(struct ad7124_state *st)
static int ad7124_probe(struct spi_device *spi)
{
- const struct spi_device_id *id;
+ const struct ad7124_chip_info *info;
struct ad7124_state *st;
struct iio_dev *indio_dev;
int i, ret;
+ info = of_device_get_match_data(&spi->dev);
+ if (!info)
+ return -ENODEV;
+
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
- id = spi_get_device_id(spi);
- st->chip_info = &ad7124_chip_info_tbl[id->driver_data];
+ st->chip_info = info;
ad_sd_init(&st->sd, indio_dev, spi, &ad7124_sigma_delta_info);
spi_set_drvdata(spi, indio_dev);
- indio_dev->dev.parent = &spi->dev;
- indio_dev->name = spi_get_device_id(spi)->name;
+ indio_dev->name = st->chip_info->name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &ad7124_info;
@@ -722,6 +768,10 @@ static int ad7124_probe(struct spi_device *spi)
if (ret < 0)
goto error_clk_disable_unprepare;
+ ret = ad7124_check_chip_id(st);
+ if (ret)
+ goto error_clk_disable_unprepare;
+
ret = ad7124_setup(st);
if (ret < 0)
goto error_clk_disable_unprepare;
@@ -769,16 +819,11 @@ static int ad7124_remove(struct spi_device *spi)
return 0;
}
-static const struct spi_device_id ad7124_id_table[] = {
- { "ad7124-4", ID_AD7124_4 },
- { "ad7124-8", ID_AD7124_8 },
- {}
-};
-MODULE_DEVICE_TABLE(spi, ad7124_id_table);
-
static const struct of_device_id ad7124_of_match[] = {
- { .compatible = "adi,ad7124-4" },
- { .compatible = "adi,ad7124-8" },
+ { .compatible = "adi,ad7124-4",
+ .data = &ad7124_chip_info_tbl[ID_AD7124_4], },
+ { .compatible = "adi,ad7124-8",
+ .data = &ad7124_chip_info_tbl[ID_AD7124_8], },
{ },
};
MODULE_DEVICE_TABLE(of, ad7124_of_match);
@@ -790,7 +835,6 @@ static struct spi_driver ad71124_driver = {
},
.probe = ad7124_probe,
.remove = ad7124_remove,
- .id_table = ad7124_id_table,
};
module_spi_driver(ad71124_driver);
diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c
index 08ba1a8f05eb..2ed580521d81 100644
--- a/drivers/iio/adc/ad7192.c
+++ b/drivers/iio/adc/ad7192.c
@@ -908,15 +908,6 @@ static int ad7192_channels_config(struct iio_dev *indio_dev)
return 0;
}
-static const struct of_device_id ad7192_of_match[] = {
- { .compatible = "adi,ad7190", .data = &ad7192_chip_info_tbl[ID_AD7190] },
- { .compatible = "adi,ad7192", .data = &ad7192_chip_info_tbl[ID_AD7192] },
- { .compatible = "adi,ad7193", .data = &ad7192_chip_info_tbl[ID_AD7193] },
- { .compatible = "adi,ad7195", .data = &ad7192_chip_info_tbl[ID_AD7195] },
- {}
-};
-MODULE_DEVICE_TABLE(of, ad7192_of_match);
-
static int ad7192_probe(struct spi_device *spi)
{
struct ad7192_state *st;
@@ -970,7 +961,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;
@@ -1050,6 +1040,15 @@ static int ad7192_remove(struct spi_device *spi)
return 0;
}
+static const struct of_device_id ad7192_of_match[] = {
+ { .compatible = "adi,ad7190", .data = &ad7192_chip_info_tbl[ID_AD7190] },
+ { .compatible = "adi,ad7192", .data = &ad7192_chip_info_tbl[ID_AD7192] },
+ { .compatible = "adi,ad7193", .data = &ad7192_chip_info_tbl[ID_AD7193] },
+ { .compatible = "adi,ad7195", .data = &ad7192_chip_info_tbl[ID_AD7195] },
+ {}
+};
+MODULE_DEVICE_TABLE(of, ad7192_of_match);
+
static struct spi_driver ad7192_driver = {
.driver = {
.name = "ad7192",
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c
index c8524f098883..a8ec3efd659e 100644
--- a/drivers/iio/adc/ad7266.c
+++ b/drivers/iio/adc/ad7266.c
@@ -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;
diff --git a/drivers/iio/adc/ad7291.c b/drivers/iio/adc/ad7291.c
index b2b137fed246..62fde2aad282 100644
--- a/drivers/iio/adc/ad7291.c
+++ b/drivers/iio/adc/ad7291.c
@@ -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;
diff --git a/drivers/iio/adc/ad7292.c b/drivers/iio/adc/ad7292.c
index 6595fd196288..2eafbe7ac7c7 100644
--- a/drivers/iio/adc/ad7292.c
+++ b/drivers/iio/adc/ad7292.c
@@ -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;
diff --git a/drivers/iio/adc/ad7298.c b/drivers/iio/adc/ad7298.c
index dc8d8c5f6ad3..48d43cb0f932 100644
--- a/drivers/iio/adc/ad7298.c
+++ b/drivers/iio/adc/ad7298.c
@@ -98,9 +98,9 @@ static const struct iio_chan_spec ad7298_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(8),
};
-/**
+/*
* ad7298_update_scan_mode() setup the spi transfer buffer for the new scan mask
- **/
+ */
static int ad7298_update_scan_mode(struct iio_dev *indio_dev,
const unsigned long *active_scan_mask)
{
@@ -144,12 +144,12 @@ static int ad7298_update_scan_mode(struct iio_dev *indio_dev,
return 0;
}
-/**
+/*
* ad7298_trigger_handler() bh of trigger launched polling to ring buffer
*
* Currently there is no option in this driver to disable the saving of
* timestamps within the ring.
- **/
+ */
static irqreturn_t ad7298_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
@@ -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);
diff --git a/drivers/iio/adc/ad7476.c b/drivers/iio/adc/ad7476.c
index 76747488044b..66c55ae67791 100644
--- a/drivers/iio/adc/ad7476.c
+++ b/drivers/iio/adc/ad7476.c
@@ -12,9 +12,11 @@
#include <linux/sysfs.h>
#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
+#include <linux/gpio/consumer.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/bitops.h>
+#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -27,6 +29,8 @@ struct ad7476_state;
struct ad7476_chip_info {
unsigned int int_vref_uv;
struct iio_chan_spec channel[2];
+ /* channels used when convst gpio is defined */
+ struct iio_chan_spec convst_channel[2];
void (*reset)(struct ad7476_state *);
};
@@ -34,6 +38,7 @@ struct ad7476_state {
struct spi_device *spi;
const struct ad7476_chip_info *chip_info;
struct regulator *reg;
+ struct gpio_desc *convst_gpio;
struct spi_transfer xfer;
struct spi_message msg;
/*
@@ -64,6 +69,17 @@ enum ad7476_supported_device_ids {
ID_ADS7868,
};
+static void ad7091_convst(struct ad7476_state *st)
+{
+ if (!st->convst_gpio)
+ return;
+
+ gpiod_set_value(st->convst_gpio, 0);
+ udelay(1); /* CONVST pulse width: 10 ns min */
+ gpiod_set_value(st->convst_gpio, 1);
+ udelay(1); /* Conversion time: 650 ns max */
+}
+
static irqreturn_t ad7476_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
@@ -71,6 +87,8 @@ static irqreturn_t ad7476_trigger_handler(int irq, void *p)
struct ad7476_state *st = iio_priv(indio_dev);
int b_sent;
+ ad7091_convst(st);
+
b_sent = spi_sync(st->spi, &st->msg);
if (b_sent < 0)
goto done;
@@ -93,6 +111,8 @@ static int ad7476_scan_direct(struct ad7476_state *st)
{
int ret;
+ ad7091_convst(st);
+
ret = spi_sync(st->spi, &st->msg);
if (ret)
return ret;
@@ -160,6 +180,8 @@ static int ad7476_read_raw(struct iio_dev *indio_dev,
#define AD7940_CHAN(bits) _AD7476_CHAN((bits), 15 - (bits), \
BIT(IIO_CHAN_INFO_RAW))
#define AD7091R_CHAN(bits) _AD7476_CHAN((bits), 16 - (bits), 0)
+#define AD7091R_CONVST_CHAN(bits) _AD7476_CHAN((bits), 16 - (bits), \
+ BIT(IIO_CHAN_INFO_RAW))
#define ADS786X_CHAN(bits) _AD7476_CHAN((bits), 12 - (bits), \
BIT(IIO_CHAN_INFO_RAW))
@@ -167,6 +189,8 @@ static const struct ad7476_chip_info ad7476_chip_info_tbl[] = {
[ID_AD7091R] = {
.channel[0] = AD7091R_CHAN(12),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
+ .convst_channel[0] = AD7091R_CONVST_CHAN(12),
+ .convst_channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
.reset = ad7091_reset,
},
[ID_AD7276] = {
@@ -232,6 +256,13 @@ static const struct iio_info ad7476_info = {
.read_raw = &ad7476_read_raw,
};
+static void ad7476_reg_disable(void *data)
+{
+ struct ad7476_state *st = data;
+
+ regulator_disable(st->reg);
+}
+
static int ad7476_probe(struct spi_device *spi)
{
struct ad7476_state *st;
@@ -254,18 +285,29 @@ static int ad7476_probe(struct spi_device *spi)
if (ret)
return ret;
+ ret = devm_add_action_or_reset(&spi->dev, ad7476_reg_disable,
+ st);
+ if (ret)
+ return ret;
+
+ st->convst_gpio = devm_gpiod_get_optional(&spi->dev,
+ "adi,conversion-start",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(st->convst_gpio))
+ return PTR_ERR(st->convst_gpio);
+
spi_set_drvdata(spi, indio_dev);
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;
indio_dev->num_channels = 2;
indio_dev->info = &ad7476_info;
+
+ if (st->convst_gpio)
+ indio_dev->channels = st->chip_info->convst_channel;
/* Setup default message */
st->xfer.rx_buf = &st->data;
@@ -295,19 +337,8 @@ error_disable_reg:
return ret;
}
-static int ad7476_remove(struct spi_device *spi)
-{
- struct iio_dev *indio_dev = spi_get_drvdata(spi);
- struct ad7476_state *st = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
- iio_triggered_buffer_cleanup(indio_dev);
- regulator_disable(st->reg);
-
- return 0;
-}
-
static const struct spi_device_id ad7476_id[] = {
+ {"ad7091", ID_AD7091R},
{"ad7091r", ID_AD7091R},
{"ad7273", ID_AD7277},
{"ad7274", ID_AD7276},
@@ -343,7 +374,6 @@ static struct spi_driver ad7476_driver = {
.name = "ad7476",
},
.probe = ad7476_probe,
- .remove = ad7476_remove,
.id_table = ad7476_id,
};
module_spi_driver(ad7476_driver);
diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c
index e4683a68522a..ee7b108688b3 100644
--- a/drivers/iio/adc/ad7606.c
+++ b/drivers/iio/adc/ad7606.c
@@ -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;
diff --git a/drivers/iio/adc/ad7766.c b/drivers/iio/adc/ad7766.c
index bc388ea41754..b6b6765be7b4 100644
--- a/drivers/iio/adc/ad7766.c
+++ b/drivers/iio/adc/ad7766.c
@@ -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;
diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c
index 0d132708c429..0e93b0766eb4 100644
--- a/drivers/iio/adc/ad7768-1.c
+++ b/drivers/iio/adc/ad7768-1.c
@@ -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;
diff --git a/drivers/iio/adc/ad7780.c b/drivers/iio/adc/ad7780.c
index 291c1a898129..42e7e8e595d1 100644
--- a/drivers/iio/adc/ad7780.c
+++ b/drivers/iio/adc/ad7780.c
@@ -206,10 +206,29 @@ static const struct ad_sigma_delta_info ad7780_sigma_delta_info = {
.irq_flags = IRQF_TRIGGER_LOW,
};
-#define AD7780_CHANNEL(bits, wordsize) \
- AD_SD_CHANNEL(1, 0, 0, bits, 32, (wordsize) - (bits))
-#define AD7170_CHANNEL(bits, wordsize) \
- AD_SD_CHANNEL_NO_SAMP_FREQ(1, 0, 0, bits, 32, (wordsize) - (bits))
+#define _AD7780_CHANNEL(_bits, _wordsize, _mask_all) \
+{ \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = 0, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_OFFSET), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = _mask_all, \
+ .scan_index = 1, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = (_bits), \
+ .storagebits = 32, \
+ .shift = (_wordsize) - (_bits), \
+ .endianness = IIO_BE, \
+ }, \
+}
+
+#define AD7780_CHANNEL(_bits, _wordsize) \
+ _AD7780_CHANNEL(_bits, _wordsize, BIT(IIO_CHAN_INFO_SAMP_FREQ))
+#define AD7170_CHANNEL(_bits, _wordsize) \
+ _AD7780_CHANNEL(_bits, _wordsize, 0)
static const struct ad7780_chip_info ad7780_chip_info_tbl[] = {
[ID_AD7170] = {
@@ -301,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;
@@ -310,7 +328,7 @@ static int ad7780_probe(struct spi_device *spi)
ret = ad7780_init_gpios(&spi->dev, st);
if (ret)
- goto error_cleanup_buffer_and_trigger;
+ return ret;
st->reg = devm_regulator_get(&spi->dev, "avdd");
if (IS_ERR(st->reg))
diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c
index abb239392631..d57ad966e17c 100644
--- a/drivers/iio/adc/ad7791.c
+++ b/drivers/iio/adc/ad7791.c
@@ -64,25 +64,73 @@
#define AD7791_MODE_SEL_MASK (0x3 << 6)
#define AD7791_MODE_SEL(x) ((x) << 6)
+#define __AD7991_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
+ _storagebits, _shift, _extend_name, _type, _mask_all) \
+ { \
+ .type = (_type), \
+ .differential = (_channel2 == -1 ? 0 : 1), \
+ .indexed = 1, \
+ .channel = (_channel1), \
+ .channel2 = (_channel2), \
+ .address = (_address), \
+ .extend_name = (_extend_name), \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_OFFSET), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = _mask_all, \
+ .scan_index = (_si), \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = (_bits), \
+ .storagebits = (_storagebits), \
+ .shift = (_shift), \
+ .endianness = IIO_BE, \
+ }, \
+ }
+
+#define AD7991_SHORTED_CHANNEL(_si, _channel, _address, _bits, \
+ _storagebits, _shift) \
+ __AD7991_CHANNEL(_si, _channel, _channel, _address, _bits, \
+ _storagebits, _shift, "shorted", IIO_VOLTAGE, \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ))
+
+#define AD7991_CHANNEL(_si, _channel, _address, _bits, \
+ _storagebits, _shift) \
+ __AD7991_CHANNEL(_si, _channel, -1, _address, _bits, \
+ _storagebits, _shift, NULL, IIO_VOLTAGE, \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ))
+
+#define AD7991_DIFF_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
+ _storagebits, _shift) \
+ __AD7991_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
+ _storagebits, _shift, NULL, IIO_VOLTAGE, \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ))
+
+#define AD7991_SUPPLY_CHANNEL(_si, _channel, _address, _bits, _storagebits, \
+ _shift) \
+ __AD7991_CHANNEL(_si, _channel, -1, _address, _bits, \
+ _storagebits, _shift, "supply", IIO_VOLTAGE, \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ))
+
#define DECLARE_AD7787_CHANNELS(name, bits, storagebits) \
const struct iio_chan_spec name[] = { \
- AD_SD_DIFF_CHANNEL(0, 0, 0, AD7791_CH_AIN1P_AIN1N, \
+ AD7991_DIFF_CHANNEL(0, 0, 0, AD7791_CH_AIN1P_AIN1N, \
(bits), (storagebits), 0), \
- AD_SD_CHANNEL(1, 1, AD7791_CH_AIN2, (bits), (storagebits), 0), \
- AD_SD_SHORTED_CHANNEL(2, 0, AD7791_CH_AIN1N_AIN1N, \
+ AD7991_CHANNEL(1, 1, AD7791_CH_AIN2, (bits), (storagebits), 0), \
+ AD7991_SHORTED_CHANNEL(2, 0, AD7791_CH_AIN1N_AIN1N, \
(bits), (storagebits), 0), \
- AD_SD_SUPPLY_CHANNEL(3, 2, AD7791_CH_AVDD_MONITOR, \
+ AD7991_SUPPLY_CHANNEL(3, 2, AD7791_CH_AVDD_MONITOR, \
(bits), (storagebits), 0), \
IIO_CHAN_SOFT_TIMESTAMP(4), \
}
#define DECLARE_AD7791_CHANNELS(name, bits, storagebits) \
const struct iio_chan_spec name[] = { \
- AD_SD_DIFF_CHANNEL(0, 0, 0, AD7791_CH_AIN1P_AIN1N, \
+ AD7991_DIFF_CHANNEL(0, 0, 0, AD7791_CH_AIN1P_AIN1N, \
(bits), (storagebits), 0), \
- AD_SD_SHORTED_CHANNEL(1, 0, AD7791_CH_AIN1N_AIN1N, \
+ AD7991_SHORTED_CHANNEL(1, 0, AD7791_CH_AIN1N_AIN1N, \
(bits), (storagebits), 0), \
- AD_SD_SUPPLY_CHANNEL(2, 1, AD7791_CH_AVDD_MONITOR, \
+ AD7991_SUPPLY_CHANNEL(2, 1, AD7791_CH_AVDD_MONITOR, \
(bits), (storagebits), 0), \
IIO_CHAN_SOFT_TIMESTAMP(3), \
}
@@ -377,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;
@@ -444,5 +490,5 @@ static struct spi_driver ad7791_driver = {
module_spi_driver(ad7791_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
-MODULE_DESCRIPTION("Analog Device AD7787/AD7788/AD7789/AD7790/AD7791 ADC driver");
+MODULE_DESCRIPTION("Analog Devices AD7787/AD7788/AD7789/AD7790/AD7791 ADC driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c
index e5691e330323..5e980a06258e 100644
--- a/drivers/iio/adc/ad7793.c
+++ b/drivers/iio/adc/ad7793.c
@@ -354,29 +354,28 @@ static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(
static IIO_CONST_ATTR_NAMED(sampling_frequency_available_ad7797,
sampling_frequency_available, "123 62 50 33 17 16 12 10 8 6 4");
-static ssize_t ad7793_show_scale_available(struct device *dev,
- struct device_attribute *attr, char *buf)
+static int ad7793_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long mask)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7793_state *st = iio_priv(indio_dev);
- int i, len = 0;
- for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++)
- len += sprintf(buf + len, "%d.%09u ", st->scale_avail[i][0],
- st->scale_avail[i][1]);
-
- len += sprintf(buf + len, "\n");
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ *vals = (int *)st->scale_avail;
+ *type = IIO_VAL_INT_PLUS_NANO;
+ /* Values are stored in a 2D matrix */
+ *length = ARRAY_SIZE(st->scale_avail) * 2;
- return len;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
}
-static IIO_DEVICE_ATTR_NAMED(in_m_in_scale_available,
- in_voltage-voltage_scale_available, S_IRUGO,
- ad7793_show_scale_available, NULL, 0);
-
static struct attribute *ad7793_attributes[] = {
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
- &iio_dev_attr_in_m_in_scale_available.dev_attr.attr,
NULL
};
@@ -534,6 +533,7 @@ static const struct iio_info ad7793_info = {
.read_raw = &ad7793_read_raw,
.write_raw = &ad7793_write_raw,
.write_raw_get_fmt = &ad7793_write_raw_get_fmt,
+ .read_avail = ad7793_read_avail,
.attrs = &ad7793_attribute_group,
.validate_trigger = ad_sd_validate_trigger,
};
@@ -546,47 +546,113 @@ static const struct iio_info ad7797_info = {
.validate_trigger = ad_sd_validate_trigger,
};
+#define __AD7793_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
+ _storagebits, _shift, _extend_name, _type, _mask_type_av, _mask_all) \
+ { \
+ .type = (_type), \
+ .differential = (_channel2 == -1 ? 0 : 1), \
+ .indexed = 1, \
+ .channel = (_channel1), \
+ .channel2 = (_channel2), \
+ .address = (_address), \
+ .extend_name = (_extend_name), \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_OFFSET), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_type_available = (_mask_type_av), \
+ .info_mask_shared_by_all = _mask_all, \
+ .scan_index = (_si), \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = (_bits), \
+ .storagebits = (_storagebits), \
+ .shift = (_shift), \
+ .endianness = IIO_BE, \
+ }, \
+ }
+
+#define AD7793_DIFF_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
+ _storagebits, _shift) \
+ __AD7793_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
+ _storagebits, _shift, NULL, IIO_VOLTAGE, \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ))
+
+#define AD7793_SHORTED_CHANNEL(_si, _channel, _address, _bits, \
+ _storagebits, _shift) \
+ __AD7793_CHANNEL(_si, _channel, _channel, _address, _bits, \
+ _storagebits, _shift, "shorted", IIO_VOLTAGE, \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ))
+
+#define AD7793_TEMP_CHANNEL(_si, _address, _bits, _storagebits, _shift) \
+ __AD7793_CHANNEL(_si, 0, -1, _address, _bits, \
+ _storagebits, _shift, NULL, IIO_TEMP, \
+ 0, \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ))
+
+#define AD7793_SUPPLY_CHANNEL(_si, _channel, _address, _bits, _storagebits, \
+ _shift) \
+ __AD7793_CHANNEL(_si, _channel, -1, _address, _bits, \
+ _storagebits, _shift, "supply", IIO_VOLTAGE, \
+ 0, \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ))
+
+#define AD7797_DIFF_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
+ _storagebits, _shift) \
+ __AD7793_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
+ _storagebits, _shift, NULL, IIO_VOLTAGE, \
+ 0, \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ))
+
+#define AD7797_SHORTED_CHANNEL(_si, _channel, _address, _bits, \
+ _storagebits, _shift) \
+ __AD7793_CHANNEL(_si, _channel, _channel, _address, _bits, \
+ _storagebits, _shift, "shorted", IIO_VOLTAGE, \
+ 0, \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ))
+
#define DECLARE_AD7793_CHANNELS(_name, _b, _sb, _s) \
const struct iio_chan_spec _name##_channels[] = { \
- AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), (_s)), \
- AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), (_s)), \
- AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), (_s)), \
- AD_SD_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), (_s)), \
- AD_SD_TEMP_CHANNEL(4, AD7793_CH_TEMP, (_b), (_sb), (_s)), \
- AD_SD_SUPPLY_CHANNEL(5, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), (_s)), \
+ AD7793_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), (_s)), \
+ AD7793_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), (_s)), \
+ AD7793_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), (_s)), \
+ AD7793_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), (_s)), \
+ AD7793_TEMP_CHANNEL(4, AD7793_CH_TEMP, (_b), (_sb), (_s)), \
+ AD7793_SUPPLY_CHANNEL(5, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), (_s)), \
IIO_CHAN_SOFT_TIMESTAMP(6), \
}
#define DECLARE_AD7795_CHANNELS(_name, _b, _sb) \
const struct iio_chan_spec _name##_channels[] = { \
- AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \
- AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), 0), \
- AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), 0), \
- AD_SD_DIFF_CHANNEL(3, 3, 3, AD7795_CH_AIN4P_AIN4M, (_b), (_sb), 0), \
- AD_SD_DIFF_CHANNEL(4, 4, 4, AD7795_CH_AIN5P_AIN5M, (_b), (_sb), 0), \
- AD_SD_DIFF_CHANNEL(5, 5, 5, AD7795_CH_AIN6P_AIN6M, (_b), (_sb), 0), \
- AD_SD_SHORTED_CHANNEL(6, 0, AD7795_CH_AIN1M_AIN1M, (_b), (_sb), 0), \
- AD_SD_TEMP_CHANNEL(7, AD7793_CH_TEMP, (_b), (_sb), 0), \
- AD_SD_SUPPLY_CHANNEL(8, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \
+ AD7793_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \
+ AD7793_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), 0), \
+ AD7793_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), 0), \
+ AD7793_DIFF_CHANNEL(3, 3, 3, AD7795_CH_AIN4P_AIN4M, (_b), (_sb), 0), \
+ AD7793_DIFF_CHANNEL(4, 4, 4, AD7795_CH_AIN5P_AIN5M, (_b), (_sb), 0), \
+ AD7793_DIFF_CHANNEL(5, 5, 5, AD7795_CH_AIN6P_AIN6M, (_b), (_sb), 0), \
+ AD7793_SHORTED_CHANNEL(6, 0, AD7795_CH_AIN1M_AIN1M, (_b), (_sb), 0), \
+ AD7793_TEMP_CHANNEL(7, AD7793_CH_TEMP, (_b), (_sb), 0), \
+ AD7793_SUPPLY_CHANNEL(8, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \
IIO_CHAN_SOFT_TIMESTAMP(9), \
}
#define DECLARE_AD7797_CHANNELS(_name, _b, _sb) \
const struct iio_chan_spec _name##_channels[] = { \
- AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \
- AD_SD_SHORTED_CHANNEL(1, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), 0), \
- AD_SD_TEMP_CHANNEL(2, AD7793_CH_TEMP, (_b), (_sb), 0), \
- AD_SD_SUPPLY_CHANNEL(3, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \
+ AD7797_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \
+ AD7797_SHORTED_CHANNEL(1, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), 0), \
+ AD7793_TEMP_CHANNEL(2, AD7793_CH_TEMP, (_b), (_sb), 0), \
+ AD7793_SUPPLY_CHANNEL(3, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \
IIO_CHAN_SOFT_TIMESTAMP(4), \
}
#define DECLARE_AD7799_CHANNELS(_name, _b, _sb) \
const struct iio_chan_spec _name##_channels[] = { \
- AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \
- AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), 0), \
- AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), 0), \
- AD_SD_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), 0), \
- AD_SD_SUPPLY_CHANNEL(4, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \
+ AD7793_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \
+ AD7793_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), 0), \
+ AD7793_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), 0), \
+ AD7793_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), 0), \
+ AD7793_SUPPLY_CHANNEL(4, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \
IIO_CHAN_SOFT_TIMESTAMP(5), \
}
@@ -752,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;
diff --git a/drivers/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c
index c6a3428e950a..037bcb47693c 100644
--- a/drivers/iio/adc/ad7887.c
+++ b/drivers/iio/adc/ad7887.c
@@ -109,7 +109,7 @@ static int ad7887_ring_postdisable(struct iio_dev *indio_dev)
return spi_sync(st->spi, &st->msg[AD7887_CH0]);
}
-/**
+/*
* ad7887_trigger_handler() bh of trigger launched polling to ring buffer
*
* Currently there is no option in this driver to disable the saving of
@@ -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;
diff --git a/drivers/iio/adc/ad7923.c b/drivers/iio/adc/ad7923.c
index 1d124c87c6ac..a2cc96658054 100644
--- a/drivers/iio/adc/ad7923.c
+++ b/drivers/iio/adc/ad7923.c
@@ -151,9 +151,9 @@ static const struct ad7923_chip_info ad7923_chip_info[] = {
},
};
-/**
+/*
* ad7923_update_scan_mode() setup the spi transfer buffer for the new scan mask
- **/
+ */
static int ad7923_update_scan_mode(struct iio_dev *indio_dev,
const unsigned long *active_scan_mask)
{
@@ -192,12 +192,12 @@ static int ad7923_update_scan_mode(struct iio_dev *indio_dev,
return 0;
}
-/**
+/*
* ad7923_trigger_handler() bh of trigger launched polling to ring buffer
*
* Currently there is no option in this driver to disable the saving of
* timestamps within the ring.
- **/
+ */
static irqreturn_t ad7923_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
@@ -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;
diff --git a/drivers/iio/adc/ad7949.c b/drivers/iio/adc/ad7949.c
index 2c6f60edb7ce..d9566a83988a 100644
--- a/drivers/iio/adc/ad7949.c
+++ b/drivers/iio/adc/ad7949.c
@@ -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;
diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c
index ef013af1aec0..1575b7670207 100644
--- a/drivers/iio/adc/ad799x.c
+++ b/drivers/iio/adc/ad799x.c
@@ -182,7 +182,7 @@ static int ad799x_update_config(struct ad799x_state *st, u16 config)
return 0;
}
-/**
+/*
* ad799x_trigger_handler() bh of trigger launched polling to ring buffer
*
* Currently there is no option in this driver to disable the saving of
@@ -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;
diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c
new file mode 100644
index 000000000000..1e8fd83b9bc2
--- /dev/null
+++ b/drivers/iio/adc/ad9467.c
@@ -0,0 +1,422 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Analog Devices AD9467 SPI ADC driver
+ *
+ * Copyright 2012-2020 Analog Devices Inc.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/of_device.h>
+
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#include <linux/clk.h>
+
+#include <linux/iio/adc/adi-axi-adc.h>
+
+/*
+ * ADI High-Speed ADC common spi interface registers
+ * See Application-Note AN-877:
+ * https://www.analog.com/media/en/technical-documentation/application-notes/AN-877.pdf
+ */
+
+#define AN877_ADC_REG_CHIP_PORT_CONF 0x00
+#define AN877_ADC_REG_CHIP_ID 0x01
+#define AN877_ADC_REG_CHIP_GRADE 0x02
+#define AN877_ADC_REG_CHAN_INDEX 0x05
+#define AN877_ADC_REG_TRANSFER 0xFF
+#define AN877_ADC_REG_MODES 0x08
+#define AN877_ADC_REG_TEST_IO 0x0D
+#define AN877_ADC_REG_ADC_INPUT 0x0F
+#define AN877_ADC_REG_OFFSET 0x10
+#define AN877_ADC_REG_OUTPUT_MODE 0x14
+#define AN877_ADC_REG_OUTPUT_ADJUST 0x15
+#define AN877_ADC_REG_OUTPUT_PHASE 0x16
+#define AN877_ADC_REG_OUTPUT_DELAY 0x17
+#define AN877_ADC_REG_VREF 0x18
+#define AN877_ADC_REG_ANALOG_INPUT 0x2C
+
+/* AN877_ADC_REG_TEST_IO */
+#define AN877_ADC_TESTMODE_OFF 0x0
+#define AN877_ADC_TESTMODE_MIDSCALE_SHORT 0x1
+#define AN877_ADC_TESTMODE_POS_FULLSCALE 0x2
+#define AN877_ADC_TESTMODE_NEG_FULLSCALE 0x3
+#define AN877_ADC_TESTMODE_ALT_CHECKERBOARD 0x4
+#define AN877_ADC_TESTMODE_PN23_SEQ 0x5
+#define AN877_ADC_TESTMODE_PN9_SEQ 0x6
+#define AN877_ADC_TESTMODE_ONE_ZERO_TOGGLE 0x7
+#define AN877_ADC_TESTMODE_USER 0x8
+#define AN877_ADC_TESTMODE_BIT_TOGGLE 0x9
+#define AN877_ADC_TESTMODE_SYNC 0xA
+#define AN877_ADC_TESTMODE_ONE_BIT_HIGH 0xB
+#define AN877_ADC_TESTMODE_MIXED_BIT_FREQUENCY 0xC
+#define AN877_ADC_TESTMODE_RAMP 0xF
+
+/* AN877_ADC_REG_TRANSFER */
+#define AN877_ADC_TRANSFER_SYNC 0x1
+
+/* AN877_ADC_REG_OUTPUT_MODE */
+#define AN877_ADC_OUTPUT_MODE_OFFSET_BINARY 0x0
+#define AN877_ADC_OUTPUT_MODE_TWOS_COMPLEMENT 0x1
+#define AN877_ADC_OUTPUT_MODE_GRAY_CODE 0x2
+
+/* AN877_ADC_REG_OUTPUT_PHASE */
+#define AN877_ADC_OUTPUT_EVEN_ODD_MODE_EN 0x20
+#define AN877_ADC_INVERT_DCO_CLK 0x80
+
+/* AN877_ADC_REG_OUTPUT_DELAY */
+#define AN877_ADC_DCO_DELAY_ENABLE 0x80
+
+/*
+ * Analog Devices AD9467 16-Bit, 200/250 MSPS ADC
+ */
+
+#define CHIPID_AD9467 0x50
+#define AD9467_DEF_OUTPUT_MODE 0x08
+#define AD9467_REG_VREF_MASK 0x0F
+
+enum {
+ ID_AD9467,
+};
+
+struct ad9467_state {
+ struct spi_device *spi;
+ struct clk *clk;
+ unsigned int output_mode;
+
+ struct gpio_desc *pwrdown_gpio;
+ struct gpio_desc *reset_gpio;
+};
+
+static int ad9467_spi_read(struct spi_device *spi, unsigned int reg)
+{
+ unsigned char tbuf[2], rbuf[1];
+ int ret;
+
+ tbuf[0] = 0x80 | (reg >> 8);
+ tbuf[1] = reg & 0xFF;
+
+ ret = spi_write_then_read(spi,
+ tbuf, ARRAY_SIZE(tbuf),
+ rbuf, ARRAY_SIZE(rbuf));
+
+ if (ret < 0)
+ return ret;
+
+ return rbuf[0];
+}
+
+static int ad9467_spi_write(struct spi_device *spi, unsigned int reg,
+ unsigned int val)
+{
+ unsigned char buf[3];
+
+ buf[0] = reg >> 8;
+ buf[1] = reg & 0xFF;
+ buf[2] = val;
+
+ return spi_write(spi, buf, ARRAY_SIZE(buf));
+}
+
+static int ad9467_reg_access(struct adi_axi_adc_conv *conv, unsigned int reg,
+ unsigned int writeval, unsigned int *readval)
+{
+ struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
+ struct spi_device *spi = st->spi;
+ int ret;
+
+ if (readval == NULL) {
+ ret = ad9467_spi_write(spi, reg, writeval);
+ ad9467_spi_write(spi, AN877_ADC_REG_TRANSFER,
+ AN877_ADC_TRANSFER_SYNC);
+ return ret;
+ }
+
+ ret = ad9467_spi_read(spi, reg);
+ if (ret < 0)
+ return ret;
+ *readval = ret;
+
+ return 0;
+}
+
+static const unsigned int ad9467_scale_table[][2] = {
+ {2000, 0}, {2100, 6}, {2200, 7},
+ {2300, 8}, {2400, 9}, {2500, 10},
+};
+
+static void __ad9467_get_scale(struct adi_axi_adc_conv *conv, int index,
+ unsigned int *val, unsigned int *val2)
+{
+ const struct adi_axi_adc_chip_info *info = conv->chip_info;
+ const struct iio_chan_spec *chan = &info->channels[0];
+ unsigned int tmp;
+
+ tmp = (info->scale_table[index][0] * 1000000ULL) >>
+ chan->scan_type.realbits;
+ *val = tmp / 1000000;
+ *val2 = tmp % 1000000;
+}
+
+#define AD9467_CHAN(_chan, _si, _bits, _sign) \
+{ \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = _chan, \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = _si, \
+ .scan_type = { \
+ .sign = _sign, \
+ .realbits = _bits, \
+ .storagebits = 16, \
+ }, \
+}
+
+static const struct iio_chan_spec ad9467_channels[] = {
+ AD9467_CHAN(0, 0, 16, 'S'),
+};
+
+static const struct adi_axi_adc_chip_info ad9467_chip_tbl[] = {
+ [ID_AD9467] = {
+ .id = CHIPID_AD9467,
+ .max_rate = 250000000UL,
+ .scale_table = ad9467_scale_table,
+ .num_scales = ARRAY_SIZE(ad9467_scale_table),
+ .channels = ad9467_channels,
+ .num_channels = ARRAY_SIZE(ad9467_channels),
+ },
+};
+
+static int ad9467_get_scale(struct adi_axi_adc_conv *conv, int *val, int *val2)
+{
+ const struct adi_axi_adc_chip_info *info = conv->chip_info;
+ struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
+ unsigned int i, vref_val, vref_mask;
+
+ vref_val = ad9467_spi_read(st->spi, AN877_ADC_REG_VREF);
+
+ switch (info->id) {
+ case CHIPID_AD9467:
+ vref_mask = AD9467_REG_VREF_MASK;
+ break;
+ default:
+ vref_mask = 0xFFFF;
+ break;
+ }
+
+ vref_val &= vref_mask;
+
+ for (i = 0; i < info->num_scales; i++) {
+ if (vref_val == info->scale_table[i][1])
+ break;
+ }
+
+ if (i == info->num_scales)
+ return -ERANGE;
+
+ __ad9467_get_scale(conv, i, val, val2);
+
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static int ad9467_set_scale(struct adi_axi_adc_conv *conv, int val, int val2)
+{
+ const struct adi_axi_adc_chip_info *info = conv->chip_info;
+ struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
+ unsigned int scale_val[2];
+ unsigned int i;
+
+ if (val != 0)
+ return -EINVAL;
+
+ for (i = 0; i < info->num_scales; i++) {
+ __ad9467_get_scale(conv, i, &scale_val[0], &scale_val[1]);
+ if (scale_val[0] != val || scale_val[1] != val2)
+ continue;
+
+ ad9467_spi_write(st->spi, AN877_ADC_REG_VREF,
+ info->scale_table[i][1]);
+ ad9467_spi_write(st->spi, AN877_ADC_REG_TRANSFER,
+ AN877_ADC_TRANSFER_SYNC);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int ad9467_read_raw(struct adi_axi_adc_conv *conv,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long m)
+{
+ struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
+
+ switch (m) {
+ case IIO_CHAN_INFO_SCALE:
+ return ad9467_get_scale(conv, val, val2);
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = clk_get_rate(st->clk);
+
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad9467_write_raw(struct adi_axi_adc_conv *conv,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ const struct adi_axi_adc_chip_info *info = conv->chip_info;
+ struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
+ long r_clk;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ return ad9467_set_scale(conv, val, val2);
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ r_clk = clk_round_rate(st->clk, val);
+ if (r_clk < 0 || r_clk > info->max_rate) {
+ dev_warn(&st->spi->dev,
+ "Error setting ADC sample rate %ld", r_clk);
+ return -EINVAL;
+ }
+
+ return clk_set_rate(st->clk, r_clk);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad9467_outputmode_set(struct spi_device *spi, unsigned int mode)
+{
+ int ret;
+
+ ret = ad9467_spi_write(spi, AN877_ADC_REG_OUTPUT_MODE, mode);
+ if (ret < 0)
+ return ret;
+
+ return ad9467_spi_write(spi, AN877_ADC_REG_TRANSFER,
+ AN877_ADC_TRANSFER_SYNC);
+}
+
+static int ad9467_preenable_setup(struct adi_axi_adc_conv *conv)
+{
+ struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
+
+ return ad9467_outputmode_set(st->spi, st->output_mode);
+}
+
+static int ad9467_setup(struct ad9467_state *st, unsigned int chip_id)
+{
+ switch (chip_id) {
+ case CHIPID_AD9467:
+ st->output_mode = AD9467_DEF_OUTPUT_MODE |
+ AN877_ADC_OUTPUT_MODE_TWOS_COMPLEMENT;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static void ad9467_clk_disable(void *data)
+{
+ struct ad9467_state *st = data;
+
+ clk_disable_unprepare(st->clk);
+}
+
+static int ad9467_probe(struct spi_device *spi)
+{
+ const struct adi_axi_adc_chip_info *info;
+ struct adi_axi_adc_conv *conv;
+ struct ad9467_state *st;
+ unsigned int id;
+ int ret;
+
+ info = of_device_get_match_data(&spi->dev);
+ if (!info)
+ return -ENODEV;
+
+ conv = devm_adi_axi_adc_conv_register(&spi->dev, sizeof(*st));
+ if (IS_ERR(conv))
+ return PTR_ERR(conv);
+
+ st = adi_axi_adc_conv_priv(conv);
+ st->spi = spi;
+
+ st->clk = devm_clk_get(&spi->dev, "adc-clk");
+ if (IS_ERR(st->clk))
+ return PTR_ERR(st->clk);
+
+ ret = clk_prepare_enable(st->clk);
+ if (ret < 0)
+ return ret;
+
+ ret = devm_add_action_or_reset(&spi->dev, ad9467_clk_disable, st);
+ if (ret)
+ return ret;
+
+ st->pwrdown_gpio = devm_gpiod_get_optional(&spi->dev, "powerdown",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(st->pwrdown_gpio))
+ return PTR_ERR(st->pwrdown_gpio);
+
+ st->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(st->reset_gpio))
+ return PTR_ERR(st->reset_gpio);
+
+ if (st->reset_gpio) {
+ udelay(1);
+ ret = gpiod_direction_output(st->reset_gpio, 1);
+ if (ret)
+ return ret;
+ mdelay(10);
+ }
+
+ spi_set_drvdata(spi, st);
+
+ conv->chip_info = info;
+
+ id = ad9467_spi_read(spi, AN877_ADC_REG_CHIP_ID);
+ if (id != conv->chip_info->id) {
+ dev_err(&spi->dev, "Unrecognized CHIP_ID 0x%X\n", id);
+ return -ENODEV;
+ }
+
+ conv->reg_access = ad9467_reg_access;
+ conv->write_raw = ad9467_write_raw;
+ conv->read_raw = ad9467_read_raw;
+ conv->preenable_setup = ad9467_preenable_setup;
+
+ return ad9467_setup(st, id);
+}
+
+static const struct of_device_id ad9467_of_match[] = {
+ { .compatible = "adi,ad9467", .data = &ad9467_chip_tbl[ID_AD9467], },
+ {}
+};
+MODULE_DEVICE_TABLE(of, ad9467_of_match);
+
+static struct spi_driver ad9467_driver = {
+ .driver = {
+ .name = "ad9467",
+ .of_match_table = ad9467_of_match,
+ },
+ .probe = ad9467_probe,
+};
+module_spi_driver(ad9467_driver);
+
+MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
+MODULE_DESCRIPTION("Analog Devices AD9467 ADC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
index 8115b6de1d6c..86039e9ecaca 100644
--- a/drivers/iio/adc/ad_sigma_delta.c
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -70,9 +70,7 @@ int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
switch (size) {
case 3:
- data[1] = val >> 16;
- data[2] = val >> 8;
- data[3] = val;
+ put_unaligned_be24(val, &data[1]);
break;
case 2:
put_unaligned_be16(val, &data[1]);
@@ -157,9 +155,7 @@ int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta,
*val = get_unaligned_be32(sigma_delta->data);
break;
case 3:
- *val = (sigma_delta->data[0] << 16) |
- (sigma_delta->data[1] << 8) |
- sigma_delta->data[2];
+ *val = get_unaligned_be24(&sigma_delta->data[0]);
break;
case 2:
*val = get_unaligned_be16(sigma_delta->data);
@@ -349,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,
@@ -406,7 +398,6 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
unsigned int reg_size;
unsigned int data_reg;
uint8_t data[16];
- int ret;
memset(data, 0x00, 16);
@@ -423,14 +414,12 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
case 4:
case 2:
case 1:
- ret = ad_sd_read_reg_raw(sigma_delta, data_reg, reg_size,
- &data[0]);
+ ad_sd_read_reg_raw(sigma_delta, data_reg, reg_size, &data[0]);
break;
case 3:
/* We store 24 bit samples in a 32 bit word. Keep the upper
* byte set to zero. */
- ret = ad_sd_read_reg_raw(sigma_delta, data_reg, reg_size,
- &data[1]);
+ ad_sd_read_reg_raw(sigma_delta, data_reg, reg_size, &data[1]);
break;
}
@@ -445,7 +434,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,
};
diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c
new file mode 100644
index 000000000000..86b6b65916ee
--- /dev/null
+++ b/drivers/iio/adc/adi-axi-adc.c
@@ -0,0 +1,481 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Analog Devices Generic AXI ADC IP core
+ * Link: https://wiki.analog.com/resources/fpga/docs/axi_adc_ip
+ *
+ * Copyright 2012-2020 Analog Devices Inc.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/buffer-dmaengine.h>
+
+#include <linux/fpga/adi-axi-common.h>
+#include <linux/iio/adc/adi-axi-adc.h>
+
+/**
+ * Register definitions:
+ * https://wiki.analog.com/resources/fpga/docs/axi_adc_ip#register_map
+ */
+
+/* ADC controls */
+
+#define ADI_AXI_REG_RSTN 0x0040
+#define ADI_AXI_REG_RSTN_CE_N BIT(2)
+#define ADI_AXI_REG_RSTN_MMCM_RSTN BIT(1)
+#define ADI_AXI_REG_RSTN_RSTN BIT(0)
+
+/* ADC Channel controls */
+
+#define ADI_AXI_REG_CHAN_CTRL(c) (0x0400 + (c) * 0x40)
+#define ADI_AXI_REG_CHAN_CTRL_LB_OWR BIT(11)
+#define ADI_AXI_REG_CHAN_CTRL_PN_SEL_OWR BIT(10)
+#define ADI_AXI_REG_CHAN_CTRL_IQCOR_EN BIT(9)
+#define ADI_AXI_REG_CHAN_CTRL_DCFILT_EN BIT(8)
+#define ADI_AXI_REG_CHAN_CTRL_FMT_SIGNEXT BIT(6)
+#define ADI_AXI_REG_CHAN_CTRL_FMT_TYPE BIT(5)
+#define ADI_AXI_REG_CHAN_CTRL_FMT_EN BIT(4)
+#define ADI_AXI_REG_CHAN_CTRL_PN_TYPE_OWR BIT(1)
+#define ADI_AXI_REG_CHAN_CTRL_ENABLE BIT(0)
+
+#define ADI_AXI_REG_CHAN_CTRL_DEFAULTS \
+ (ADI_AXI_REG_CHAN_CTRL_FMT_SIGNEXT | \
+ ADI_AXI_REG_CHAN_CTRL_FMT_EN | \
+ ADI_AXI_REG_CHAN_CTRL_ENABLE)
+
+struct adi_axi_adc_core_info {
+ unsigned int version;
+};
+
+struct adi_axi_adc_state {
+ struct mutex lock;
+
+ struct adi_axi_adc_client *client;
+ void __iomem *regs;
+};
+
+struct adi_axi_adc_client {
+ struct list_head entry;
+ struct adi_axi_adc_conv conv;
+ struct adi_axi_adc_state *state;
+ struct device *dev;
+ const struct adi_axi_adc_core_info *info;
+};
+
+static LIST_HEAD(registered_clients);
+static DEFINE_MUTEX(registered_clients_lock);
+
+static struct adi_axi_adc_client *conv_to_client(struct adi_axi_adc_conv *conv)
+{
+ return container_of(conv, struct adi_axi_adc_client, conv);
+}
+
+void *adi_axi_adc_conv_priv(struct adi_axi_adc_conv *conv)
+{
+ struct adi_axi_adc_client *cl = conv_to_client(conv);
+
+ return (char *)cl + ALIGN(sizeof(struct adi_axi_adc_client), IIO_ALIGN);
+}
+EXPORT_SYMBOL_GPL(adi_axi_adc_conv_priv);
+
+static void adi_axi_adc_write(struct adi_axi_adc_state *st,
+ unsigned int reg,
+ unsigned int val)
+{
+ iowrite32(val, st->regs + reg);
+}
+
+static unsigned int adi_axi_adc_read(struct adi_axi_adc_state *st,
+ unsigned int reg)
+{
+ return ioread32(st->regs + reg);
+}
+
+static int adi_axi_adc_config_dma_buffer(struct device *dev,
+ struct iio_dev *indio_dev)
+{
+ struct iio_buffer *buffer;
+ const char *dma_name;
+
+ if (!device_property_present(dev, "dmas"))
+ return 0;
+
+ if (device_property_read_string(dev, "dma-names", &dma_name))
+ dma_name = "rx";
+
+ buffer = devm_iio_dmaengine_buffer_alloc(indio_dev->dev.parent,
+ dma_name);
+ if (IS_ERR(buffer))
+ return PTR_ERR(buffer);
+
+ indio_dev->modes |= INDIO_BUFFER_HARDWARE;
+ iio_device_attach_buffer(indio_dev, buffer);
+
+ return 0;
+}
+
+static int adi_axi_adc_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct adi_axi_adc_state *st = iio_priv(indio_dev);
+ struct adi_axi_adc_conv *conv = &st->client->conv;
+
+ if (!conv->read_raw)
+ return -EOPNOTSUPP;
+
+ return conv->read_raw(conv, chan, val, val2, mask);
+}
+
+static int adi_axi_adc_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct adi_axi_adc_state *st = iio_priv(indio_dev);
+ struct adi_axi_adc_conv *conv = &st->client->conv;
+
+ if (!conv->write_raw)
+ return -EOPNOTSUPP;
+
+ return conv->write_raw(conv, chan, val, val2, mask);
+}
+
+static int adi_axi_adc_update_scan_mode(struct iio_dev *indio_dev,
+ const unsigned long *scan_mask)
+{
+ struct adi_axi_adc_state *st = iio_priv(indio_dev);
+ struct adi_axi_adc_conv *conv = &st->client->conv;
+ unsigned int i, ctrl;
+
+ for (i = 0; i < conv->chip_info->num_channels; i++) {
+ ctrl = adi_axi_adc_read(st, ADI_AXI_REG_CHAN_CTRL(i));
+
+ if (test_bit(i, scan_mask))
+ ctrl |= ADI_AXI_REG_CHAN_CTRL_ENABLE;
+ else
+ ctrl &= ~ADI_AXI_REG_CHAN_CTRL_ENABLE;
+
+ adi_axi_adc_write(st, ADI_AXI_REG_CHAN_CTRL(i), ctrl);
+ }
+
+ return 0;
+}
+
+static struct adi_axi_adc_conv *adi_axi_adc_conv_register(struct device *dev,
+ size_t sizeof_priv)
+{
+ struct adi_axi_adc_client *cl;
+ size_t alloc_size;
+
+ alloc_size = ALIGN(sizeof(struct adi_axi_adc_client), IIO_ALIGN);
+ if (sizeof_priv)
+ alloc_size += ALIGN(sizeof_priv, IIO_ALIGN);
+
+ cl = kzalloc(alloc_size, GFP_KERNEL);
+ if (!cl)
+ return ERR_PTR(-ENOMEM);
+
+ mutex_lock(&registered_clients_lock);
+
+ cl->dev = get_device(dev);
+
+ list_add_tail(&cl->entry, &registered_clients);
+
+ mutex_unlock(&registered_clients_lock);
+
+ return &cl->conv;
+}
+
+static void adi_axi_adc_conv_unregister(struct adi_axi_adc_conv *conv)
+{
+ struct adi_axi_adc_client *cl = conv_to_client(conv);
+
+ mutex_lock(&registered_clients_lock);
+
+ list_del(&cl->entry);
+ put_device(cl->dev);
+
+ mutex_unlock(&registered_clients_lock);
+
+ kfree(cl);
+}
+
+static void devm_adi_axi_adc_conv_release(struct device *dev, void *res)
+{
+ adi_axi_adc_conv_unregister(*(struct adi_axi_adc_conv **)res);
+}
+
+struct adi_axi_adc_conv *devm_adi_axi_adc_conv_register(struct device *dev,
+ size_t sizeof_priv)
+{
+ struct adi_axi_adc_conv **ptr, *conv;
+
+ ptr = devres_alloc(devm_adi_axi_adc_conv_release, sizeof(*ptr),
+ GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ conv = adi_axi_adc_conv_register(dev, sizeof_priv);
+ if (IS_ERR(conv)) {
+ devres_free(ptr);
+ return ERR_CAST(conv);
+ }
+
+ *ptr = conv;
+ devres_add(dev, ptr);
+
+ return conv;
+}
+EXPORT_SYMBOL_GPL(devm_adi_axi_adc_conv_register);
+
+static ssize_t in_voltage_scale_available_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct adi_axi_adc_state *st = iio_priv(indio_dev);
+ struct adi_axi_adc_conv *conv = &st->client->conv;
+ size_t len = 0;
+ int i;
+
+ for (i = 0; i < conv->chip_info->num_scales; i++) {
+ const unsigned int *s = conv->chip_info->scale_table[i];
+
+ len += scnprintf(buf + len, PAGE_SIZE - len,
+ "%u.%06u ", s[0], s[1]);
+ }
+ buf[len - 1] = '\n';
+
+ return len;
+}
+
+static IIO_DEVICE_ATTR_RO(in_voltage_scale_available, 0);
+
+enum {
+ ADI_AXI_ATTR_SCALE_AVAIL,
+};
+
+#define ADI_AXI_ATTR(_en_, _file_) \
+ [ADI_AXI_ATTR_##_en_] = &iio_dev_attr_##_file_.dev_attr.attr
+
+static struct attribute *adi_axi_adc_attributes[] = {
+ ADI_AXI_ATTR(SCALE_AVAIL, in_voltage_scale_available),
+ NULL
+};
+
+static umode_t axi_adc_attr_is_visible(struct kobject *kobj,
+ struct attribute *attr, int n)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct adi_axi_adc_state *st = iio_priv(indio_dev);
+ struct adi_axi_adc_conv *conv = &st->client->conv;
+
+ switch (n) {
+ case ADI_AXI_ATTR_SCALE_AVAIL:
+ if (!conv->chip_info->num_scales)
+ return 0;
+ return attr->mode;
+ default:
+ return attr->mode;
+ }
+}
+
+static const struct attribute_group adi_axi_adc_attribute_group = {
+ .attrs = adi_axi_adc_attributes,
+ .is_visible = axi_adc_attr_is_visible,
+};
+
+static const struct iio_info adi_axi_adc_info = {
+ .read_raw = &adi_axi_adc_read_raw,
+ .write_raw = &adi_axi_adc_write_raw,
+ .attrs = &adi_axi_adc_attribute_group,
+ .update_scan_mode = &adi_axi_adc_update_scan_mode,
+};
+
+static const struct adi_axi_adc_core_info adi_axi_adc_10_0_a_info = {
+ .version = ADI_AXI_PCORE_VER(10, 0, 'a'),
+};
+
+static struct adi_axi_adc_client *adi_axi_adc_attach_client(struct device *dev)
+{
+ const struct adi_axi_adc_core_info *info;
+ struct adi_axi_adc_client *cl;
+ struct device_node *cln;
+
+ info = of_device_get_match_data(dev);
+ if (!info)
+ return ERR_PTR(-ENODEV);
+
+ cln = of_parse_phandle(dev->of_node, "adi,adc-dev", 0);
+ if (!cln) {
+ dev_err(dev, "No 'adi,adc-dev' node defined\n");
+ return ERR_PTR(-ENODEV);
+ }
+
+ mutex_lock(&registered_clients_lock);
+
+ list_for_each_entry(cl, &registered_clients, entry) {
+ if (!cl->dev)
+ continue;
+
+ if (cl->dev->of_node != cln)
+ continue;
+
+ if (!try_module_get(cl->dev->driver->owner)) {
+ mutex_unlock(&registered_clients_lock);
+ return ERR_PTR(-ENODEV);
+ }
+
+ get_device(cl->dev);
+ cl->info = info;
+ mutex_unlock(&registered_clients_lock);
+ return cl;
+ }
+
+ mutex_unlock(&registered_clients_lock);
+
+ return ERR_PTR(-EPROBE_DEFER);
+}
+
+static int adi_axi_adc_setup_channels(struct device *dev,
+ struct adi_axi_adc_state *st)
+{
+ struct adi_axi_adc_conv *conv = &st->client->conv;
+ int i, ret;
+
+ if (conv->preenable_setup) {
+ ret = conv->preenable_setup(conv);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < conv->chip_info->num_channels; i++) {
+ adi_axi_adc_write(st, ADI_AXI_REG_CHAN_CTRL(i),
+ ADI_AXI_REG_CHAN_CTRL_DEFAULTS);
+ }
+
+ return 0;
+}
+
+static void axi_adc_reset(struct adi_axi_adc_state *st)
+{
+ adi_axi_adc_write(st, ADI_AXI_REG_RSTN, 0);
+ mdelay(10);
+ adi_axi_adc_write(st, ADI_AXI_REG_RSTN, ADI_AXI_REG_RSTN_MMCM_RSTN);
+ mdelay(10);
+ adi_axi_adc_write(st, ADI_AXI_REG_RSTN,
+ ADI_AXI_REG_RSTN_RSTN | ADI_AXI_REG_RSTN_MMCM_RSTN);
+}
+
+static void adi_axi_adc_cleanup(void *data)
+{
+ struct adi_axi_adc_client *cl = data;
+
+ put_device(cl->dev);
+ module_put(cl->dev->driver->owner);
+}
+
+static int adi_axi_adc_probe(struct platform_device *pdev)
+{
+ struct adi_axi_adc_conv *conv;
+ struct iio_dev *indio_dev;
+ struct adi_axi_adc_client *cl;
+ struct adi_axi_adc_state *st;
+ unsigned int ver;
+ int ret;
+
+ cl = adi_axi_adc_attach_client(&pdev->dev);
+ if (IS_ERR(cl))
+ return PTR_ERR(cl);
+
+ ret = devm_add_action_or_reset(&pdev->dev, adi_axi_adc_cleanup, cl);
+ if (ret)
+ return ret;
+
+ indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
+ if (indio_dev == NULL)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+ st->client = cl;
+ cl->state = st;
+ mutex_init(&st->lock);
+
+ st->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(st->regs))
+ return PTR_ERR(st->regs);
+
+ conv = &st->client->conv;
+
+ axi_adc_reset(st);
+
+ ver = adi_axi_adc_read(st, ADI_AXI_REG_VERSION);
+
+ if (cl->info->version > ver) {
+ dev_err(&pdev->dev,
+ "IP core version is too old. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n",
+ ADI_AXI_PCORE_VER_MAJOR(cl->info->version),
+ ADI_AXI_PCORE_VER_MINOR(cl->info->version),
+ ADI_AXI_PCORE_VER_PATCH(cl->info->version),
+ ADI_AXI_PCORE_VER_MAJOR(ver),
+ ADI_AXI_PCORE_VER_MINOR(ver),
+ ADI_AXI_PCORE_VER_PATCH(ver));
+ return -ENODEV;
+ }
+
+ indio_dev->info = &adi_axi_adc_info;
+ indio_dev->name = "adi-axi-adc";
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->num_channels = conv->chip_info->num_channels;
+ indio_dev->channels = conv->chip_info->channels;
+
+ ret = adi_axi_adc_config_dma_buffer(&pdev->dev, indio_dev);
+ if (ret)
+ return ret;
+
+ ret = adi_axi_adc_setup_channels(&pdev->dev, st);
+ if (ret)
+ return ret;
+
+ ret = devm_iio_device_register(&pdev->dev, indio_dev);
+ if (ret)
+ return ret;
+
+ dev_info(&pdev->dev, "AXI ADC IP core (%d.%.2d.%c) probed\n",
+ ADI_AXI_PCORE_VER_MAJOR(ver),
+ ADI_AXI_PCORE_VER_MINOR(ver),
+ ADI_AXI_PCORE_VER_PATCH(ver));
+
+ return 0;
+}
+
+/* Match table for of_platform binding */
+static const struct of_device_id adi_axi_adc_of_match[] = {
+ { .compatible = "adi,axi-adc-10.0.a", .data = &adi_axi_adc_10_0_a_info },
+ { /* end of list */ }
+};
+MODULE_DEVICE_TABLE(of, adi_axi_adc_of_match);
+
+static struct platform_driver adi_axi_adc_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .of_match_table = adi_axi_adc_of_match,
+ },
+ .probe = adi_axi_adc_probe,
+};
+module_platform_driver(adi_axi_adc_driver);
+
+MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
+MODULE_DESCRIPTION("Analog Devices Generic AXI ADC IP core driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c
index 1e5375235cfe..19efaa41bc34 100644
--- a/drivers/iio/adc/aspeed_adc.c
+++ b/drivers/iio/adc/aspeed_adc.c
@@ -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;
diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index 9d96f7d08b95..de9583d6cddd 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -8,6 +8,7 @@
#include <linux/bitops.h>
#include <linux/clk.h>
+#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/interrupt.h>
@@ -100,6 +101,8 @@
#define AT91_SAMA5D2_IER_YRDY BIT(21)
/* Interrupt Enable Register - TS pressure measurement ready */
#define AT91_SAMA5D2_IER_PRDY BIT(22)
+/* Interrupt Enable Register - Data ready */
+#define AT91_SAMA5D2_IER_DRDY BIT(24)
/* Interrupt Enable Register - general overrun error */
#define AT91_SAMA5D2_IER_GOVRE BIT(25)
/* Interrupt Enable Register - Pen detect */
@@ -344,7 +347,7 @@ struct at91_adc_trigger {
};
/**
- * at91_adc_dma - at91-sama5d2 dma information struct
+ * struct at91_adc_dma - at91-sama5d2 dma information struct
* @dma_chan: the dma channel acquired
* @rx_buf: dma coherent allocated area
* @rx_dma_buf: dma handler for the buffer
@@ -366,7 +369,7 @@ struct at91_adc_dma {
};
/**
- * at91_adc_touch - at91-sama5d2 touchscreen information struct
+ * struct at91_adc_touch - at91-sama5d2 touchscreen information struct
* @sample_period_val: the value for periodic trigger interval
* @touching: is the pen touching the screen or not
* @x_pos: temporary placeholder for pressure computation
@@ -399,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
@@ -486,6 +490,21 @@ static inline int at91_adc_of_xlate(struct iio_dev *indio_dev,
return at91_adc_chan_xlate(indio_dev, iiospec->args[0]);
}
+static unsigned int at91_adc_active_scan_mask_to_reg(struct iio_dev *indio_dev)
+{
+ u32 mask = 0;
+ u8 bit;
+
+ for_each_set_bit(bit, indio_dev->active_scan_mask,
+ indio_dev->num_channels) {
+ struct iio_chan_spec const *chan =
+ at91_adc_chan_get(indio_dev, bit);
+ mask |= BIT(chan->channel);
+ }
+
+ return mask & GENMASK(11, 0);
+}
+
static void at91_adc_config_emr(struct at91_adc_state *st)
{
/* configure the extended mode register */
@@ -624,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;
@@ -710,7 +729,6 @@ static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
struct iio_dev *indio = iio_trigger_get_drvdata(trig);
struct at91_adc_state *st = iio_priv(indio);
u32 status = at91_adc_readl(st, AT91_SAMA5D2_TRGR);
- u8 bit;
/* clear TRGMOD */
status &= ~AT91_SAMA5D2_TRGR_TRGMOD_MASK;
@@ -721,50 +739,6 @@ static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
/* set/unset hw trigger */
at91_adc_writel(st, AT91_SAMA5D2_TRGR, status);
- for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
- struct iio_chan_spec const *chan = at91_adc_chan_get(indio, bit);
- u32 cor;
-
- if (!chan)
- continue;
- /* these channel types cannot be handled by this trigger */
- if (chan->type == IIO_POSITIONRELATIVE ||
- chan->type == IIO_PRESSURE)
- continue;
-
- if (state) {
- cor = at91_adc_readl(st, AT91_SAMA5D2_COR);
-
- if (chan->differential)
- cor |= (BIT(chan->channel) |
- BIT(chan->channel2)) <<
- AT91_SAMA5D2_COR_DIFF_OFFSET;
- else
- cor &= ~(BIT(chan->channel) <<
- AT91_SAMA5D2_COR_DIFF_OFFSET);
-
- at91_adc_writel(st, AT91_SAMA5D2_COR, cor);
- }
-
- if (state) {
- at91_adc_writel(st, AT91_SAMA5D2_CHER,
- BIT(chan->channel));
- /* enable irq only if not using DMA */
- if (!st->dma_st.dma_chan) {
- at91_adc_writel(st, AT91_SAMA5D2_IER,
- BIT(chan->channel));
- }
- } else {
- /* disable irq only if not using DMA */
- if (!st->dma_st.dma_chan) {
- at91_adc_writel(st, AT91_SAMA5D2_IDR,
- BIT(chan->channel));
- }
- at91_adc_writel(st, AT91_SAMA5D2_CHDR,
- BIT(chan->channel));
- }
- }
-
return 0;
}
@@ -781,6 +755,7 @@ static int at91_adc_reenable_trigger(struct iio_trigger *trig)
/* Needed to ACK the DRDY interruption */
at91_adc_readl(st, AT91_SAMA5D2_LCDR);
+
return 0;
}
@@ -888,18 +863,37 @@ static int at91_adc_dma_start(struct iio_dev *indio_dev)
return 0;
}
-static int at91_adc_buffer_postenable(struct iio_dev *indio_dev)
+static bool at91_adc_buffer_check_use_irq(struct iio_dev *indio,
+ struct at91_adc_state *st)
+{
+ /* if using DMA, we do not use our own IRQ (we use DMA-controller) */
+ if (st->dma_st.dma_chan)
+ return false;
+ /* if the trigger is not ours, then it has its own IRQ */
+ if (iio_trigger_validate_own_device(indio->trig, indio))
+ return false;
+ return true;
+}
+
+static bool at91_adc_current_chan_is_touch(struct iio_dev *indio_dev)
+{
+ struct at91_adc_state *st = iio_priv(indio_dev);
+
+ return !!bitmap_subset(indio_dev->active_scan_mask,
+ &st->touch_st.channels_bitmask,
+ AT91_SAMA5D2_MAX_CHAN_IDX + 1);
+}
+
+static int at91_adc_buffer_preenable(struct iio_dev *indio_dev)
{
int ret;
+ u8 bit;
struct at91_adc_state *st = iio_priv(indio_dev);
/* check if we are enabling triggered buffer or the touchscreen */
- if (bitmap_subset(indio_dev->active_scan_mask,
- &st->touch_st.channels_bitmask,
- AT91_SAMA5D2_MAX_CHAN_IDX + 1)) {
- /* touchscreen enabling */
+ if (at91_adc_current_chan_is_touch(indio_dev))
return at91_adc_configure_touch(st, true);
- }
+
/* if we are not in triggered mode, we cannot enable the buffer. */
if (!(indio_dev->currentmode & INDIO_ALL_TRIGGERED_MODES))
return -EINVAL;
@@ -911,41 +905,57 @@ static int at91_adc_buffer_postenable(struct iio_dev *indio_dev)
return ret;
}
- return iio_triggered_buffer_postenable(indio_dev);
+ for_each_set_bit(bit, indio_dev->active_scan_mask,
+ indio_dev->num_channels) {
+ struct iio_chan_spec const *chan =
+ at91_adc_chan_get(indio_dev, bit);
+ u32 cor;
+
+ if (!chan)
+ continue;
+ /* these channel types cannot be handled by this trigger */
+ if (chan->type == IIO_POSITIONRELATIVE ||
+ chan->type == IIO_PRESSURE)
+ continue;
+
+ cor = at91_adc_readl(st, AT91_SAMA5D2_COR);
+
+ if (chan->differential)
+ cor |= (BIT(chan->channel) | BIT(chan->channel2)) <<
+ AT91_SAMA5D2_COR_DIFF_OFFSET;
+ else
+ cor &= ~(BIT(chan->channel) <<
+ AT91_SAMA5D2_COR_DIFF_OFFSET);
+
+ at91_adc_writel(st, AT91_SAMA5D2_COR, cor);
+
+ at91_adc_writel(st, AT91_SAMA5D2_CHER, BIT(chan->channel));
+ }
+
+ if (at91_adc_buffer_check_use_irq(indio_dev, st))
+ at91_adc_writel(st, AT91_SAMA5D2_IER, AT91_SAMA5D2_IER_DRDY);
+
+ return 0;
}
-static int at91_adc_buffer_predisable(struct iio_dev *indio_dev)
+static int at91_adc_buffer_postdisable(struct iio_dev *indio_dev)
{
struct at91_adc_state *st = iio_priv(indio_dev);
- int ret;
u8 bit;
/* check if we are disabling triggered buffer or the touchscreen */
- if (bitmap_subset(indio_dev->active_scan_mask,
- &st->touch_st.channels_bitmask,
- AT91_SAMA5D2_MAX_CHAN_IDX + 1)) {
- /* touchscreen disable */
+ if (at91_adc_current_chan_is_touch(indio_dev))
return at91_adc_configure_touch(st, false);
- }
+
/* if we are not in triggered mode, nothing to do here */
if (!(indio_dev->currentmode & INDIO_ALL_TRIGGERED_MODES))
return -EINVAL;
- /* continue with the triggered buffer */
- ret = iio_triggered_buffer_predisable(indio_dev);
- if (ret < 0)
- dev_err(&indio_dev->dev, "buffer predisable failed\n");
-
- if (!st->dma_st.dma_chan)
- return ret;
-
- /* if we are using DMA we must clear registers and end DMA */
- dmaengine_terminate_sync(st->dma_st.dma_chan);
-
/*
- * For each enabled channel we must read the last converted value
+ * For each enable channel we must disable it in hardware.
+ * In the case of DMA, we must read the last converted value
* to clear EOC status and not get a possible interrupt later.
- * This value is being read by DMA from LCDR anyway
+ * This value is being read by DMA from LCDR anyway, so it's not lost.
*/
for_each_set_bit(bit, indio_dev->active_scan_mask,
indio_dev->num_channels) {
@@ -958,18 +968,29 @@ static int at91_adc_buffer_predisable(struct iio_dev *indio_dev)
if (chan->type == IIO_POSITIONRELATIVE ||
chan->type == IIO_PRESSURE)
continue;
+
+ at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel));
+
if (st->dma_st.dma_chan)
at91_adc_readl(st, chan->address);
}
+ if (at91_adc_buffer_check_use_irq(indio_dev, st))
+ at91_adc_writel(st, AT91_SAMA5D2_IDR, AT91_SAMA5D2_IER_DRDY);
+
/* read overflow register to clear possible overflow status */
at91_adc_readl(st, AT91_SAMA5D2_OVER);
- return ret;
+
+ /* if we are using DMA we must clear registers and end DMA */
+ if (st->dma_st.dma_chan)
+ dmaengine_terminate_sync(st->dma_st.dma_chan);
+
+ return 0;
}
static const struct iio_buffer_setup_ops at91_buffer_setup_ops = {
- .postenable = &at91_adc_buffer_postenable,
- .predisable = &at91_adc_buffer_predisable,
+ .preenable = &at91_adc_buffer_preenable,
+ .postdisable = &at91_adc_buffer_postdisable,
};
static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio,
@@ -1015,6 +1036,22 @@ static void at91_adc_trigger_handler_nodma(struct iio_dev *indio_dev,
int i = 0;
int val;
u8 bit;
+ u32 mask = at91_adc_active_scan_mask_to_reg(indio_dev);
+ unsigned int timeout = 50;
+
+ /*
+ * Check if the conversion is ready. If not, wait a little bit, and
+ * in case of timeout exit with an error.
+ */
+ while ((at91_adc_readl(st, AT91_SAMA5D2_ISR) & mask) != mask &&
+ timeout) {
+ usleep_range(50, 100);
+ timeout--;
+ }
+
+ /* Cannot read data, not ready. Continue without reporting data */
+ if (!timeout)
+ return;
for_each_set_bit(bit, indio_dev->active_scan_mask,
indio_dev->num_channels) {
@@ -1102,6 +1139,13 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
struct iio_dev *indio_dev = pf->indio_dev;
struct at91_adc_state *st = iio_priv(indio_dev);
+ /*
+ * If it's not our trigger, start a conversion now, as we are
+ * actually polling the trigger now.
+ */
+ if (iio_trigger_validate_own_device(indio_dev->trig, indio_dev))
+ at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_START);
+
if (st->dma_st.dma_chan)
at91_adc_trigger_handler_dma(indio_dev);
else
@@ -1114,20 +1158,9 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
static int at91_adc_buffer_init(struct iio_dev *indio)
{
- struct at91_adc_state *st = iio_priv(indio);
-
- if (st->selected_trig->hw_trig) {
- return devm_iio_triggered_buffer_setup(&indio->dev, indio,
- &iio_pollfunc_store_time,
- &at91_adc_trigger_handler, &at91_buffer_setup_ops);
- }
- /*
- * we need to prepare the buffer ops in case we will get
- * another buffer attached (like a callback buffer for the touchscreen)
- */
- indio->setup_ops = &at91_buffer_setup_ops;
-
- return 0;
+ return devm_iio_triggered_buffer_setup(&indio->dev, indio,
+ &iio_pollfunc_store_time,
+ &at91_adc_trigger_handler, &at91_buffer_setup_ops);
}
static unsigned at91_adc_startup_time(unsigned startup_time_min,
@@ -1154,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);
@@ -1225,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);
@@ -1247,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);
}
@@ -1268,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 */
@@ -1281,7 +1314,8 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private)
status = at91_adc_readl(st, AT91_SAMA5D2_XPOSR);
status = at91_adc_readl(st, AT91_SAMA5D2_YPOSR);
status = at91_adc_readl(st, AT91_SAMA5D2_PRESSR);
- } else if (iio_buffer_enabled(indio) && !st->dma_st.dma_chan) {
+ } else if (iio_buffer_enabled(indio) &&
+ (status & AT91_SAMA5D2_IER_DRDY)) {
/* triggered buffer without DMA */
disable_irq_nosync(irq);
iio_trigger_poll(indio->trig);
@@ -1435,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;
@@ -1573,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);
/*
@@ -1584,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);
@@ -1659,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;
@@ -1667,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);
@@ -1778,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)
@@ -1894,21 +1930,17 @@ 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))
return 0;
/* check if we are enabling triggered buffer or the touchscreen */
- if (bitmap_subset(indio_dev->active_scan_mask,
- &st->touch_st.channels_bitmask,
- AT91_SAMA5D2_MAX_CHAN_IDX + 1)) {
- /* touchscreen enabling */
+ if (at91_adc_current_chan_is_touch(indio_dev))
return at91_adc_configure_touch(st, true);
- } else {
+ else
return at91_adc_configure_trigger(st->trig, true);
- }
/* not needed but more explicit */
return 0;
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index abe99856c823..9b2c548fae95 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -157,7 +157,7 @@
* struct at91_adc_reg_desc - Various informations relative to registers
* @channel_base: Base offset for the channel data registers
* @drdy_mask: Mask of the DRDY field in the relevant registers
- (Interruptions registers mostly)
+ * (Interruptions registers mostly)
* @status_register: Offset of the Interrupt Status Register
* @trigger_register: Offset of the Trigger setup register
* @mr_prescal_mask: Mask of the PRESCAL field in the adc MR register
@@ -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();
@@ -1152,7 +1152,6 @@ static int at91_adc_probe(struct platform_device *pdev)
int ret;
struct iio_dev *idev;
struct at91_adc_state *st;
- struct resource *res;
u32 reg;
idev = devm_iio_device_alloc(&pdev->dev, sizeof(struct at91_adc_state));
@@ -1162,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);
@@ -1173,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;
@@ -1182,9 +1180,7 @@ static int at91_adc_probe(struct platform_device *pdev)
if (st->irq < 0)
return -ENODEV;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- st->reg_base = devm_ioremap_resource(&pdev->dev, res);
+ st->reg_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(st->reg_base))
return PTR_ERR(st->reg_base);
@@ -1304,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);
diff --git a/drivers/iio/adc/axp20x_adc.c b/drivers/iio/adc/axp20x_adc.c
index 88059480da17..798ff2d89691 100644
--- a/drivers/iio/adc/axp20x_adc.c
+++ b/drivers/iio/adc/axp20x_adc.c
@@ -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) {
diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c
index 8ea2aed6d6f5..5f5e8b39e4d2 100644
--- a/drivers/iio/adc/axp288_adc.c
+++ b/drivers/iio/adc/axp288_adc.c
@@ -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);
diff --git a/drivers/iio/adc/bcm_iproc_adc.c b/drivers/iio/adc/bcm_iproc_adc.c
index 5e396104ac86..936da32faa9d 100644
--- a/drivers/iio/adc/bcm_iproc_adc.c
+++ b/drivers/iio/adc/bcm_iproc_adc.c
@@ -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;
diff --git a/drivers/iio/adc/berlin2-adc.c b/drivers/iio/adc/berlin2-adc.c
index 72d8fa94ab31..8b04b95b7b7a 100644
--- a/drivers/iio/adc/berlin2-adc.c
+++ b/drivers/iio/adc/berlin2-adc.c
@@ -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;
diff --git a/drivers/iio/adc/cc10001_adc.c b/drivers/iio/adc/cc10001_adc.c
index fe9257624f16..e16ac935693b 100644
--- a/drivers/iio/adc/cc10001_adc.c
+++ b/drivers/iio/adc/cc10001_adc.c
@@ -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;
diff --git a/drivers/iio/adc/cpcap-adc.c b/drivers/iio/adc/cpcap-adc.c
index 5086a337f4c9..64c3cc382311 100644
--- a/drivers/iio/adc/cpcap-adc.c
+++ b/drivers/iio/adc/cpcap-adc.c
@@ -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>
@@ -82,7 +82,7 @@
#define CPCAP_ADC_MAX_RETRIES 5 /* Calibration */
-/**
+/*
* struct cpcap_adc_ato - timing settings for cpcap adc
*
* Unfortunately no cpcap documentation available, please document when
@@ -121,7 +121,7 @@ struct cpcap_adc {
bool done;
};
-/**
+/*
* enum cpcap_adc_channel - cpcap adc channels
*/
enum cpcap_adc_channel {
@@ -152,7 +152,7 @@ enum cpcap_adc_channel {
CPCAP_ADC_CHANNEL_NUM,
};
-/**
+/*
* enum cpcap_adc_timing - cpcap adc timing options
*
* CPCAP_ADC_TIMING_IMM seems to be immediate with no timings.
@@ -690,7 +690,7 @@ static void cpcap_adc_phase(struct cpcap_adc_request *req)
break;
case CPCAP_ADC_BATTI_PI17:
index = req->bank_index;
- /* fallthrough */
+ fallthrough;
default:
req->result += conv_tbl[index].cal_offset;
req->result += conv_tbl[index].align_offset;
@@ -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,
};
diff --git a/drivers/iio/adc/da9150-gpadc.c b/drivers/iio/adc/da9150-gpadc.c
index ae8bcc32f63d..7a7a54a7ed76 100644
--- a/drivers/iio/adc/da9150-gpadc.c
+++ b/drivers/iio/adc/da9150-gpadc.c
@@ -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;
diff --git a/drivers/iio/adc/dln2-adc.c b/drivers/iio/adc/dln2-adc.c
index 65c7c9329b1c..0d53ef18e045 100644
--- a/drivers/iio/adc/dln2-adc.c
+++ b/drivers/iio/adc/dln2-adc.c
@@ -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;
diff --git a/drivers/iio/adc/envelope-detector.c b/drivers/iio/adc/envelope-detector.c
index 28f3d6758eb5..2a4fd3bb64cf 100644
--- a/drivers/iio/adc/envelope-detector.c
+++ b/drivers/iio/adc/envelope-detector.c
@@ -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;
diff --git a/drivers/iio/adc/ep93xx_adc.c b/drivers/iio/adc/ep93xx_adc.c
index 5c97e8a511f2..c08ab3c6dfaf 100644
--- a/drivers/iio/adc/ep93xx_adc.c
+++ b/drivers/iio/adc/ep93xx_adc.c
@@ -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;
diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
index 22131a677445..7d23b6c33284 100644
--- a/drivers/iio/adc/exynos_adc.c
+++ b/drivers/iio/adc/exynos_adc.c
@@ -449,9 +449,6 @@ static void exynos_adc_exynos7_init_hw(struct exynos_adc *info)
{
u32 con1, con2;
- if (info->data->needs_adc_phy)
- regmap_write(info->pmu_map, info->data->phy_offset, 1);
-
con1 = ADC_V2_CON1_SOFT_RESET;
writel(con1, ADC_V2_CON1(info->regs));
@@ -531,8 +528,19 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
unsigned long timeout;
int ret;
- if (mask != IIO_CHAN_INFO_RAW)
+ if (mask == IIO_CHAN_INFO_SCALE) {
+ ret = regulator_get_voltage(info->vdd);
+ if (ret < 0)
+ return ret;
+
+ /* Regulator voltage is in uV, but need mV */
+ *val = ret / 1000;
+ *val2 = info->data->mask;
+
+ return IIO_VAL_FRACTIONAL;
+ } else if (mask != IIO_CHAN_INFO_RAW) {
return -EINVAL;
+ }
mutex_lock(&indio_dev->mlock);
reinit_completion(&info->completion);
@@ -683,6 +691,7 @@ static const struct iio_info exynos_adc_iio_info = {
.channel = _index, \
.address = _index, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE), \
.datasheet_name = _id, \
}
@@ -858,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;
diff --git a/drivers/iio/adc/fsl-imx25-gcq.c b/drivers/iio/adc/fsl-imx25-gcq.c
index fa71489195c6..8cb51cf7a816 100644
--- a/drivers/iio/adc/fsl-imx25-gcq.c
+++ b/drivers/iio/adc/fsl-imx25-gcq.c
@@ -294,7 +294,6 @@ static int mx25_gcq_probe(struct platform_device *pdev)
struct mx25_gcq_priv *priv;
struct mx25_tsadc *tsadc = dev_get_drvdata(pdev->dev.parent);
struct device *dev = &pdev->dev;
- struct resource *res;
void __iomem *mem;
int ret;
int i;
@@ -305,8 +304,7 @@ static int mx25_gcq_probe(struct platform_device *pdev)
priv = iio_priv(indio_dev);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- mem = devm_ioremap_resource(dev, res);
+ mem = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mem))
return PTR_ERR(mem);
@@ -352,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;
diff --git a/drivers/iio/adc/hi8435.c b/drivers/iio/adc/hi8435.c
index 8da45bf36d36..074c30970465 100644
--- a/drivers/iio/adc/hi8435.c
+++ b/drivers/iio/adc/hi8435.c
@@ -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,
diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
index c8686558429b..6a173531d355 100644
--- a/drivers/iio/adc/hx711.c
+++ b/drivers/iio/adc/hx711.c
@@ -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;
diff --git a/drivers/iio/adc/imx7d_adc.c b/drivers/iio/adc/imx7d_adc.c
index 2a2fbf788e95..4969a5f941e3 100644
--- a/drivers/iio/adc/imx7d_adc.c
+++ b/drivers/iio/adc/imx7d_adc.c
@@ -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;
diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c
index bdd7cba6f6b0..b573ec60a8b8 100644
--- a/drivers/iio/adc/ina2xx-adc.c
+++ b/drivers/iio/adc/ina2xx-adc.c
@@ -146,6 +146,11 @@ struct ina2xx_chip_info {
int range_vbus; /* Bus voltage maximum in V */
int pga_gain_vshunt; /* Shunt voltage PGA gain */
bool allow_async_readout;
+ /* data buffer needs space for channel data and timestamp */
+ struct {
+ u16 chan[4];
+ u64 ts __aligned(8);
+ } scan;
};
static const struct ina2xx_config ina2xx_config[] = {
@@ -273,7 +278,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 };
@@ -738,8 +743,6 @@ static int ina2xx_conversion_ready(struct iio_dev *indio_dev)
static int ina2xx_work_buffer(struct iio_dev *indio_dev)
{
struct ina2xx_chip_info *chip = iio_priv(indio_dev);
- /* data buffer needs space for channel data and timestap */
- unsigned short data[4 + sizeof(s64)/sizeof(short)];
int bit, ret, i = 0;
s64 time;
@@ -758,10 +761,10 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev)
if (ret < 0)
return ret;
- data[i++] = val;
+ chip->scan.chan[i++] = val;
}
- iio_push_to_buffers_with_timestamp(indio_dev, data, time);
+ iio_push_to_buffers_with_timestamp(indio_dev, &chip->scan, time);
return 0;
};
@@ -1015,8 +1018,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);
diff --git a/drivers/iio/adc/ingenic-adc.c b/drivers/iio/adc/ingenic-adc.c
index 39c0a609fc94..92b25083e23f 100644
--- a/drivers/iio/adc/ingenic-adc.c
+++ b/drivers/iio/adc/ingenic-adc.c
@@ -8,11 +8,14 @@
#include <dt-bindings/iio/adc/ingenic,adc.h>
#include <linux/clk.h>
+#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
+#include <linux/interrupt.h>
#include <linux/io.h>
#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>
@@ -20,19 +23,46 @@
#define JZ_ADC_REG_CFG 0x04
#define JZ_ADC_REG_CTRL 0x08
#define JZ_ADC_REG_STATUS 0x0c
+#define JZ_ADC_REG_ADSAME 0x10
+#define JZ_ADC_REG_ADWAIT 0x14
#define JZ_ADC_REG_ADTCH 0x18
#define JZ_ADC_REG_ADBDAT 0x1c
#define JZ_ADC_REG_ADSDAT 0x20
+#define JZ_ADC_REG_ADCMD 0x24
#define JZ_ADC_REG_ADCLK 0x28
#define JZ_ADC_REG_ENABLE_PD BIT(7)
#define JZ_ADC_REG_CFG_AUX_MD (BIT(0) | BIT(1))
#define JZ_ADC_REG_CFG_BAT_MD BIT(4)
+#define JZ_ADC_REG_CFG_SAMPLE_NUM(n) ((n) << 10)
+#define JZ_ADC_REG_CFG_PULL_UP(n) ((n) << 16)
+#define JZ_ADC_REG_CFG_CMD_SEL BIT(22)
+#define JZ_ADC_REG_CFG_TOUCH_OPS_MASK (BIT(31) | GENMASK(23, 10))
#define JZ_ADC_REG_ADCLK_CLKDIV_LSB 0
#define JZ4725B_ADC_REG_ADCLK_CLKDIV10US_LSB 16
#define JZ4770_ADC_REG_ADCLK_CLKDIV10US_LSB 8
#define JZ4770_ADC_REG_ADCLK_CLKDIVMS_LSB 16
+#define JZ_ADC_REG_ADCMD_YNADC BIT(7)
+#define JZ_ADC_REG_ADCMD_YPADC BIT(8)
+#define JZ_ADC_REG_ADCMD_XNADC BIT(9)
+#define JZ_ADC_REG_ADCMD_XPADC BIT(10)
+#define JZ_ADC_REG_ADCMD_VREFPYP BIT(11)
+#define JZ_ADC_REG_ADCMD_VREFPXP BIT(12)
+#define JZ_ADC_REG_ADCMD_VREFPXN BIT(13)
+#define JZ_ADC_REG_ADCMD_VREFPAUX BIT(14)
+#define JZ_ADC_REG_ADCMD_VREFPVDD33 BIT(15)
+#define JZ_ADC_REG_ADCMD_VREFNYN BIT(16)
+#define JZ_ADC_REG_ADCMD_VREFNXP BIT(17)
+#define JZ_ADC_REG_ADCMD_VREFNXN BIT(18)
+#define JZ_ADC_REG_ADCMD_VREFAUX BIT(19)
+#define JZ_ADC_REG_ADCMD_YNGRU BIT(20)
+#define JZ_ADC_REG_ADCMD_XNGRU BIT(21)
+#define JZ_ADC_REG_ADCMD_XPGRU BIT(22)
+#define JZ_ADC_REG_ADCMD_YPSUP BIT(23)
+#define JZ_ADC_REG_ADCMD_XNSUP BIT(24)
+#define JZ_ADC_REG_ADCMD_XPSUP BIT(25)
+
#define JZ_ADC_AUX_VREF 3300
#define JZ_ADC_AUX_VREF_BITS 12
#define JZ_ADC_BATTERY_LOW_VREF 2500
@@ -44,6 +74,14 @@
#define JZ4770_ADC_BATTERY_VREF 6600
#define JZ4770_ADC_BATTERY_VREF_BITS 12
+#define JZ_ADC_IRQ_AUX BIT(0)
+#define JZ_ADC_IRQ_BATTERY BIT(1)
+#define JZ_ADC_IRQ_TOUCH BIT(2)
+#define JZ_ADC_IRQ_PEN_DOWN BIT(3)
+#define JZ_ADC_IRQ_PEN_UP BIT(4)
+#define JZ_ADC_IRQ_PEN_DOWN_SLEEP BIT(5)
+#define JZ_ADC_IRQ_SLEEP BIT(7)
+
struct ingenic_adc;
struct ingenic_adc_soc_data {
@@ -55,6 +93,8 @@ struct ingenic_adc_soc_data {
size_t battery_scale_avail_size;
unsigned int battery_vref_mode: 1;
unsigned int has_aux2: 1;
+ const struct iio_chan_spec *channels;
+ unsigned int num_channels;
int (*init_clk_div)(struct device *dev, struct ingenic_adc *adc);
};
@@ -67,13 +107,67 @@ struct ingenic_adc {
bool low_vref_mode;
};
+static void ingenic_adc_set_adcmd(struct iio_dev *iio_dev, unsigned long mask)
+{
+ struct ingenic_adc *adc = iio_priv(iio_dev);
+
+ mutex_lock(&adc->lock);
+
+ /* Init ADCMD */
+ readl(adc->base + JZ_ADC_REG_ADCMD);
+
+ if (mask & 0x3) {
+ /* Second channel (INGENIC_ADC_TOUCH_YP): sample YP vs. GND */
+ writel(JZ_ADC_REG_ADCMD_XNGRU
+ | JZ_ADC_REG_ADCMD_VREFNXN | JZ_ADC_REG_ADCMD_VREFPVDD33
+ | JZ_ADC_REG_ADCMD_YPADC,
+ adc->base + JZ_ADC_REG_ADCMD);
+
+ /* First channel (INGENIC_ADC_TOUCH_XP): sample XP vs. GND */
+ writel(JZ_ADC_REG_ADCMD_YNGRU
+ | JZ_ADC_REG_ADCMD_VREFNYN | JZ_ADC_REG_ADCMD_VREFPVDD33
+ | JZ_ADC_REG_ADCMD_XPADC,
+ adc->base + JZ_ADC_REG_ADCMD);
+ }
+
+ if (mask & 0xc) {
+ /* Fourth channel (INGENIC_ADC_TOUCH_YN): sample YN vs. GND */
+ writel(JZ_ADC_REG_ADCMD_XNGRU
+ | JZ_ADC_REG_ADCMD_VREFNXN | JZ_ADC_REG_ADCMD_VREFPVDD33
+ | JZ_ADC_REG_ADCMD_YNADC,
+ adc->base + JZ_ADC_REG_ADCMD);
+
+ /* Third channel (INGENIC_ADC_TOUCH_XN): sample XN vs. GND */
+ writel(JZ_ADC_REG_ADCMD_YNGRU
+ | JZ_ADC_REG_ADCMD_VREFNYN | JZ_ADC_REG_ADCMD_VREFPVDD33
+ | JZ_ADC_REG_ADCMD_XNADC,
+ adc->base + JZ_ADC_REG_ADCMD);
+ }
+
+ if (mask & 0x30) {
+ /* Sixth channel (INGENIC_ADC_TOUCH_YD): sample YP vs. YN */
+ writel(JZ_ADC_REG_ADCMD_VREFNYN | JZ_ADC_REG_ADCMD_VREFPVDD33
+ | JZ_ADC_REG_ADCMD_YPADC,
+ adc->base + JZ_ADC_REG_ADCMD);
+
+ /* Fifth channel (INGENIC_ADC_TOUCH_XD): sample XP vs. XN */
+ writel(JZ_ADC_REG_ADCMD_VREFNXN | JZ_ADC_REG_ADCMD_VREFPVDD33
+ | JZ_ADC_REG_ADCMD_XPADC,
+ adc->base + JZ_ADC_REG_ADCMD);
+ }
+
+ /* We're done */
+ writel(0, adc->base + JZ_ADC_REG_ADCMD);
+
+ mutex_unlock(&adc->lock);
+}
+
static void ingenic_adc_set_config(struct ingenic_adc *adc,
uint32_t mask,
uint32_t val)
{
uint32_t cfg;
- clk_enable(adc->clk);
mutex_lock(&adc->lock);
cfg = readl(adc->base + JZ_ADC_REG_CFG) & ~mask;
@@ -81,7 +175,6 @@ static void ingenic_adc_set_config(struct ingenic_adc *adc,
writel(cfg, adc->base + JZ_ADC_REG_CFG);
mutex_unlock(&adc->lock);
- clk_disable(adc->clk);
}
static void ingenic_adc_enable(struct ingenic_adc *adc,
@@ -124,6 +217,8 @@ static int ingenic_adc_write_raw(struct iio_dev *iio_dev,
long m)
{
struct ingenic_adc *adc = iio_priv(iio_dev);
+ struct device *dev = iio_dev->dev.parent;
+ int ret;
switch (m) {
case IIO_CHAN_INFO_SCALE:
@@ -131,6 +226,14 @@ static int ingenic_adc_write_raw(struct iio_dev *iio_dev,
case INGENIC_ADC_BATTERY:
if (!adc->soc_data->battery_vref_mode)
return -EINVAL;
+
+ ret = clk_enable(adc->clk);
+ if (ret) {
+ dev_err(dev, "Failed to enable clock: %d\n",
+ ret);
+ return ret;
+ }
+
if (val > JZ_ADC_BATTERY_LOW_VREF) {
ingenic_adc_set_config(adc,
JZ_ADC_REG_CFG_BAT_MD,
@@ -142,6 +245,9 @@ static int ingenic_adc_write_raw(struct iio_dev *iio_dev,
JZ_ADC_REG_CFG_BAT_MD);
adc->low_vref_mode = true;
}
+
+ clk_disable(adc->clk);
+
return 0;
default:
return -EINVAL;
@@ -251,6 +357,127 @@ static int jz4770_adc_init_clk_div(struct device *dev, struct ingenic_adc *adc)
return 0;
}
+static const struct iio_chan_spec jz4740_channels[] = {
+ {
+ .extend_name = "aux",
+ .type = IIO_VOLTAGE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .indexed = 1,
+ .channel = INGENIC_ADC_AUX,
+ .scan_index = -1,
+ },
+ {
+ .extend_name = "battery",
+ .type = IIO_VOLTAGE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .indexed = 1,
+ .channel = INGENIC_ADC_BATTERY,
+ .scan_index = -1,
+ },
+};
+
+static const struct iio_chan_spec jz4770_channels[] = {
+ {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = INGENIC_ADC_TOUCH_XP,
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ },
+ },
+ {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = INGENIC_ADC_TOUCH_YP,
+ .scan_index = 1,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ },
+ },
+ {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = INGENIC_ADC_TOUCH_XN,
+ .scan_index = 2,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ },
+ },
+ {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = INGENIC_ADC_TOUCH_YN,
+ .scan_index = 3,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ },
+ },
+ {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = INGENIC_ADC_TOUCH_XD,
+ .scan_index = 4,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ },
+ },
+ {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = INGENIC_ADC_TOUCH_YD,
+ .scan_index = 5,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ },
+ },
+ {
+ .extend_name = "aux",
+ .type = IIO_VOLTAGE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .indexed = 1,
+ .channel = INGENIC_ADC_AUX,
+ .scan_index = -1,
+ },
+ {
+ .extend_name = "battery",
+ .type = IIO_VOLTAGE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .indexed = 1,
+ .channel = INGENIC_ADC_BATTERY,
+ .scan_index = -1,
+ },
+ {
+ .extend_name = "aux2",
+ .type = IIO_VOLTAGE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .indexed = 1,
+ .channel = INGENIC_ADC_AUX2,
+ .scan_index = -1,
+ },
+};
+
static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = {
.battery_high_vref = JZ4725B_ADC_BATTERY_HIGH_VREF,
.battery_high_vref_bits = JZ4725B_ADC_BATTERY_HIGH_VREF_BITS,
@@ -260,6 +487,8 @@ static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = {
.battery_scale_avail_size = ARRAY_SIZE(jz4725b_adc_battery_scale_avail),
.battery_vref_mode = true,
.has_aux2 = false,
+ .channels = jz4740_channels,
+ .num_channels = ARRAY_SIZE(jz4740_channels),
.init_clk_div = jz4725b_adc_init_clk_div,
};
@@ -272,6 +501,8 @@ static const struct ingenic_adc_soc_data jz4740_adc_soc_data = {
.battery_scale_avail_size = ARRAY_SIZE(jz4740_adc_battery_scale_avail),
.battery_vref_mode = true,
.has_aux2 = false,
+ .channels = jz4740_channels,
+ .num_channels = ARRAY_SIZE(jz4740_channels),
.init_clk_div = NULL, /* no ADCLK register on JZ4740 */
};
@@ -284,6 +515,8 @@ static const struct ingenic_adc_soc_data jz4770_adc_soc_data = {
.battery_scale_avail_size = ARRAY_SIZE(jz4770_adc_battery_scale_avail),
.battery_vref_mode = false,
.has_aux2 = true,
+ .channels = jz4770_channels,
+ .num_channels = ARRAY_SIZE(jz4770_channels),
.init_clk_div = jz4770_adc_init_clk_div,
};
@@ -312,11 +545,19 @@ static int ingenic_adc_read_avail(struct iio_dev *iio_dev,
};
}
-static int ingenic_adc_read_chan_info_raw(struct ingenic_adc *adc,
+static int ingenic_adc_read_chan_info_raw(struct iio_dev *iio_dev,
struct iio_chan_spec const *chan,
int *val)
{
int bit, ret, engine = (chan->channel == INGENIC_ADC_BATTERY);
+ struct ingenic_adc *adc = iio_priv(iio_dev);
+
+ ret = clk_enable(adc->clk);
+ if (ret) {
+ dev_err(iio_dev->dev.parent, "Failed to enable clock: %d\n",
+ ret);
+ return ret;
+ }
/* We cannot sample AUX/AUX2 in parallel. */
mutex_lock(&adc->aux_lock);
@@ -325,7 +566,6 @@ static int ingenic_adc_read_chan_info_raw(struct ingenic_adc *adc,
ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_AUX_MD, bit);
}
- clk_enable(adc->clk);
ret = ingenic_adc_capture(adc, engine);
if (ret)
goto out;
@@ -342,8 +582,8 @@ static int ingenic_adc_read_chan_info_raw(struct ingenic_adc *adc,
ret = IIO_VAL_INT;
out:
- clk_disable(adc->clk);
mutex_unlock(&adc->aux_lock);
+ clk_disable(adc->clk);
return ret;
}
@@ -358,7 +598,7 @@ static int ingenic_adc_read_raw(struct iio_dev *iio_dev,
switch (m) {
case IIO_CHAN_INFO_RAW:
- return ingenic_adc_read_chan_info_raw(adc, chan, val);
+ return ingenic_adc_read_chan_info_raw(iio_dev, chan, val);
case IIO_CHAN_INFO_SCALE:
switch (chan->channel) {
case INGENIC_ADC_AUX:
@@ -383,6 +623,21 @@ static int ingenic_adc_read_raw(struct iio_dev *iio_dev,
}
}
+static int ingenic_adc_of_xlate(struct iio_dev *iio_dev,
+ const struct of_phandle_args *iiospec)
+{
+ int i;
+
+ if (!iiospec->args_count)
+ return -EINVAL;
+
+ for (i = 0; i < iio_dev->num_channels; ++i)
+ if (iio_dev->channels[i].channel == iiospec->args[0])
+ return i;
+
+ return -EINVAL;
+}
+
static void ingenic_adc_clk_cleanup(void *data)
{
clk_unprepare(data);
@@ -392,44 +647,92 @@ static const struct iio_info ingenic_adc_info = {
.write_raw = ingenic_adc_write_raw,
.read_raw = ingenic_adc_read_raw,
.read_avail = ingenic_adc_read_avail,
+ .of_xlate = ingenic_adc_of_xlate,
};
-static const struct iio_chan_spec ingenic_channels[] = {
- {
- .extend_name = "aux",
- .type = IIO_VOLTAGE,
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
- BIT(IIO_CHAN_INFO_SCALE),
- .indexed = 1,
- .channel = INGENIC_ADC_AUX,
- },
- {
- .extend_name = "battery",
- .type = IIO_VOLTAGE,
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
- BIT(IIO_CHAN_INFO_SCALE),
- .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW) |
- BIT(IIO_CHAN_INFO_SCALE),
- .indexed = 1,
- .channel = INGENIC_ADC_BATTERY,
- },
- { /* Must always be last in the array. */
- .extend_name = "aux2",
- .type = IIO_VOLTAGE,
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
- BIT(IIO_CHAN_INFO_SCALE),
- .indexed = 1,
- .channel = INGENIC_ADC_AUX2,
- },
+static int ingenic_adc_buffer_enable(struct iio_dev *iio_dev)
+{
+ struct ingenic_adc *adc = iio_priv(iio_dev);
+ int ret;
+
+ ret = clk_enable(adc->clk);
+ if (ret) {
+ dev_err(iio_dev->dev.parent, "Failed to enable clock: %d\n",
+ ret);
+ return ret;
+ }
+
+ /* It takes significant time for the touchscreen hw to stabilize. */
+ msleep(50);
+ ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_TOUCH_OPS_MASK,
+ JZ_ADC_REG_CFG_SAMPLE_NUM(4) |
+ JZ_ADC_REG_CFG_PULL_UP(4));
+
+ writew(80, adc->base + JZ_ADC_REG_ADWAIT);
+ writew(2, adc->base + JZ_ADC_REG_ADSAME);
+ writeb((u8)~JZ_ADC_IRQ_TOUCH, adc->base + JZ_ADC_REG_CTRL);
+ writel(0, adc->base + JZ_ADC_REG_ADTCH);
+
+ ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_CMD_SEL,
+ JZ_ADC_REG_CFG_CMD_SEL);
+ ingenic_adc_set_adcmd(iio_dev, iio_dev->active_scan_mask[0]);
+
+ ingenic_adc_enable(adc, 2, true);
+
+ return 0;
+}
+
+static int ingenic_adc_buffer_disable(struct iio_dev *iio_dev)
+{
+ struct ingenic_adc *adc = iio_priv(iio_dev);
+
+ ingenic_adc_enable(adc, 2, false);
+
+ ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_CMD_SEL, 0);
+
+ writeb(0xff, adc->base + JZ_ADC_REG_CTRL);
+ writeb(0xff, adc->base + JZ_ADC_REG_STATUS);
+ ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_TOUCH_OPS_MASK, 0);
+ writew(0, adc->base + JZ_ADC_REG_ADSAME);
+ writew(0, adc->base + JZ_ADC_REG_ADWAIT);
+ clk_disable(adc->clk);
+
+ return 0;
+}
+
+static const struct iio_buffer_setup_ops ingenic_buffer_setup_ops = {
+ .postenable = &ingenic_adc_buffer_enable,
+ .predisable = &ingenic_adc_buffer_disable
};
+static irqreturn_t ingenic_adc_irq(int irq, void *data)
+{
+ struct iio_dev *iio_dev = data;
+ struct ingenic_adc *adc = iio_priv(iio_dev);
+ unsigned long mask = iio_dev->active_scan_mask[0];
+ unsigned int i;
+ u32 tdat[3];
+
+ for (i = 0; i < ARRAY_SIZE(tdat); mask >>= 2, i++) {
+ if (mask & 0x3)
+ tdat[i] = readl(adc->base + JZ_ADC_REG_ADTCH);
+ else
+ tdat[i] = 0;
+ }
+
+ iio_push_to_buffers(iio_dev, tdat);
+ writeb(JZ_ADC_IRQ_TOUCH, adc->base + JZ_ADC_REG_STATUS);
+
+ return IRQ_HANDLED;
+}
+
static int ingenic_adc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct iio_dev *iio_dev;
struct ingenic_adc *adc;
const struct ingenic_adc_soc_data *soc_data;
- int ret;
+ int irq, ret;
soc_data = device_get_match_data(dev);
if (!soc_data)
@@ -444,6 +747,17 @@ static int ingenic_adc_probe(struct platform_device *pdev)
mutex_init(&adc->aux_lock);
adc->soc_data = soc_data;
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ ret = devm_request_irq(dev, irq, ingenic_adc_irq, 0,
+ dev_name(dev), iio_dev);
+ if (ret < 0) {
+ dev_err(dev, "Failed to request irq: %d\n", ret);
+ return ret;
+ }
+
adc->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(adc->base))
return PTR_ERR(adc->base);
@@ -481,14 +795,11 @@ 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;
- iio_dev->num_channels = ARRAY_SIZE(ingenic_channels);
- /* Remove AUX2 from the list of supported channels. */
- if (!adc->soc_data->has_aux2)
- iio_dev->num_channels -= 1;
+ iio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
+ iio_dev->setup_ops = &ingenic_buffer_setup_ops;
+ iio_dev->channels = soc_data->channels;
+ iio_dev->num_channels = soc_data->num_channels;
iio_dev->info = &ingenic_adc_info;
ret = devm_iio_device_register(dev, iio_dev);
@@ -498,7 +809,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 +816,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,
};
diff --git a/drivers/iio/adc/intel_mrfld_adc.c b/drivers/iio/adc/intel_mrfld_adc.c
index c35a1beb817c..75394350eb4c 100644
--- a/drivers/iio/adc/intel_mrfld_adc.c
+++ b/drivers/iio/adc/intel_mrfld_adc.c
@@ -75,7 +75,7 @@ static int mrfld_adc_single_conv(struct iio_dev *indio_dev,
struct regmap *regmap = adc->regmap;
unsigned int req;
long timeout;
- u8 buf[2];
+ __be16 value;
int ret;
reinit_completion(&adc->completion);
@@ -105,11 +105,11 @@ static int mrfld_adc_single_conv(struct iio_dev *indio_dev,
goto done;
}
- ret = regmap_bulk_read(regmap, chan->address, buf, 2);
+ ret = regmap_bulk_read(regmap, chan->address, &value, sizeof(value));
if (ret)
goto done;
- *result = get_unaligned_be16(buf);
+ *result = be16_to_cpu(value);
ret = IIO_VAL_INT;
done:
@@ -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;
diff --git a/drivers/iio/adc/lp8788_adc.c b/drivers/iio/adc/lp8788_adc.c
index c1fc1b678e0f..8fb57e375529 100644
--- a/drivers/iio/adc/lp8788_adc.c
+++ b/drivers/iio/adc/lp8788_adc.c
@@ -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;
diff --git a/drivers/iio/adc/lpc18xx_adc.c b/drivers/iio/adc/lpc18xx_adc.c
index 4c6ac6644dc0..3566990ae87d 100644
--- a/drivers/iio/adc/lpc18xx_adc.c
+++ b/drivers/iio/adc/lpc18xx_adc.c
@@ -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;
diff --git a/drivers/iio/adc/lpc32xx_adc.c b/drivers/iio/adc/lpc32xx_adc.c
index b896f7ff4572..b56ce15255cf 100644
--- a/drivers/iio/adc/lpc32xx_adc.c
+++ b/drivers/iio/adc/lpc32xx_adc.c
@@ -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,
},
};
diff --git a/drivers/iio/adc/ltc2471.c b/drivers/iio/adc/ltc2471.c
index 55fab612843a..0e0fe881a8e6 100644
--- a/drivers/iio/adc/ltc2471.c
+++ b/drivers/iio/adc/ltc2471.c
@@ -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;
diff --git a/drivers/iio/adc/ltc2485.c b/drivers/iio/adc/ltc2485.c
index c418466d51fd..37c762f8218c 100644
--- a/drivers/iio/adc/ltc2485.c
+++ b/drivers/iio/adc/ltc2485.c
@@ -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;
diff --git a/drivers/iio/adc/ltc2496.c b/drivers/iio/adc/ltc2496.c
index 88a30156a849..dd956a7c216e 100644
--- a/drivers/iio/adc/ltc2496.c
+++ b/drivers/iio/adc/ltc2496.c
@@ -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,
diff --git a/drivers/iio/adc/ltc2497-core.c b/drivers/iio/adc/ltc2497-core.c
index f5f7039caacc..9b8fd9c32364 100644
--- a/drivers/iio/adc/ltc2497-core.c
+++ b/drivers/iio/adc/ltc2497-core.c
@@ -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;
diff --git a/drivers/iio/adc/ltc2497.c b/drivers/iio/adc/ltc2497.c
index 5db63d7c6bc5..1adddf5a88a9 100644
--- a/drivers/iio/adc/ltc2497.c
+++ b/drivers/iio/adc/ltc2497.c
@@ -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,
diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c
index 02834ca3e1ce..ca1dff3924ff 100644
--- a/drivers/iio/adc/max1027.c
+++ b/drivers/iio/adc/max1027.c
@@ -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,
diff --git a/drivers/iio/adc/max11100.c b/drivers/iio/adc/max11100.c
index 3440539cfdba..6cf21758ca66 100644
--- a/drivers/iio/adc/max11100.c
+++ b/drivers/iio/adc/max11100.c
@@ -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,
diff --git a/drivers/iio/adc/max1118.c b/drivers/iio/adc/max1118.c
index 0c5d7aaf6826..6efb0b43d938 100644
--- a/drivers/iio/adc/max1118.c
+++ b/drivers/iio/adc/max1118.c
@@ -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>
@@ -35,6 +36,11 @@ struct max1118 {
struct spi_device *spi;
struct mutex lock;
struct regulator *reg;
+ /* Ensure natural alignment of buffer elements */
+ struct {
+ u8 channels[2];
+ s64 ts __aligned(8);
+ } scan;
u8 data ____cacheline_aligned;
};
@@ -165,7 +171,6 @@ static irqreturn_t max1118_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct max1118 *adc = iio_priv(indio_dev);
- u8 data[16] = { }; /* 2x 8-bit ADC data + padding + 8 bytes timestamp */
int scan_index;
int i = 0;
@@ -183,10 +188,10 @@ static irqreturn_t max1118_trigger_handler(int irq, void *p)
goto out;
}
- data[i] = ret;
+ adc->scan.channels[i] = ret;
i++;
}
- iio_push_to_buffers_with_timestamp(indio_dev, data,
+ iio_push_to_buffers_with_timestamp(indio_dev, &adc->scan,
iio_get_time_ns(indio_dev));
out:
mutex_unlock(&adc->lock);
@@ -225,7 +230,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 +285,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 +293,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,
diff --git a/drivers/iio/adc/max1241.c b/drivers/iio/adc/max1241.c
new file mode 100644
index 000000000000..0cbbb3c56d08
--- /dev/null
+++ b/drivers/iio/adc/max1241.c
@@ -0,0 +1,226 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * MAX1241 low-power, 12-bit serial ADC
+ *
+ * Datasheet: https://datasheets.maximintegrated.com/en/ds/MAX1240-MAX1241.pdf
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+
+#define MAX1241_VAL_MASK GENMASK(11, 0)
+#define MAX1241_SHUTDOWN_DELAY_USEC 4
+
+enum max1241_id {
+ max1241,
+};
+
+struct max1241 {
+ struct spi_device *spi;
+ struct mutex lock;
+ struct regulator *vdd;
+ struct regulator *vref;
+ struct gpio_desc *shutdown;
+
+ __be16 data ____cacheline_aligned;
+};
+
+static const struct iio_chan_spec max1241_channels[] = {
+ {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ },
+};
+
+static int max1241_read(struct max1241 *adc)
+{
+ struct spi_transfer xfers[] = {
+ /*
+ * Begin conversion by bringing /CS low for at least
+ * tconv us.
+ */
+ {
+ .len = 0,
+ .delay.value = 8,
+ .delay.unit = SPI_DELAY_UNIT_USECS,
+ },
+ /*
+ * Then read two bytes of data in our RX buffer.
+ */
+ {
+ .rx_buf = &adc->data,
+ .len = 2,
+ },
+ };
+
+ return spi_sync_transfer(adc->spi, xfers, ARRAY_SIZE(xfers));
+}
+
+static int max1241_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ int ret, vref_uV;
+ struct max1241 *adc = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ mutex_lock(&adc->lock);
+
+ if (adc->shutdown) {
+ gpiod_set_value(adc->shutdown, 0);
+ udelay(MAX1241_SHUTDOWN_DELAY_USEC);
+ ret = max1241_read(adc);
+ gpiod_set_value(adc->shutdown, 1);
+ } else
+ ret = max1241_read(adc);
+
+ if (ret) {
+ mutex_unlock(&adc->lock);
+ return ret;
+ }
+
+ *val = (be16_to_cpu(adc->data) >> 3) & MAX1241_VAL_MASK;
+
+ mutex_unlock(&adc->lock);
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ vref_uV = regulator_get_voltage(adc->vref);
+
+ if (vref_uV < 0)
+ return vref_uV;
+
+ *val = vref_uV / 1000;
+ *val2 = 12;
+
+ return IIO_VAL_FRACTIONAL_LOG2;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info max1241_info = {
+ .read_raw = max1241_read_raw,
+};
+
+static void max1241_disable_vdd_action(void *data)
+{
+ struct max1241 *adc = data;
+ struct device *dev = &adc->spi->dev;
+ int err;
+
+ err = regulator_disable(adc->vdd);
+ if (err)
+ dev_err(dev, "could not disable vdd regulator.\n");
+}
+
+static void max1241_disable_vref_action(void *data)
+{
+ struct max1241 *adc = data;
+ struct device *dev = &adc->spi->dev;
+ int err;
+
+ err = regulator_disable(adc->vref);
+ if (err)
+ dev_err(dev, "could not disable vref regulator.\n");
+}
+
+static int max1241_probe(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct iio_dev *indio_dev;
+ struct max1241 *adc;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*adc));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ adc = iio_priv(indio_dev);
+ adc->spi = spi;
+ mutex_init(&adc->lock);
+
+ spi_set_drvdata(spi, indio_dev);
+
+ adc->vdd = devm_regulator_get(dev, "vdd");
+ if (IS_ERR(adc->vdd)) {
+ dev_err(dev, "failed to get vdd regulator\n");
+ return PTR_ERR(adc->vdd);
+ }
+
+ ret = regulator_enable(adc->vdd);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(dev, max1241_disable_vdd_action, adc);
+ if (ret) {
+ dev_err(dev, "could not set up vdd regulator cleanup action\n");
+ return ret;
+ }
+
+ adc->vref = devm_regulator_get(dev, "vref");
+ if (IS_ERR(adc->vref)) {
+ dev_err(dev, "failed to get vref regulator\n");
+ return PTR_ERR(adc->vref);
+ }
+
+ ret = regulator_enable(adc->vref);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(dev, max1241_disable_vref_action, adc);
+ if (ret) {
+ dev_err(dev, "could not set up vref regulator cleanup action\n");
+ return ret;
+ }
+
+ adc->shutdown = devm_gpiod_get_optional(dev, "shutdown",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(adc->shutdown))
+ return PTR_ERR(adc->shutdown);
+
+ if (adc->shutdown)
+ dev_dbg(dev, "shutdown pin passed, low-power mode enabled");
+ else
+ dev_dbg(dev, "no shutdown pin passed, low-power mode disabled");
+
+ indio_dev->name = spi_get_device_id(spi)->name;
+ indio_dev->info = &max1241_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = max1241_channels;
+ indio_dev->num_channels = ARRAY_SIZE(max1241_channels);
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+
+static const struct spi_device_id max1241_id[] = {
+ { "max1241", max1241 },
+ {}
+};
+
+static const struct of_device_id max1241_dt_ids[] = {
+ { .compatible = "maxim,max1241" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, max1241_dt_ids);
+
+static struct spi_driver max1241_spi_driver = {
+ .driver = {
+ .name = "max1241",
+ .of_match_table = max1241_dt_ids,
+ },
+ .probe = max1241_probe,
+ .id_table = max1241_id,
+};
+module_spi_driver(max1241_spi_driver);
+
+MODULE_AUTHOR("Alexandru Lazar <alazar@startmail.com>");
+MODULE_DESCRIPTION("MAX1241 ADC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c
index 5c2cc61b666e..f2b576c69949 100644
--- a/drivers/iio/adc/max1363.c
+++ b/drivers/iio/adc/max1363.c
@@ -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>
@@ -150,6 +150,7 @@ struct max1363_chip_info {
* @current_mode: the scan mode of this chip
* @requestedmask: a valid requested set of channels
* @reg: supply regulator
+ * @lock: lock to ensure state is consistent
* @monitor_on: whether monitor mode is enabled
* @monitor_speed: parameter corresponding to device monitor speed setting
* @mask_high: bitmask for enabled high thresholds
@@ -169,6 +170,7 @@ struct max1363_state {
const struct max1363_mode *current_mode;
u32 requestedmask;
struct regulator *reg;
+ struct mutex lock;
/* Using monitor modes and buffer at the same time is
currently not supported */
@@ -364,7 +366,11 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev,
struct max1363_state *st = iio_priv(indio_dev);
struct i2c_client *client = st->client;
- mutex_lock(&indio_dev->mlock);
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+ mutex_lock(&st->lock);
+
/*
* If monitor mode is enabled, the method for reading a single
* channel will have to be rather different and has not yet
@@ -372,7 +378,7 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev,
*
* Also, cannot read directly if buffered capture enabled.
*/
- if (st->monitor_on || iio_buffer_enabled(indio_dev)) {
+ if (st->monitor_on) {
ret = -EBUSY;
goto error_ret;
}
@@ -404,8 +410,10 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev,
data = rxbuf[0];
}
*val = data;
+
error_ret:
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
+ iio_device_release_direct_mode(indio_dev);
return ret;
}
@@ -705,9 +713,9 @@ static ssize_t max1363_monitor_store_freq(struct device *dev,
if (!found)
return -EINVAL;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
st->monitor_speed = i;
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return 0;
}
@@ -810,12 +818,12 @@ static int max1363_read_event_config(struct iio_dev *indio_dev,
int val;
int number = chan->channel;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
if (dir == IIO_EV_DIR_FALLING)
val = (1 << number) & st->mask_low;
else
val = (1 << number) & st->mask_high;
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return val;
}
@@ -962,7 +970,11 @@ static int max1363_write_event_config(struct iio_dev *indio_dev,
u16 unifiedmask;
int number = chan->channel;
- mutex_lock(&indio_dev->mlock);
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+ mutex_lock(&st->lock);
+
unifiedmask = st->mask_low | st->mask_high;
if (dir == IIO_EV_DIR_FALLING) {
@@ -989,7 +1001,8 @@ static int max1363_write_event_config(struct iio_dev *indio_dev,
max1363_monitor_mode_update(st, !!(st->mask_high | st->mask_low));
error_ret:
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
+ iio_device_release_direct_mode(indio_dev);
return ret;
}
@@ -1516,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], \
@@ -1565,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)
@@ -1580,13 +1590,13 @@ 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;
st = iio_priv(indio_dev);
+ mutex_init(&st->lock);
st->reg = devm_regulator_get(&client->dev, "vcc");
if (IS_ERR(st->reg)) {
ret = PTR_ERR(st->reg);
@@ -1600,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;
@@ -1638,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;
@@ -1746,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,
diff --git a/drivers/iio/adc/max9611.c b/drivers/iio/adc/max9611.c
index 04d5ff7d2c8e..052ab23f10b2 100644
--- a/drivers/iio/adc/max9611.c
+++ b/drivers/iio/adc/max9611.c
@@ -110,7 +110,7 @@ enum max9611_conf_ids {
CONF_TEMP,
};
-/**
+/*
* max9611_mux_conf - associate ADC mux configuration with register address
* where data shall be read from
*/
@@ -133,7 +133,7 @@ enum max9611_csa_gain_params {
CSA_GAIN_OFFS_RAW,
};
-/**
+/*
* max9611_csa_gain_conf - associate gain multiplier with LSB and
* offset values.
*
@@ -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;
diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c
index 2c0eb5de110c..8d1cff28cae0 100644
--- a/drivers/iio/adc/mcp320x.c
+++ b/drivers/iio/adc/mcp320x.c
@@ -27,13 +27,13 @@
* 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,
diff --git a/drivers/iio/adc/mcp3422.c b/drivers/iio/adc/mcp3422.c
index ea24d7c58b12..da353dcb1e9d 100644
--- a/drivers/iio/adc/mcp3422.c
+++ b/drivers/iio/adc/mcp3422.c
@@ -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,10 @@
#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>
#include <linux/iio/sysfs.h>
@@ -95,16 +96,12 @@ static int mcp3422_update_config(struct mcp3422 *adc, u8 newconfig)
{
int ret;
- mutex_lock(&adc->lock);
-
ret = i2c_master_send(adc->i2c, &newconfig, 1);
if (ret > 0) {
adc->config = newconfig;
ret = 0;
}
- mutex_unlock(&adc->lock);
-
return ret;
}
@@ -117,11 +114,11 @@ static int mcp3422_read(struct mcp3422 *adc, int *value, u8 *config)
if (sample_rate == MCP3422_SRATE_3) {
ret = i2c_master_recv(adc->i2c, buf, 4);
- temp = buf[0] << 16 | buf[1] << 8 | buf[2];
+ temp = get_unaligned_be24(&buf[0]);
*config = buf[3];
} else {
ret = i2c_master_recv(adc->i2c, buf, 3);
- temp = buf[0] << 8 | buf[1];
+ temp = get_unaligned_be16(&buf[0]);
*config = buf[2];
}
@@ -137,6 +134,8 @@ static int mcp3422_read_channel(struct mcp3422 *adc,
u8 config;
u8 req_channel = channel->channel;
+ mutex_lock(&adc->lock);
+
if (req_channel != MCP3422_CHANNEL(adc->config)) {
config = adc->config;
config &= ~MCP3422_CHANNEL_MASK;
@@ -144,12 +143,18 @@ static int mcp3422_read_channel(struct mcp3422 *adc,
config &= ~MCP3422_PGA_MASK;
config |= MCP3422_PGA_VALUE(adc->pga[req_channel]);
ret = mcp3422_update_config(adc, config);
- if (ret < 0)
+ if (ret < 0) {
+ mutex_unlock(&adc->lock);
return ret;
+ }
msleep(mcp3422_read_times[MCP3422_SAMPLE_RATE(adc->config)]);
}
- return mcp3422_read(adc, value, &config);
+ ret = mcp3422_read(adc, value, &config);
+
+ mutex_unlock(&adc->lock);
+
+ return ret;
}
static int mcp3422_read_raw(struct iio_dev *iio,
@@ -346,8 +351,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;
@@ -403,18 +406,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,
diff --git a/drivers/iio/adc/mcp3911.c b/drivers/iio/adc/mcp3911.c
index dd52f08ec82e..e573da5397bb 100644
--- a/drivers/iio/adc/mcp3911.c
+++ b/drivers/iio/adc/mcp3911.c
@@ -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;
diff --git a/drivers/iio/adc/men_z188_adc.c b/drivers/iio/adc/men_z188_adc.c
index 196c8226381e..42ea8bc7e780 100644
--- a/drivers/iio/adc/men_z188_adc.c
+++ b/drivers/iio/adc/men_z188_adc.c
@@ -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;
diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
index 22a470db9ef8..1a9189ba69ae 100644
--- a/drivers/iio/adc/meson_saradc.c
+++ b/drivers/iio/adc/meson_saradc.c
@@ -707,7 +707,7 @@ static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev)
size_t read_len;
int ret;
- temperature_calib = devm_nvmem_cell_get(&indio_dev->dev,
+ temperature_calib = devm_nvmem_cell_get(indio_dev->dev.parent,
"temperature_calib");
if (IS_ERR(temperature_calib)) {
ret = PTR_ERR(temperature_calib);
@@ -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;
diff --git a/drivers/iio/adc/mp2629_adc.c b/drivers/iio/adc/mp2629_adc.c
new file mode 100644
index 000000000000..331a9a728217
--- /dev/null
+++ b/drivers/iio/adc/mp2629_adc.c
@@ -0,0 +1,208 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * MP2629 Driver for ADC
+ *
+ * Copyright 2020 Monolithic Power Systems, Inc
+ *
+ * Author: Saravanan Sekar <sravanhome@gmail.com>
+ */
+
+#include <linux/iio/driver.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/machine.h>
+#include <linux/mfd/mp2629.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define MP2629_REG_ADC_CTRL 0x03
+#define MP2629_REG_BATT_VOLT 0x0e
+#define MP2629_REG_SYSTEM_VOLT 0x0f
+#define MP2629_REG_INPUT_VOLT 0x11
+#define MP2629_REG_BATT_CURRENT 0x12
+#define MP2629_REG_INPUT_CURRENT 0x13
+
+#define MP2629_ADC_START BIT(7)
+#define MP2629_ADC_CONTINUOUS BIT(6)
+
+#define MP2629_MAP(_mp, _mpc) IIO_MAP(#_mp, "mp2629_charger", "mp2629-"_mpc)
+
+#define MP2629_ADC_CHAN(_ch, _type) { \
+ .type = _type, \
+ .indexed = 1, \
+ .datasheet_name = #_ch, \
+ .channel = MP2629_ ## _ch, \
+ .address = MP2629_REG_ ## _ch, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+}
+
+struct mp2629_adc {
+ struct regmap *regmap;
+ struct device *dev;
+};
+
+static struct iio_chan_spec mp2629_channels[] = {
+ MP2629_ADC_CHAN(BATT_VOLT, IIO_VOLTAGE),
+ MP2629_ADC_CHAN(SYSTEM_VOLT, IIO_VOLTAGE),
+ MP2629_ADC_CHAN(INPUT_VOLT, IIO_VOLTAGE),
+ MP2629_ADC_CHAN(BATT_CURRENT, IIO_CURRENT),
+ MP2629_ADC_CHAN(INPUT_CURRENT, IIO_CURRENT)
+};
+
+static struct iio_map mp2629_adc_maps[] = {
+ MP2629_MAP(BATT_VOLT, "batt-volt"),
+ MP2629_MAP(SYSTEM_VOLT, "system-volt"),
+ MP2629_MAP(INPUT_VOLT, "input-volt"),
+ MP2629_MAP(BATT_CURRENT, "batt-current"),
+ MP2629_MAP(INPUT_CURRENT, "input-current")
+};
+
+static int mp2629_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct mp2629_adc *info = iio_priv(indio_dev);
+ unsigned int rval;
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ ret = regmap_read(info->regmap, chan->address, &rval);
+ if (ret)
+ return ret;
+
+ if (chan->address == MP2629_INPUT_VOLT)
+ rval &= GENMASK(6, 0);
+ *val = rval;
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->channel) {
+ case MP2629_BATT_VOLT:
+ case MP2629_SYSTEM_VOLT:
+ *val = 20;
+ return IIO_VAL_INT;
+
+ case MP2629_INPUT_VOLT:
+ *val = 60;
+ return IIO_VAL_INT;
+
+ case MP2629_BATT_CURRENT:
+ *val = 175;
+ *val2 = 10;
+ return IIO_VAL_FRACTIONAL;
+
+ case MP2629_INPUT_CURRENT:
+ *val = 133;
+ *val2 = 10;
+ return IIO_VAL_FRACTIONAL;
+
+ default:
+ return -EINVAL;
+ }
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info mp2629_adc_info = {
+ .read_raw = &mp2629_read_raw,
+};
+
+static int mp2629_adc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mp2629_data *ddata = dev_get_drvdata(dev->parent);
+ struct mp2629_adc *info;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*info));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ info = iio_priv(indio_dev);
+ info->regmap = ddata->regmap;
+ info->dev = dev;
+ platform_set_drvdata(pdev, indio_dev);
+
+ ret = regmap_update_bits(info->regmap, MP2629_REG_ADC_CTRL,
+ MP2629_ADC_START | MP2629_ADC_CONTINUOUS,
+ MP2629_ADC_START | MP2629_ADC_CONTINUOUS);
+ if (ret) {
+ dev_err(dev, "adc enable fail: %d\n", ret);
+ return ret;
+ }
+
+ ret = iio_map_array_register(indio_dev, mp2629_adc_maps);
+ if (ret) {
+ dev_err(dev, "IIO maps register fail: %d\n", ret);
+ goto fail_disable;
+ }
+
+ indio_dev->name = "mp2629-adc";
+ indio_dev->dev.parent = dev;
+ indio_dev->channels = mp2629_channels;
+ indio_dev->num_channels = ARRAY_SIZE(mp2629_channels);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &mp2629_adc_info;
+
+ ret = iio_device_register(indio_dev);
+ if (ret) {
+ dev_err(dev, "IIO device register fail: %d\n", ret);
+ goto fail_map_unregister;
+ }
+
+ return 0;
+
+fail_map_unregister:
+ iio_map_array_unregister(indio_dev);
+
+fail_disable:
+ regmap_update_bits(info->regmap, MP2629_REG_ADC_CTRL,
+ MP2629_ADC_CONTINUOUS, 0);
+ regmap_update_bits(info->regmap, MP2629_REG_ADC_CTRL,
+ MP2629_ADC_START, 0);
+
+ return ret;
+}
+
+static int mp2629_adc_remove(struct platform_device *pdev)
+{
+ struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+ struct mp2629_adc *info = iio_priv(indio_dev);
+
+ iio_device_unregister(indio_dev);
+
+ iio_map_array_unregister(indio_dev);
+
+ regmap_update_bits(info->regmap, MP2629_REG_ADC_CTRL,
+ MP2629_ADC_CONTINUOUS, 0);
+ regmap_update_bits(info->regmap, MP2629_REG_ADC_CTRL,
+ MP2629_ADC_START, 0);
+
+ return 0;
+}
+
+static const struct of_device_id mp2629_adc_of_match[] = {
+ { .compatible = "mps,mp2629_adc"},
+ {}
+};
+MODULE_DEVICE_TABLE(of, mp2629_adc_of_match);
+
+static struct platform_driver mp2629_adc_driver = {
+ .driver = {
+ .name = "mp2629_adc",
+ .of_match_table = mp2629_adc_of_match,
+ },
+ .probe = mp2629_adc_probe,
+ .remove = mp2629_adc_remove,
+};
+module_platform_driver(mp2629_adc_driver);
+
+MODULE_AUTHOR("Saravanan Sekar <sravanhome@gmail.com>");
+MODULE_DESCRIPTION("MP2629 ADC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/adc/mt6577_auxadc.c b/drivers/iio/adc/mt6577_auxadc.c
index a4776d924f3a..ac415cb089cd 100644
--- a/drivers/iio/adc/mt6577_auxadc.c
+++ b/drivers/iio/adc/mt6577_auxadc.c
@@ -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;
diff --git a/drivers/iio/adc/mxs-lradc-adc.c b/drivers/iio/adc/mxs-lradc-adc.c
index 9d2f74c2489a..30e29f44ebd2 100644
--- a/drivers/iio/adc/mxs-lradc-adc.c
+++ b/drivers/iio/adc/mxs-lradc-adc.c
@@ -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;
diff --git a/drivers/iio/adc/nau7802.c b/drivers/iio/adc/nau7802.c
index 572579139fba..07c85434b568 100644
--- a/drivers/iio/adc/nau7802.c
+++ b/drivers/iio/adc/nau7802.c
@@ -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;
diff --git a/drivers/iio/adc/npcm_adc.c b/drivers/iio/adc/npcm_adc.c
index 83bad2d5575d..d9d105920001 100644
--- a/drivers/iio/adc/npcm_adc.c
+++ b/drivers/iio/adc/npcm_adc.c
@@ -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;
diff --git a/drivers/iio/adc/palmas_gpadc.c b/drivers/iio/adc/palmas_gpadc.c
index 46e595eb889f..1ca6570be66a 100644
--- a/drivers/iio/adc/palmas_gpadc.c
+++ b/drivers/iio/adc/palmas_gpadc.c
@@ -76,7 +76,7 @@ static struct palmas_gpadc_info palmas_gpadc_info[] = {
PALMAS_ADC_INFO(IN15, 0, 0, 0, 0, INVALID, INVALID, true),
};
-/**
+/*
* struct palmas_gpadc - the palmas_gpadc structure
* @ch0_current: channel 0 current source setting
* 0: 0 uA
@@ -94,7 +94,6 @@ static struct palmas_gpadc_info palmas_gpadc_info[] = {
* This is the palmas_gpadc structure to store run-time information
* and pointers for this driver instance.
*/
-
struct palmas_gpadc {
struct device *dev;
struct palmas *palmas;
@@ -593,7 +592,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;
diff --git a/drivers/iio/adc/qcom-pm8xxx-xoadc.c b/drivers/iio/adc/qcom-pm8xxx-xoadc.c
index c599ffa45a04..7e108da7d255 100644
--- a/drivers/iio/adc/qcom-pm8xxx-xoadc.c
+++ b/drivers/iio/adc/qcom-pm8xxx-xoadc.c
@@ -120,7 +120,7 @@
#define ADC_ARB_USRP_DATA0 0x19D
#define ADC_ARB_USRP_DATA1 0x19C
-/**
+/*
* Physical channels which MUST exist on all PM variants in order to provide
* proper reference points for calibration.
*
@@ -388,6 +388,7 @@ struct pm8xxx_chan_info {
* struct pm8xxx_xoadc - state container for the XOADC
* @dev: pointer to device
* @map: regmap to access registers
+ * @variant: XOADC variant characteristics
* @vref: reference voltage regulator
* characteristics of the channels, and sensible default settings
* @nchans: number of channels, configured by the device tree
@@ -933,8 +934,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;
diff --git a/drivers/iio/adc/qcom-spmi-adc5.c b/drivers/iio/adc/qcom-spmi-adc5.c
index 21fdcde77883..c10aa28be70a 100644
--- a/drivers/iio/adc/qcom-spmi-adc5.c
+++ b/drivers/iio/adc/qcom-spmi-adc5.c
@@ -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.
@@ -79,6 +83,11 @@
#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;
@@ -786,7 +982,7 @@ static int adc5_probe(struct platform_device *pdev)
static struct platform_driver adc5_driver = {
.driver = {
- .name = "qcom-spmi-adc5.c",
+ .name = "qcom-spmi-adc5",
.of_match_table = adc5_match_table,
},
.probe = adc5_probe,
diff --git a/drivers/iio/adc/qcom-spmi-iadc.c b/drivers/iio/adc/qcom-spmi-iadc.c
index 46858eddf1c3..acbda6636dc5 100644
--- a/drivers/iio/adc/qcom-spmi-iadc.c
+++ b/drivers/iio/adc/qcom-spmi-iadc.c
@@ -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;
diff --git a/drivers/iio/adc/qcom-spmi-vadc.c b/drivers/iio/adc/qcom-spmi-vadc.c
index 203ad59da336..b0388f8a69f4 100644
--- a/drivers/iio/adc/qcom-spmi-vadc.c
+++ b/drivers/iio/adc/qcom-spmi-vadc.c
@@ -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;
diff --git a/drivers/iio/adc/qcom-vadc-common.c b/drivers/iio/adc/qcom-vadc-common.c
index 2bb78d1c4daa..5113aaa6ba67 100644
--- a/drivers/iio/adc/qcom-vadc-common.c
+++ b/drivers/iio/adc/qcom-vadc-common.c
@@ -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,
diff --git a/drivers/iio/adc/qcom-vadc-common.h b/drivers/iio/adc/qcom-vadc-common.h
index e074902a24cc..17b2fc4d8bf2 100644
--- a/drivers/iio/adc/qcom-vadc-common.h
+++ b/drivers/iio/adc/qcom-vadc-common.h
@@ -49,6 +49,14 @@
#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;
diff --git a/drivers/iio/adc/rcar-gyroadc.c b/drivers/iio/adc/rcar-gyroadc.c
index 63ce743ee7af..d2c1419e72a0 100644
--- a/drivers/iio/adc/rcar-gyroadc.c
+++ b/drivers/iio/adc/rcar-gyroadc.c
@@ -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;
diff --git a/drivers/iio/adc/rn5t618-adc.c b/drivers/iio/adc/rn5t618-adc.c
index f21027e4e26a..7010c4276947 100644
--- a/drivers/iio/adc/rn5t618-adc.c
+++ b/drivers/iio/adc/rn5t618-adc.c
@@ -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;
diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c
index 582ba047c4a6..1f3d7d639d37 100644
--- a/drivers/iio/adc/rockchip_saradc.c
+++ b/drivers/iio/adc/rockchip_saradc.c
@@ -15,7 +15,10 @@
#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,
@@ -183,7 +207,7 @@ static const struct of_device_id rockchip_saradc_match[] = {
};
MODULE_DEVICE_TABLE(of, rockchip_saradc_match);
-/**
+/*
* Reset SARADC Controller.
*/
static void rockchip_saradc_reset_controller(struct reset_control *reset)
@@ -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,
diff --git a/drivers/iio/adc/sc27xx_adc.c b/drivers/iio/adc/sc27xx_adc.c
index 66b387f9b36d..aa32a1f385e2 100644
--- a/drivers/iio/adc/sc27xx_adc.c
+++ b/drivers/iio/adc/sc27xx_adc.c
@@ -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;
diff --git a/drivers/iio/adc/sd_adc_modulator.c b/drivers/iio/adc/sd_adc_modulator.c
index 560d8c7d9d86..327cc2097f6c 100644
--- a/drivers/iio/adc/sd_adc_modulator.c
+++ b/drivers/iio/adc/sd_adc_modulator.c
@@ -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,
};
diff --git a/drivers/iio/adc/spear_adc.c b/drivers/iio/adc/spear_adc.c
index 0ad536494e8f..1bc986a7009d 100644
--- a/drivers/iio/adc/spear_adc.c
+++ b/drivers/iio/adc/spear_adc.c
@@ -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;
diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
index 2df88d2b880a..0e2068ec068b 100644
--- a/drivers/iio/adc/stm32-adc-core.c
+++ b/drivers/iio/adc/stm32-adc-core.c
@@ -65,12 +65,14 @@ struct stm32_adc_priv;
* @clk_sel: clock selection routine
* @max_clk_rate_hz: maximum analog clock rate (Hz, from datasheet)
* @has_syscfg: SYSCFG capability flags
+ * @num_irqs: number of interrupt lines
*/
struct stm32_adc_priv_cfg {
const struct stm32_adc_common_regs *regs;
int (*clk_sel)(struct platform_device *, struct stm32_adc_priv *);
u32 max_clk_rate_hz;
unsigned int has_syscfg;
+ unsigned int num_irqs;
};
/**
@@ -375,21 +377,15 @@ static int stm32_adc_irq_probe(struct platform_device *pdev,
struct device_node *np = pdev->dev.of_node;
unsigned int i;
- for (i = 0; i < STM32_ADC_MAX_ADCS; i++) {
+ /*
+ * Interrupt(s) must be provided, depending on the compatible:
+ * - stm32f4/h7 shares a common interrupt line.
+ * - stm32mp1, has one line per ADC
+ */
+ for (i = 0; i < priv->cfg->num_irqs; i++) {
priv->irq[i] = platform_get_irq(pdev, i);
- if (priv->irq[i] < 0) {
- /*
- * At least one interrupt must be provided, make others
- * optional:
- * - stm32f4/h7 shares a common interrupt.
- * - stm32mp1, has one line per ADC (either for ADC1,
- * ADC2 or both).
- */
- if (i && priv->irq[i] == -ENXIO)
- continue;
-
+ if (priv->irq[i] < 0)
return priv->irq[i];
- }
}
priv->domain = irq_domain_add_simple(np, STM32_ADC_MAX_ADCS, 0,
@@ -400,9 +396,7 @@ static int stm32_adc_irq_probe(struct platform_device *pdev,
return -ENOMEM;
}
- for (i = 0; i < STM32_ADC_MAX_ADCS; i++) {
- if (priv->irq[i] < 0)
- continue;
+ for (i = 0; i < priv->cfg->num_irqs; i++) {
irq_set_chained_handler(priv->irq[i], stm32_adc_irq_handler);
irq_set_handler_data(priv->irq[i], priv);
}
@@ -420,11 +414,8 @@ static void stm32_adc_irq_remove(struct platform_device *pdev,
irq_dispose_mapping(irq_find_mapping(priv->domain, hwirq));
irq_domain_remove(priv->domain);
- for (i = 0; i < STM32_ADC_MAX_ADCS; i++) {
- if (priv->irq[i] < 0)
- continue;
+ for (i = 0; i < priv->cfg->num_irqs; i++)
irq_set_chained_handler(priv->irq[i], NULL);
- }
}
static int stm32_adc_core_switches_supply_en(struct stm32_adc_priv *priv,
@@ -817,6 +808,7 @@ static const struct stm32_adc_priv_cfg stm32f4_adc_priv_cfg = {
.regs = &stm32f4_adc_common_regs,
.clk_sel = stm32f4_adc_clk_sel,
.max_clk_rate_hz = 36000000,
+ .num_irqs = 1,
};
static const struct stm32_adc_priv_cfg stm32h7_adc_priv_cfg = {
@@ -824,6 +816,7 @@ static const struct stm32_adc_priv_cfg stm32h7_adc_priv_cfg = {
.clk_sel = stm32h7_adc_clk_sel,
.max_clk_rate_hz = 36000000,
.has_syscfg = HAS_VBOOSTER,
+ .num_irqs = 1,
};
static const struct stm32_adc_priv_cfg stm32mp1_adc_priv_cfg = {
@@ -831,6 +824,7 @@ static const struct stm32_adc_priv_cfg stm32mp1_adc_priv_cfg = {
.clk_sel = stm32h7_adc_clk_sel,
.max_clk_rate_hz = 40000000,
.has_syscfg = HAS_VBOOSTER | HAS_ANASWVDD,
+ .num_irqs = 2,
};
static const struct of_device_id stm32_adc_of_match[] = {
diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
index dfc3a306c667..3eb9ebe8372f 100644
--- a/drivers/iio/adc/stm32-adc.c
+++ b/drivers/iio/adc/stm32-adc.c
@@ -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
diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
index 506bf519f64c..5e10fb4f3704 100644
--- a/drivers/iio/adc/stm32-dfsdm-adc.c
+++ b/drivers/iio/adc/stm32-dfsdm-adc.c
@@ -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;
}
diff --git a/drivers/iio/adc/stmpe-adc.c b/drivers/iio/adc/stmpe-adc.c
index 0f88048ea48f..fba659bfdb40 100644
--- a/drivers/iio/adc/stmpe-adc.c
+++ b/drivers/iio/adc/stmpe-adc.c
@@ -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;
diff --git a/drivers/iio/adc/stx104.c b/drivers/iio/adc/stx104.c
index f87bbc711ccc..55bd2dc514e9 100644
--- a/drivers/iio/adc/stx104.c
+++ b/drivers/iio/adc/stx104.c
@@ -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];
diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
index 176e1cb4abb1..99b43f28e879 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -496,7 +496,6 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev,
struct iio_dev *indio_dev)
{
struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
- struct resource *mem;
void __iomem *base;
int ret;
@@ -508,8 +507,7 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev,
indio_dev->num_channels = ARRAY_SIZE(sun8i_a33_gpadc_channels);
indio_dev->channels = sun8i_a33_gpadc_channels;
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(&pdev->dev, mem);
+ base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
@@ -621,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;
diff --git a/drivers/iio/adc/ti-adc081c.c b/drivers/iio/adc/ti-adc081c.c
index 0235863ff77b..cf63983a54d9 100644
--- a/drivers/iio/adc/ti-adc081c.c
+++ b/drivers/iio/adc/ti-adc081c.c
@@ -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>
@@ -33,6 +33,12 @@ struct adc081c {
/* 8, 10 or 12 */
int bits;
+
+ /* Ensure natural alignment of buffer elements */
+ struct {
+ u16 channel;
+ s64 ts __aligned(8);
+ } scan;
};
#define REG_CONV_RES 0x00
@@ -128,14 +134,13 @@ static irqreturn_t adc081c_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct adc081c *data = iio_priv(indio_dev);
- u16 buf[8]; /* 2 bytes data + 6 bytes padding + 8 bytes timestamp */
int ret;
ret = i2c_smbus_read_word_swapped(data->i2c, REG_CONV_RES);
if (ret < 0)
goto out;
- buf[0] = ret;
- iio_push_to_buffers_with_timestamp(indio_dev, buf,
+ data->scan.channel = ret;
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
iio_get_time_ns(indio_dev));
out:
iio_trigger_notify_done(indio_dev->trig);
@@ -181,8 +186,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 +235,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 +242,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 +256,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,
diff --git a/drivers/iio/adc/ti-adc0832.c b/drivers/iio/adc/ti-adc0832.c
index 6ea39f4bbb37..c7a085dce1f4 100644
--- a/drivers/iio/adc/ti-adc0832.c
+++ b/drivers/iio/adc/ti-adc0832.c
@@ -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,
diff --git a/drivers/iio/adc/ti-adc084s021.c b/drivers/iio/adc/ti-adc084s021.c
index bdedf456ee05..dfba34834a57 100644
--- a/drivers/iio/adc/ti-adc084s021.c
+++ b/drivers/iio/adc/ti-adc084s021.c
@@ -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>
@@ -25,6 +26,11 @@ struct adc084s021 {
struct spi_transfer spi_trans;
struct regulator *reg;
struct mutex lock;
+ /* Buffer used to align data */
+ struct {
+ __be16 channels[4];
+ s64 ts __aligned(8);
+ } scan;
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache line.
@@ -140,14 +146,13 @@ static irqreturn_t adc084s021_buffer_trigger_handler(int irq, void *pollfunc)
struct iio_poll_func *pf = pollfunc;
struct iio_dev *indio_dev = pf->indio_dev;
struct adc084s021 *adc = iio_priv(indio_dev);
- __be16 data[8] = {0}; /* 4 * 16-bit words of data + 8 bytes timestamp */
mutex_lock(&adc->lock);
- if (adc084s021_adc_conversion(adc, &data) < 0)
+ if (adc084s021_adc_conversion(adc, adc->scan.channels) < 0)
dev_err(&adc->spi->dev, "Failed to read data\n");
- iio_push_to_buffers_with_timestamp(indio_dev, data,
+ iio_push_to_buffers_with_timestamp(indio_dev, &adc->scan,
iio_get_time_ns(indio_dev));
mutex_unlock(&adc->lock);
iio_trigger_notify_done(indio_dev->trig);
@@ -187,8 +192,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 +214,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 +259,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,
diff --git a/drivers/iio/adc/ti-adc108s102.c b/drivers/iio/adc/ti-adc108s102.c
index de9aaebff862..9b9b27415c93 100644
--- a/drivers/iio/adc/ti-adc108s102.c
+++ b/drivers/iio/adc/ti-adc108s102.c
@@ -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);
diff --git a/drivers/iio/adc/ti-adc12138.c b/drivers/iio/adc/ti-adc12138.c
index 68a9dcb8faa2..e485719cd2c4 100644
--- a/drivers/iio/adc/ti-adc12138.c
+++ b/drivers/iio/adc/ti-adc12138.c
@@ -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;
diff --git a/drivers/iio/adc/ti-adc128s052.c b/drivers/iio/adc/ti-adc128s052.c
index 1e5a936b5b6a..e86f55ce093f 100644
--- a/drivers/iio/adc/ti-adc128s052.c
+++ b/drivers/iio/adc/ti-adc128s052.c
@@ -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;
diff --git a/drivers/iio/adc/ti-adc161s626.c b/drivers/iio/adc/ti-adc161s626.c
index 3bbc9b9ddbfe..607791ffe7f0 100644
--- a/drivers/iio/adc/ti-adc161s626.c
+++ b/drivers/iio/adc/ti-adc161s626.c
@@ -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,
diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c
index 5ea4f45d6bad..9fef39bcf997 100644
--- a/drivers/iio/adc/ti-ads1015.c
+++ b/drivers/iio/adc/ti-ads1015.c
@@ -316,6 +316,7 @@ static const struct iio_chan_spec ads1115_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(ADS1015_TIMESTAMP),
};
+#ifdef CONFIG_PM
static int ads1015_set_power_state(struct ads1015_data *data, bool on)
{
int ret;
@@ -333,6 +334,15 @@ static int ads1015_set_power_state(struct ads1015_data *data, bool on)
return ret < 0 ? ret : 0;
}
+#else /* !CONFIG_PM */
+
+static int ads1015_set_power_state(struct ads1015_data *data, bool on)
+{
+ return 0;
+}
+
+#endif /* !CONFIG_PM */
+
static
int ads1015_get_adc_result(struct ads1015_data *data, int chan, int *val)
{
@@ -788,8 +798,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 +947,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;
diff --git a/drivers/iio/adc/ti-ads124s08.c b/drivers/iio/adc/ti-ads124s08.c
index 552c2be8d87a..4b4fbe33930c 100644
--- a/drivers/iio/adc/ti-ads124s08.c
+++ b/drivers/iio/adc/ti-ads124s08.c
@@ -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>
@@ -22,6 +22,8 @@
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/sysfs.h>
+#include <asm/unaligned.h>
+
/* Commands */
#define ADS124S08_CMD_NOP 0x00
#define ADS124S08_CMD_WAKEUP 0x02
@@ -188,7 +190,6 @@ static int ads124s_read(struct iio_dev *indio_dev, unsigned int chan)
{
struct ads124s_private *priv = iio_priv(indio_dev);
int ret;
- u32 tmp;
struct spi_transfer t[] = {
{
.tx_buf = &priv->data[0],
@@ -208,9 +209,7 @@ static int ads124s_read(struct iio_dev *indio_dev, unsigned int chan)
if (ret < 0)
return ret;
- tmp = priv->data[2] << 16 | priv->data[3] << 8 | priv->data[4];
-
- return tmp;
+ return get_unaligned_be24(&priv->data[2]);
}
static int ads124s_read_raw(struct iio_dev *indio_dev,
@@ -326,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;
diff --git a/drivers/iio/adc/ti-ads7950.c b/drivers/iio/adc/ti-ads7950.c
index f9edc1207f75..2383eacada87 100644
--- a/drivers/iio/adc/ti-ads7950.c
+++ b/drivers/iio/adc/ti-ads7950.c
@@ -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;
diff --git a/drivers/iio/adc/ti-ads8344.c b/drivers/iio/adc/ti-ads8344.c
index 8a8792010c20..a345a30d74fa 100644
--- a/drivers/iio/adc/ti-ads8344.c
+++ b/drivers/iio/adc/ti-ads8344.c
@@ -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;
diff --git a/drivers/iio/adc/ti-ads8688.c b/drivers/iio/adc/ti-ads8688.c
index 14fe7c320b52..16bcb37eebb7 100644
--- a/drivers/iio/adc/ti-ads8688.c
+++ b/drivers/iio/adc/ti-ads8688.c
@@ -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;
diff --git a/drivers/iio/adc/ti-tlc4541.c b/drivers/iio/adc/ti-tlc4541.c
index 77620359b54c..403b787f9f7e 100644
--- a/drivers/iio/adc/ti-tlc4541.c
+++ b/drivers/iio/adc/ti-tlc4541.c
@@ -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,
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index 9d984f2a8ba7..b11c8c47ba2a 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -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
@@ -294,7 +294,7 @@ static int tiadc_start_dma(struct iio_dev *indio_dev)
static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
{
struct tiadc_device *adc_dev = iio_priv(indio_dev);
- int i, fifo1count, read;
+ int i, fifo1count;
tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
IRQENB_FIFO1OVRRUN |
@@ -303,7 +303,7 @@ static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
/* Flush FIFO. Needed in corner cases in simultaneous tsc/adc use */
fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
for (i = 0; i < fifo1count; i++)
- read = tiadc_readl(adc_dev, REG_FIFO1);
+ tiadc_readl(adc_dev, REG_FIFO1);
return 0;
}
@@ -343,7 +343,7 @@ static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
{
struct tiadc_device *adc_dev = iio_priv(indio_dev);
struct tiadc_dma *dma = &adc_dev->dma;
- int fifo1count, i, read;
+ int fifo1count, i;
tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
@@ -358,7 +358,7 @@ static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
/* Flush FIFO of leftover data in the time it takes to disable adc */
fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
for (i = 0; i < fifo1count; i++)
- read = tiadc_readl(adc_dev, REG_FIFO1);
+ tiadc_readl(adc_dev, REG_FIFO1);
return 0;
}
@@ -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);
diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c
index 472b08f37fea..6ce40cc4568a 100644
--- a/drivers/iio/adc/twl4030-madc.c
+++ b/drivers/iio/adc/twl4030-madc.c
@@ -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
@@ -153,7 +153,7 @@ enum sample_type {
* struct twl4030_madc_data - a container for madc info
* @dev: Pointer to device structure for madc
* @lock: Mutex protecting this data structure
- * @regulator: Pointer to bias regulator for madc
+ * @usb3v1: Pointer to bias regulator for madc
* @requests: Array of request struct corresponding to SW1, SW2 and RT
* @use_second_irq: IRQ selection (main or co-processor)
* @imr: Interrupt mask register of MADC
@@ -161,7 +161,7 @@ enum sample_type {
*/
struct twl4030_madc_data {
struct device *dev;
- struct mutex lock; /* mutex protecting this data structure */
+ struct mutex lock;
struct regulator *usb3v1;
struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS];
bool use_second_irq;
@@ -472,7 +472,7 @@ static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc)
struct twl4030_madc_data *madc = _madc;
const struct twl4030_madc_conversion_method *method;
u8 isr_val, imr_val;
- int i, len, ret;
+ int i, ret;
struct twl4030_madc_request *r;
mutex_lock(&madc->lock);
@@ -504,8 +504,8 @@ static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc)
continue;
method = &twl4030_conversion_methods[r->method];
/* Read results */
- len = twl4030_madc_read_channels(madc, method->rbase,
- r->channels, r->rbuf, r->raw);
+ twl4030_madc_read_channels(madc, method->rbase,
+ r->channels, r->rbuf, r->raw);
/* Free request */
r->result_pending = false;
r->active = false;
@@ -525,8 +525,8 @@ err_i2c:
continue;
method = &twl4030_conversion_methods[r->method];
/* Read results */
- len = twl4030_madc_read_channels(madc, method->rbase,
- r->channels, r->rbuf, r->raw);
+ twl4030_madc_read_channels(madc, method->rbase,
+ r->channels, r->rbuf, r->raw);
/* Free request */
r->result_pending = false;
r->active = false;
@@ -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;
diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c
index f24148bd15de..c6416ad795ca 100644
--- a/drivers/iio/adc/twl6030-gpadc.c
+++ b/drivers/iio/adc/twl6030-gpadc.c
@@ -94,9 +94,9 @@ struct twl6030_gpadc_data;
* struct twl6030_gpadc_platform_data - platform specific data
* @nchannels: number of GPADC channels
* @iio_channels: iio channels
- * @twl6030_ideal: pointer to calibration parameters
+ * @ideal: pointer to calibration parameters
* @start_conversion: pointer to ADC start conversion function
- * @channel_to_reg pointer to ADC function to convert channel to
+ * @channel_to_reg: pointer to ADC function to convert channel to
* register address for reading conversion result
* @calibrate: pointer to calibration function
*/
@@ -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;
diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c
index cb7380bf07ca..1d794cf3e3f1 100644
--- a/drivers/iio/adc/vf610_adc.c
+++ b/drivers/iio/adc/vf610_adc.c
@@ -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;
diff --git a/drivers/iio/adc/viperboard_adc.c b/drivers/iio/adc/viperboard_adc.c
index 1d2aeb04069b..1028b101cf56 100644
--- a/drivers/iio/adc/viperboard_adc.c
+++ b/drivers/iio/adc/viperboard_adc.c
@@ -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;
diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c
index 6fd06e4eff73..d0b7ef296afb 100644
--- a/drivers/iio/adc/xilinx-xadc-core.c
+++ b/drivers/iio/adc/xilinx-xadc-core.c
@@ -3,7 +3,7 @@
* Xilinx XADC driver
*
* Copyright 2013-2014 Analog Devices Inc.
- * Author: Lars-Peter Clauen <lars@metafoo.de>
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Documentation for the parts can be found at:
* - XADC hardmacro: Xilinx UG480
@@ -663,7 +663,7 @@ static int xadc_trigger_set_state(struct iio_trigger *trigger, bool state)
mutex_lock(&xadc->mutex);
if (state) {
- /* Only one of the two triggers can be active at the a time. */
+ /* Only one of the two triggers can be active at a time. */
if (xadc->trigger != NULL) {
ret = -EBUSY;
goto err_out;
@@ -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;
diff --git a/drivers/iio/adc/xilinx-xadc-events.c b/drivers/iio/adc/xilinx-xadc-events.c
index dbfd5da290a4..2357f585720a 100644
--- a/drivers/iio/adc/xilinx-xadc-events.c
+++ b/drivers/iio/adc/xilinx-xadc-events.c
@@ -3,7 +3,7 @@
* Xilinx XADC driver
*
* Copyright 2013 Analog Devices Inc.
- * Author: Lars-Peter Clauen <lars@metafoo.de>
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
*/
#include <linux/iio/events.h>
diff --git a/drivers/iio/adc/xilinx-xadc.h b/drivers/iio/adc/xilinx-xadc.h
index 4017f18b0a4f..25abed9c0285 100644
--- a/drivers/iio/adc/xilinx-xadc.h
+++ b/drivers/iio/adc/xilinx-xadc.h
@@ -3,7 +3,7 @@
* Xilinx XADC driver
*
* Copyright 2013 Analog Devices Inc.
- * Author: Lars-Peter Clauen <lars@metafoo.de>
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
*/
#ifndef __IIO_XILINX_XADC__
diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c
index e9ceee66d1e7..69c0f277ada0 100644
--- a/drivers/iio/afe/iio-rescale.c
+++ b/drivers/iio/afe/iio-rescale.c
@@ -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;
diff --git a/drivers/iio/amplifiers/ad8366.c b/drivers/iio/amplifiers/ad8366.c
index 62167b87caea..cfcf18a0bce8 100644
--- a/drivers/iio/amplifiers/ad8366.c
+++ b/drivers/iio/amplifiers/ad8366.c
@@ -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;
diff --git a/drivers/iio/amplifiers/hmc425a.c b/drivers/iio/amplifiers/hmc425a.c
index d9e6e9678ffc..582708924e4f 100644
--- a/drivers/iio/amplifiers/hmc425a.c
+++ b/drivers/iio/amplifiers/hmc425a.c
@@ -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;
diff --git a/drivers/iio/buffer/industrialio-buffer-dma.c b/drivers/iio/buffer/industrialio-buffer-dma.c
index a74bd9c0587c..d348af8b9705 100644
--- a/drivers/iio/buffer/industrialio-buffer-dma.c
+++ b/drivers/iio/buffer/industrialio-buffer-dma.c
@@ -12,7 +12,6 @@
#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/poll.h>
-#include <linux/iio/buffer.h>
#include <linux/iio/buffer_impl.h>
#include <linux/iio/buffer-dma.h>
#include <linux/dma-mapping.h>
diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
index b129693af0fd..6dedf12b69a4 100644
--- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c
+++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
@@ -134,7 +134,7 @@ static ssize_t iio_dmaengine_buffer_get_length_align(struct device *dev,
struct dmaengine_buffer *dmaengine_buffer =
iio_buffer_to_dmaengine_buffer(indio_dev->buffer);
- return sprintf(buf, "%u\n", dmaengine_buffer->align);
+ return sprintf(buf, "%zu\n", dmaengine_buffer->align);
}
static IIO_DEVICE_ATTR(length_align_bytes, 0444,
@@ -229,6 +229,45 @@ void iio_dmaengine_buffer_free(struct iio_buffer *buffer)
}
EXPORT_SYMBOL_GPL(iio_dmaengine_buffer_free);
+static void __devm_iio_dmaengine_buffer_free(struct device *dev, void *res)
+{
+ iio_dmaengine_buffer_free(*(struct iio_buffer **)res);
+}
+
+/**
+ * devm_iio_dmaengine_buffer_alloc() - Resource-managed iio_dmaengine_buffer_alloc()
+ * @dev: Parent device for the buffer
+ * @channel: DMA channel name, typically "rx".
+ *
+ * This allocates a new IIO buffer which internally uses the DMAengine framework
+ * to perform its transfers. The parent device will be used to request the DMA
+ * channel.
+ *
+ * The buffer will be automatically de-allocated once the device gets destroyed.
+ */
+struct iio_buffer *devm_iio_dmaengine_buffer_alloc(struct device *dev,
+ const char *channel)
+{
+ struct iio_buffer **bufferp, *buffer;
+
+ bufferp = devres_alloc(__devm_iio_dmaengine_buffer_free,
+ sizeof(*bufferp), GFP_KERNEL);
+ if (!bufferp)
+ return ERR_PTR(-ENOMEM);
+
+ buffer = iio_dmaengine_buffer_alloc(dev, channel);
+ if (IS_ERR(buffer)) {
+ devres_free(bufferp);
+ return buffer;
+ }
+
+ *bufferp = buffer;
+ devres_add(dev, bufferp);
+
+ return buffer;
+}
+EXPORT_SYMBOL_GPL(devm_iio_dmaengine_buffer_alloc);
+
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("DMA buffer for the IIO framework");
MODULE_LICENSE("GPL");
diff --git a/drivers/iio/buffer/industrialio-hw-consumer.c b/drivers/iio/buffer/industrialio-hw-consumer.c
index 95165697d8ae..f2d27788f666 100644
--- a/drivers/iio/buffer/industrialio-hw-consumer.c
+++ b/drivers/iio/buffer/industrialio-hw-consumer.c
@@ -142,17 +142,6 @@ static void devm_iio_hw_consumer_release(struct device *dev, void *res)
iio_hw_consumer_free(*(struct iio_hw_consumer **)res);
}
-static int devm_iio_hw_consumer_match(struct device *dev, void *res, void *data)
-{
- struct iio_hw_consumer **r = res;
-
- if (!r || !*r) {
- WARN_ON(!r || !*r);
- return 0;
- }
- return *r == data;
-}
-
/**
* devm_iio_hw_consumer_alloc - Resource-managed iio_hw_consumer_alloc()
* @dev: Pointer to consumer device.
@@ -160,9 +149,6 @@ static int devm_iio_hw_consumer_match(struct device *dev, void *res, void *data)
* Managed iio_hw_consumer_alloc. iio_hw_consumer allocated with this function
* is automatically freed on driver detach.
*
- * If an iio_hw_consumer allocated with this function needs to be freed
- * separately, devm_iio_hw_consumer_free() must be used.
- *
* returns pointer to allocated iio_hw_consumer on success, NULL on failure.
*/
struct iio_hw_consumer *devm_iio_hw_consumer_alloc(struct device *dev)
@@ -187,23 +173,6 @@ struct iio_hw_consumer *devm_iio_hw_consumer_alloc(struct device *dev)
EXPORT_SYMBOL_GPL(devm_iio_hw_consumer_alloc);
/**
- * devm_iio_hw_consumer_free - Resource-managed iio_hw_consumer_free()
- * @dev: Pointer to consumer device.
- * @hwc: iio_hw_consumer to free.
- *
- * Free iio_hw_consumer allocated with devm_iio_hw_consumer_alloc().
- */
-void devm_iio_hw_consumer_free(struct device *dev, struct iio_hw_consumer *hwc)
-{
- int rc;
-
- rc = devres_release(dev, devm_iio_hw_consumer_release,
- devm_iio_hw_consumer_match, hwc);
- WARN_ON(rc);
-}
-EXPORT_SYMBOL_GPL(devm_iio_hw_consumer_free);
-
-/**
* iio_hw_consumer_enable() - Enable IIO hardware consumer
* @hwc: iio_hw_consumer to enable.
*
diff --git a/drivers/iio/buffer/industrialio-triggered-buffer.c b/drivers/iio/buffer/industrialio-triggered-buffer.c
index cb322b2f09cd..6c20a83f887e 100644
--- a/drivers/iio/buffer/industrialio-triggered-buffer.c
+++ b/drivers/iio/buffer/industrialio-triggered-buffer.c
@@ -13,11 +13,6 @@
#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;
@@ -126,17 +118,6 @@ int devm_iio_triggered_buffer_setup(struct device *dev,
}
EXPORT_SYMBOL_GPL(devm_iio_triggered_buffer_setup);
-void devm_iio_triggered_buffer_cleanup(struct device *dev,
- struct iio_dev *indio_dev)
-{
- int rc;
-
- rc = devres_release(dev, devm_iio_triggered_buffer_clean,
- devm_iio_device_match, indio_dev);
- WARN_ON(rc);
-}
-EXPORT_SYMBOL_GPL(devm_iio_triggered_buffer_cleanup);
-
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("IIO helper functions for setting up triggered buffers");
MODULE_LICENSE("GPL");
diff --git a/drivers/iio/buffer/kfifo_buf.c b/drivers/iio/buffer/kfifo_buf.c
index 3150f8ab984b..1359abed3b31 100644
--- a/drivers/iio/buffer/kfifo_buf.c
+++ b/drivers/iio/buffer/kfifo_buf.c
@@ -179,16 +179,6 @@ static void devm_iio_kfifo_release(struct device *dev, void *res)
iio_kfifo_free(*(struct iio_buffer **)res);
}
-static int devm_iio_kfifo_match(struct device *dev, void *res, void *data)
-{
- struct iio_buffer **r = res;
-
- if (WARN_ON(!r || !*r))
- return 0;
-
- return *r == data;
-}
-
/**
* devm_iio_fifo_allocate - Resource-managed iio_kfifo_allocate()
* @dev: Device to allocate kfifo buffer for
@@ -216,16 +206,4 @@ struct iio_buffer *devm_iio_kfifo_allocate(struct device *dev)
}
EXPORT_SYMBOL(devm_iio_kfifo_allocate);
-/**
- * devm_iio_fifo_free - Resource-managed iio_kfifo_free()
- * @dev: Device the buffer belongs to
- * @r: The buffer associated with the device
- */
-void devm_iio_kfifo_free(struct device *dev, struct iio_buffer *r)
-{
- WARN_ON(devres_release(dev, devm_iio_kfifo_release,
- devm_iio_kfifo_match, r));
-}
-EXPORT_SYMBOL(devm_iio_kfifo_free);
-
MODULE_LICENSE("GPL");
diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig
index a7e65a59bf42..10bb431bc3ce 100644
--- a/drivers/iio/chemical/Kconfig
+++ b/drivers/iio/chemical/Kconfig
@@ -22,6 +22,17 @@ config ATLAS_PH_SENSOR
To compile this driver as module, choose M here: the
module will be called atlas-ph-sensor.
+config ATLAS_EZO_SENSOR
+ tristate "Atlas Scientific EZO sensors"
+ depends on I2C
+ help
+ Say Y here to build I2C interface support for the following
+ Atlas Scientific EZO sensors
+ * CO2 EZO Sensor
+
+ To compile this driver as module, choose M here: the
+ module will be called atlas-ezo-sensor.
+
config BME680
tristate "Bosch Sensortec BME680 sensor driver"
depends on (I2C || SPI)
@@ -74,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
diff --git a/drivers/iio/chemical/Makefile b/drivers/iio/chemical/Makefile
index 33d3a595dda9..fef63dd5bf92 100644
--- a/drivers/iio/chemical/Makefile
+++ b/drivers/iio/chemical/Makefile
@@ -5,12 +5,16 @@
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_ATLAS_PH_SENSOR) += atlas-sensor.o
+obj-$(CONFIG_ATLAS_EZO_SENSOR) += atlas-ezo-sensor.o
obj-$(CONFIG_BME680) += bme680_core.o
obj-$(CONFIG_BME680_I2C) += bme680_i2c.o
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
diff --git a/drivers/iio/chemical/ams-iaq-core.c b/drivers/iio/chemical/ams-iaq-core.c
index a0646ba2ad88..8c1b64fd424a 100644
--- a/drivers/iio/chemical/ams-iaq-core.c
+++ b/drivers/iio/chemical/ams-iaq-core.c
@@ -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;
diff --git a/drivers/iio/chemical/atlas-ezo-sensor.c b/drivers/iio/chemical/atlas-ezo-sensor.c
new file mode 100644
index 000000000000..8b72bb012363
--- /dev/null
+++ b/drivers/iio/chemical/atlas-ezo-sensor.c
@@ -0,0 +1,176 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * atlas-ezo-sensor.c - Support for Atlas Scientific EZO sensors
+ *
+ * Copyright (C) 2020 Konsulko Group
+ * Author: Matt Ranostay <matt.ranostay@konsulko.com>
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/of_device.h>
+#include <linux/iio/iio.h>
+
+#define ATLAS_EZO_DRV_NAME "atlas-ezo-sensor"
+#define ATLAS_CO2_INT_TIME_IN_MS 950
+
+enum {
+ ATLAS_CO2_EZO,
+};
+
+struct atlas_ezo_device {
+ const struct iio_chan_spec *channels;
+ int num_channels;
+ int delay;
+};
+
+struct atlas_ezo_data {
+ struct i2c_client *client;
+ struct atlas_ezo_device *chip;
+
+ /* lock to avoid multiple concurrent read calls */
+ struct mutex lock;
+
+ u8 buffer[8];
+};
+
+static const struct iio_chan_spec atlas_co2_ezo_channels[] = {
+ {
+ .type = IIO_CONCENTRATION,
+ .modified = 1,
+ .channel2 = IIO_MOD_CO2,
+ .info_mask_separate =
+ BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 32,
+ .storagebits = 32,
+ .endianness = IIO_CPU,
+ },
+ },
+};
+
+static struct atlas_ezo_device atlas_ezo_devices[] = {
+ [ATLAS_CO2_EZO] = {
+ .channels = atlas_co2_ezo_channels,
+ .num_channels = 1,
+ .delay = ATLAS_CO2_INT_TIME_IN_MS,
+ },
+};
+
+static int atlas_ezo_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct atlas_ezo_data *data = iio_priv(indio_dev);
+ struct i2c_client *client = data->client;
+
+ if (chan->type != IIO_CONCENTRATION)
+ return -EINVAL;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW: {
+ int ret;
+ long tmp;
+
+ mutex_lock(&data->lock);
+
+ tmp = i2c_smbus_write_byte(client, 'R');
+
+ if (tmp < 0) {
+ mutex_unlock(&data->lock);
+ return tmp;
+ }
+
+ msleep(data->chip->delay);
+
+ tmp = i2c_master_recv(client, data->buffer, sizeof(data->buffer));
+
+ if (tmp < 0 || data->buffer[0] != 1) {
+ mutex_unlock(&data->lock);
+ return -EBUSY;
+ }
+
+ ret = kstrtol(data->buffer + 1, 10, &tmp);
+
+ *val = tmp;
+
+ mutex_unlock(&data->lock);
+
+ return ret ? ret : IIO_VAL_INT;
+ }
+ case IIO_CHAN_INFO_SCALE:
+ *val = 0;
+ *val2 = 100; /* 0.0001 */
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+
+ return 0;
+}
+
+static const struct iio_info atlas_info = {
+ .read_raw = atlas_ezo_read_raw,
+};
+
+static const struct i2c_device_id atlas_ezo_id[] = {
+ { "atlas-co2-ezo", ATLAS_CO2_EZO },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, atlas_ezo_id);
+
+static const struct of_device_id atlas_ezo_dt_ids[] = {
+ { .compatible = "atlas,co2-ezo", .data = (void *)ATLAS_CO2_EZO, },
+ {}
+};
+MODULE_DEVICE_TABLE(of, atlas_ezo_dt_ids);
+
+static int atlas_ezo_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct atlas_ezo_data *data;
+ struct atlas_ezo_device *chip;
+ const struct of_device_id *of_id;
+ struct iio_dev *indio_dev;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ of_id = of_match_device(atlas_ezo_dt_ids, &client->dev);
+ if (!of_id)
+ chip = &atlas_ezo_devices[id->driver_data];
+ else
+ chip = &atlas_ezo_devices[(unsigned long)of_id->data];
+
+ indio_dev->info = &atlas_info;
+ indio_dev->name = ATLAS_EZO_DRV_NAME;
+ indio_dev->channels = chip->channels;
+ indio_dev->num_channels = chip->num_channels;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ data = iio_priv(indio_dev);
+ data->client = client;
+ data->chip = chip;
+ mutex_init(&data->lock);
+
+ return devm_iio_device_register(&client->dev, indio_dev);
+};
+
+static struct i2c_driver atlas_ezo_driver = {
+ .driver = {
+ .name = ATLAS_EZO_DRV_NAME,
+ .of_match_table = atlas_ezo_dt_ids,
+ },
+ .probe = atlas_ezo_probe,
+ .id_table = atlas_ezo_id,
+};
+module_i2c_driver(atlas_ezo_driver);
+
+MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>");
+MODULE_DESCRIPTION("Atlas Scientific EZO sensors");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/chemical/atlas-sensor.c b/drivers/iio/chemical/atlas-sensor.c
index 7b199ce16ecf..43069636fcd5 100644
--- a/drivers/iio/chemical/atlas-sensor.c
+++ b/drivers/iio/chemical/atlas-sensor.c
@@ -53,6 +53,8 @@
#define ATLAS_REG_DO_CALIB_STATUS_PRESSURE BIT(0)
#define ATLAS_REG_DO_CALIB_STATUS_DO BIT(1)
+#define ATLAS_REG_RTD_DATA 0x0e
+
#define ATLAS_REG_PH_TEMP_DATA 0x0e
#define ATLAS_REG_PH_DATA 0x16
@@ -72,12 +74,14 @@
#define ATLAS_EC_INT_TIME_IN_MS 650
#define ATLAS_ORP_INT_TIME_IN_MS 450
#define ATLAS_DO_INT_TIME_IN_MS 450
+#define ATLAS_RTD_INT_TIME_IN_MS 450
enum {
ATLAS_PH_SM,
ATLAS_EC_SM,
ATLAS_ORP_SM,
ATLAS_DO_SM,
+ ATLAS_RTD_SM,
};
struct atlas_data {
@@ -218,6 +222,22 @@ static const struct iio_chan_spec atlas_do_channels[] = {
},
};
+static const struct iio_chan_spec atlas_rtd_channels[] = {
+ {
+ .type = IIO_TEMP,
+ .address = ATLAS_REG_RTD_DATA,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 32,
+ .storagebits = 32,
+ .endianness = IIO_BE,
+ },
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(1),
+};
+
static int atlas_check_ph_calibration(struct atlas_data *data)
{
struct device *dev = &data->client->dev;
@@ -362,6 +382,12 @@ static struct atlas_device atlas_devices[] = {
.calibration = &atlas_check_do_calibration,
.delay = ATLAS_DO_INT_TIME_IN_MS,
},
+ [ATLAS_RTD_SM] = {
+ .channels = atlas_rtd_channels,
+ .num_channels = 2,
+ .data_reg = ATLAS_REG_RTD_DATA,
+ .delay = ATLAS_RTD_INT_TIME_IN_MS,
+ },
};
static int atlas_set_powermode(struct atlas_data *data, int on)
@@ -384,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);
@@ -411,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 = {
@@ -438,8 +460,7 @@ static irqreturn_t atlas_trigger_handler(int irq, void *private)
int ret;
ret = regmap_bulk_read(data->regmap, data->chip->data_reg,
- (u8 *) &data->buffer,
- sizeof(__be32) * channels);
+ &data->buffer, sizeof(__be32) * channels);
if (!ret)
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
@@ -475,7 +496,7 @@ static int atlas_read_measurement(struct atlas_data *data, int reg, __be32 *val)
if (suspended)
msleep(data->chip->delay);
- ret = regmap_bulk_read(data->regmap, reg, (u8 *) val, sizeof(*val));
+ ret = regmap_bulk_read(data->regmap, reg, val, sizeof(*val));
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
@@ -490,6 +511,7 @@ static int atlas_read_raw(struct iio_dev *indio_dev,
struct atlas_data *data = iio_priv(indio_dev);
switch (mask) {
+ case IIO_CHAN_INFO_PROCESSED:
case IIO_CHAN_INFO_RAW: {
int ret;
__be32 reg;
@@ -497,7 +519,7 @@ static int atlas_read_raw(struct iio_dev *indio_dev,
switch (chan->type) {
case IIO_TEMP:
ret = regmap_bulk_read(data->regmap, chan->address,
- (u8 *) &reg, sizeof(reg));
+ &reg, sizeof(reg));
break;
case IIO_PH:
case IIO_CONCENTRATION:
@@ -578,6 +600,7 @@ static const struct i2c_device_id atlas_id[] = {
{ "atlas-ec-sm", ATLAS_EC_SM},
{ "atlas-orp-sm", ATLAS_ORP_SM},
{ "atlas-do-sm", ATLAS_DO_SM},
+ { "atlas-rtd-sm", ATLAS_RTD_SM},
{}
};
MODULE_DEVICE_TABLE(i2c, atlas_id);
@@ -587,6 +610,7 @@ static const struct of_device_id atlas_dt_ids[] = {
{ .compatible = "atlas,ec-sm", .data = (void *)ATLAS_EC_SM, },
{ .compatible = "atlas,orp-sm", .data = (void *)ATLAS_ORP_SM, },
{ .compatible = "atlas,do-sm", .data = (void *)ATLAS_DO_SM, },
+ { .compatible = "atlas,rtd-sm", .data = (void *)ATLAS_RTD_SM, },
{ }
};
MODULE_DEVICE_TABLE(of, atlas_dt_ids);
@@ -616,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);
diff --git a/drivers/iio/chemical/bme680_core.c b/drivers/iio/chemical/bme680_core.c
index ccde4c65ff93..6ea99e4cbf92 100644
--- a/drivers/iio/chemical/bme680_core.c
+++ b/drivers/iio/chemical/bme680_core.c
@@ -114,14 +114,16 @@ static int bme680_read_calib(struct bme680_data *data,
__le16 buf;
/* Temperature related coefficients */
- ret = regmap_bulk_read(data->regmap, BME680_T1_LSB_REG, (u8 *) &buf, 2);
+ ret = regmap_bulk_read(data->regmap, BME680_T1_LSB_REG,
+ &buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_T1_LSB_REG\n");
return ret;
}
calib->par_t1 = le16_to_cpu(buf);
- ret = regmap_bulk_read(data->regmap, BME680_T2_LSB_REG, (u8 *) &buf, 2);
+ ret = regmap_bulk_read(data->regmap, BME680_T2_LSB_REG,
+ &buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_T2_LSB_REG\n");
return ret;
@@ -136,14 +138,16 @@ static int bme680_read_calib(struct bme680_data *data,
calib->par_t3 = tmp;
/* Pressure related coefficients */
- ret = regmap_bulk_read(data->regmap, BME680_P1_LSB_REG, (u8 *) &buf, 2);
+ ret = regmap_bulk_read(data->regmap, BME680_P1_LSB_REG,
+ &buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_P1_LSB_REG\n");
return ret;
}
calib->par_p1 = le16_to_cpu(buf);
- ret = regmap_bulk_read(data->regmap, BME680_P2_LSB_REG, (u8 *) &buf, 2);
+ ret = regmap_bulk_read(data->regmap, BME680_P2_LSB_REG,
+ &buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_P2_LSB_REG\n");
return ret;
@@ -157,14 +161,16 @@ static int bme680_read_calib(struct bme680_data *data,
}
calib->par_p3 = tmp;
- ret = regmap_bulk_read(data->regmap, BME680_P4_LSB_REG, (u8 *) &buf, 2);
+ ret = regmap_bulk_read(data->regmap, BME680_P4_LSB_REG,
+ &buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_P4_LSB_REG\n");
return ret;
}
calib->par_p4 = le16_to_cpu(buf);
- ret = regmap_bulk_read(data->regmap, BME680_P5_LSB_REG, (u8 *) &buf, 2);
+ ret = regmap_bulk_read(data->regmap, BME680_P5_LSB_REG,
+ &buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_P5_LSB_REG\n");
return ret;
@@ -185,14 +191,16 @@ static int bme680_read_calib(struct bme680_data *data,
}
calib->par_p7 = tmp;
- ret = regmap_bulk_read(data->regmap, BME680_P8_LSB_REG, (u8 *) &buf, 2);
+ ret = regmap_bulk_read(data->regmap, BME680_P8_LSB_REG,
+ &buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_P8_LSB_REG\n");
return ret;
}
calib->par_p8 = le16_to_cpu(buf);
- ret = regmap_bulk_read(data->regmap, BME680_P9_LSB_REG, (u8 *) &buf, 2);
+ ret = regmap_bulk_read(data->regmap, BME680_P9_LSB_REG,
+ &buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_P9_LSB_REG\n");
return ret;
@@ -276,8 +284,8 @@ static int bme680_read_calib(struct bme680_data *data,
}
calib->par_gh1 = tmp;
- ret = regmap_bulk_read(data->regmap, BME680_GH2_LSB_REG, (u8 *) &buf,
- 2);
+ ret = regmap_bulk_read(data->regmap, BME680_GH2_LSB_REG,
+ &buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_GH2_LSB_REG\n");
return ret;
@@ -615,7 +623,7 @@ static int bme680_read_temp(struct bme680_data *data, int *val)
return ret;
ret = regmap_bulk_read(data->regmap, BME680_REG_TEMP_MSB,
- (u8 *) &tmp, 3);
+ &tmp, 3);
if (ret < 0) {
dev_err(dev, "failed to read temperature\n");
return ret;
@@ -656,7 +664,7 @@ static int bme680_read_press(struct bme680_data *data,
return ret;
ret = regmap_bulk_read(data->regmap, BME680_REG_PRESS_MSB,
- (u8 *) &tmp, 3);
+ &tmp, 3);
if (ret < 0) {
dev_err(dev, "failed to read pressure\n");
return ret;
@@ -689,7 +697,7 @@ static int bme680_read_humid(struct bme680_data *data,
return ret;
ret = regmap_bulk_read(data->regmap, BM6880_REG_HUMIDITY_MSB,
- (u8 *) &tmp, 2);
+ &tmp, sizeof(tmp));
if (ret < 0) {
dev_err(dev, "failed to read humidity\n");
return ret;
@@ -754,7 +762,7 @@ static int bme680_read_gas(struct bme680_data *data,
}
ret = regmap_bulk_read(data->regmap, BME680_REG_GAS_MSB,
- (u8 *) &tmp, 2);
+ &tmp, sizeof(tmp));
if (ret < 0) {
dev_err(dev, "failed to read gas resistance\n");
return ret;
@@ -915,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);
diff --git a/drivers/iio/chemical/ccs811.c b/drivers/iio/chemical/ccs811.c
index 2ebdfc35bcda..60dd87e96f5f 100644
--- a/drivers/iio/chemical/ccs811.c
+++ b/drivers/iio/chemical/ccs811.c
@@ -16,6 +16,7 @@
*/
#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
@@ -36,6 +37,7 @@
#define CCS811_ERR 0xE0
/* Used to transition from boot to application mode */
#define CCS811_APP_START 0xF4
+#define CCS811_SW_RESET 0xFF
/* Status register flags */
#define CCS811_STATUS_ERROR BIT(0)
@@ -74,7 +76,13 @@ struct ccs811_data {
struct mutex lock; /* Protect readings */
struct ccs811_reading buffer;
struct iio_trigger *drdy_trig;
+ struct gpio_desc *wakeup_gpio;
bool drdy_trig_on;
+ /* Ensures correct alignment of timestamp if present */
+ struct {
+ s16 channels[2];
+ s64 ts __aligned(8);
+ } scan;
};
static const struct iio_chan_spec ccs811_channels[] = {
@@ -166,10 +174,25 @@ static int ccs811_setup(struct i2c_client *client)
CCS811_MODE_IAQ_1SEC);
}
+static void ccs811_set_wakeup(struct ccs811_data *data, bool enable)
+{
+ if (!data->wakeup_gpio)
+ return;
+
+ gpiod_set_value(data->wakeup_gpio, enable);
+
+ if (enable)
+ usleep_range(50, 60);
+ else
+ usleep_range(20, 30);
+}
+
static int ccs811_get_measurement(struct ccs811_data *data)
{
int ret, tries = 11;
+ ccs811_set_wakeup(data, true);
+
/* Maximum waiting time: 1s, as measurements are made every second */
while (tries-- > 0) {
ret = i2c_smbus_read_byte_data(data->client, CCS811_STATUS);
@@ -183,9 +206,12 @@ static int ccs811_get_measurement(struct ccs811_data *data)
if (!(ret & CCS811_STATUS_DATA_READY))
return -EIO;
- return i2c_smbus_read_i2c_block_data(data->client,
+ ret = i2c_smbus_read_i2c_block_data(data->client,
CCS811_ALG_RESULT_DATA, 8,
(char *)&data->buffer);
+ ccs811_set_wakeup(data, false);
+
+ return ret;
}
static int ccs811_read_raw(struct iio_dev *indio_dev,
@@ -306,17 +332,17 @@ static irqreturn_t ccs811_trigger_handler(int irq, void *p)
struct iio_dev *indio_dev = pf->indio_dev;
struct ccs811_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
- s16 buf[8]; /* s16 eCO2 + s16 TVOC + padding + 8 byte timestamp */
int ret;
- ret = i2c_smbus_read_i2c_block_data(client, CCS811_ALG_RESULT_DATA, 4,
- (u8 *)&buf);
+ ret = i2c_smbus_read_i2c_block_data(client, CCS811_ALG_RESULT_DATA,
+ sizeof(data->scan.channels),
+ (u8 *)data->scan.channels);
if (ret != 4) {
dev_err(&client->dev, "cannot read sensor data\n");
goto err;
}
- iio_push_to_buffers_with_timestamp(indio_dev, buf,
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
iio_get_time_ns(indio_dev));
err:
@@ -336,6 +362,45 @@ static irqreturn_t ccs811_data_rdy_trigger_poll(int irq, void *private)
return IRQ_HANDLED;
}
+static int ccs811_reset(struct i2c_client *client)
+{
+ struct gpio_desc *reset_gpio;
+ int ret;
+
+ reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(reset_gpio))
+ return PTR_ERR(reset_gpio);
+
+ /* Try to reset using nRESET pin if available else do SW reset */
+ if (reset_gpio) {
+ gpiod_set_value(reset_gpio, 1);
+ usleep_range(20, 30);
+ gpiod_set_value(reset_gpio, 0);
+ } else {
+ /*
+ * As per the datasheet, this sequence of values needs to be
+ * written to the SW_RESET register for triggering the soft
+ * reset in the device and placing it in boot mode.
+ */
+ static const u8 reset_seq[] = {
+ 0x11, 0xE5, 0x72, 0x8A,
+ };
+
+ ret = i2c_smbus_write_i2c_block_data(client, CCS811_SW_RESET,
+ sizeof(reset_seq), reset_seq);
+ if (ret < 0) {
+ dev_err(&client->dev, "Failed to reset sensor\n");
+ return ret;
+ }
+ }
+
+ /* tSTART delay required after reset */
+ usleep_range(1000, 2000);
+
+ return 0;
+}
+
static int ccs811_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -348,40 +413,62 @@ static int ccs811_probe(struct i2c_client *client,
| I2C_FUNC_SMBUS_READ_I2C_BLOCK))
return -EOPNOTSUPP;
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ data->client = client;
+
+ data->wakeup_gpio = devm_gpiod_get_optional(&client->dev, "wakeup",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(data->wakeup_gpio))
+ return PTR_ERR(data->wakeup_gpio);
+
+ ccs811_set_wakeup(data, true);
+
+ ret = ccs811_reset(client);
+ if (ret) {
+ ccs811_set_wakeup(data, false);
+ return ret;
+ }
+
/* Check hardware id (should be 0x81 for this family of devices) */
ret = i2c_smbus_read_byte_data(client, CCS811_HW_ID);
- if (ret < 0)
+ if (ret < 0) {
+ ccs811_set_wakeup(data, false);
return ret;
+ }
if (ret != CCS811_HW_ID_VALUE) {
dev_err(&client->dev, "hardware id doesn't match CCS81x\n");
+ ccs811_set_wakeup(data, false);
return -ENODEV;
}
ret = i2c_smbus_read_byte_data(client, CCS811_HW_VERSION);
- if (ret < 0)
+ if (ret < 0) {
+ ccs811_set_wakeup(data, false);
return ret;
+ }
if ((ret & CCS811_HW_VERSION_MASK) != CCS811_HW_VERSION_VALUE) {
dev_err(&client->dev, "no CCS811 sensor\n");
+ ccs811_set_wakeup(data, false);
return -ENODEV;
}
- indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
- if (!indio_dev)
- return -ENOMEM;
-
ret = ccs811_setup(client);
- if (ret < 0)
+ if (ret < 0) {
+ ccs811_set_wakeup(data, false);
return ret;
+ }
- data = iio_priv(indio_dev);
- i2c_set_clientdata(client, indio_dev);
- data->client = client;
+ ccs811_set_wakeup(data, false);
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;
@@ -466,9 +553,16 @@ static const struct i2c_device_id ccs811_id[] = {
};
MODULE_DEVICE_TABLE(i2c, ccs811_id);
+static const struct of_device_id ccs811_dt_ids[] = {
+ { .compatible = "ams,ccs811" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ccs811_dt_ids);
+
static struct i2c_driver ccs811_driver = {
.driver = {
.name = "ccs811",
+ .of_match_table = ccs811_dt_ids,
},
.probe = ccs811_probe,
.remove = ccs811_remove,
diff --git a/drivers/iio/chemical/pms7003.c b/drivers/iio/chemical/pms7003.c
index 23c9ab252470..e9d4405654bc 100644
--- a/drivers/iio/chemical/pms7003.c
+++ b/drivers/iio/chemical/pms7003.c
@@ -73,6 +73,11 @@ struct pms7003_state {
struct pms7003_frame frame;
struct completion frame_ready;
struct mutex lock; /* must be held whenever state gets touched */
+ /* Used to construct scan to push to the IIO buffer */
+ struct {
+ u16 data[3]; /* PM1, PM2P5, PM10 */
+ s64 ts;
+ } scan;
};
static int pms7003_do_cmd(struct pms7003_state *state, enum pms7003_cmd cmd)
@@ -104,7 +109,6 @@ static irqreturn_t pms7003_trigger_handler(int irq, void *p)
struct iio_dev *indio_dev = pf->indio_dev;
struct pms7003_state *state = iio_priv(indio_dev);
struct pms7003_frame *frame = &state->frame;
- u16 data[3 + 1 + 4]; /* PM1, PM2P5, PM10, padding, timestamp */
int ret;
mutex_lock(&state->lock);
@@ -114,12 +118,15 @@ static irqreturn_t pms7003_trigger_handler(int irq, void *p)
goto err;
}
- data[PM1] = pms7003_get_pm(frame->data + PMS7003_PM1_OFFSET);
- data[PM2P5] = pms7003_get_pm(frame->data + PMS7003_PM2P5_OFFSET);
- data[PM10] = pms7003_get_pm(frame->data + PMS7003_PM10_OFFSET);
+ state->scan.data[PM1] =
+ pms7003_get_pm(frame->data + PMS7003_PM1_OFFSET);
+ state->scan.data[PM2P5] =
+ pms7003_get_pm(frame->data + PMS7003_PM2P5_OFFSET);
+ state->scan.data[PM10] =
+ pms7003_get_pm(frame->data + PMS7003_PM10_OFFSET);
mutex_unlock(&state->lock);
- iio_push_to_buffers_with_timestamp(indio_dev, data,
+ iio_push_to_buffers_with_timestamp(indio_dev, &state->scan,
iio_get_time_ns(indio_dev));
err:
iio_trigger_notify_done(indio_dev->trig);
@@ -273,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
index 000000000000..f60127bfe0f4
--- /dev/null
+++ b/drivers/iio/chemical/scd30.h
@@ -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
index 000000000000..eac76972f83e
--- /dev/null
+++ b/drivers/iio/chemical/scd30_core.c
@@ -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
index 000000000000..875892a070ee
--- /dev/null
+++ b/drivers/iio/chemical/scd30_i2c.c
@@ -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
index 000000000000..06f85eb1a4dd
--- /dev/null
+++ b/drivers/iio/chemical/scd30_serial.c
@@ -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");
diff --git a/drivers/iio/chemical/sgp30.c b/drivers/iio/chemical/sgp30.c
index 403e8803471a..2c4086c48136 100644
--- a/drivers/iio/chemical/sgp30.c
+++ b/drivers/iio/chemical/sgp30.c
@@ -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;
diff --git a/drivers/iio/chemical/sps30.c b/drivers/iio/chemical/sps30.c
index acb9f8ecbb3d..2ea9a5c4d846 100644
--- a/drivers/iio/chemical/sps30.c
+++ b/drivers/iio/chemical/sps30.c
@@ -118,7 +118,7 @@ static int sps30_do_cmd(struct sps30_state *state, u16 cmd, u8 *data, int size)
case SPS30_READ_AUTO_CLEANING_PERIOD:
buf[0] = SPS30_AUTO_CLEANING_PERIOD >> 8;
buf[1] = (u8)(SPS30_AUTO_CLEANING_PERIOD & 0xff);
- /* fall through */
+ fallthrough;
case SPS30_READ_DATA_READY_FLAG:
case SPS30_READ_DATA:
case SPS30_READ_SERIAL:
@@ -230,15 +230,18 @@ static irqreturn_t sps30_trigger_handler(int irq, void *p)
struct iio_dev *indio_dev = pf->indio_dev;
struct sps30_state *state = iio_priv(indio_dev);
int ret;
- s32 data[4 + 2]; /* PM1, PM2P5, PM4, PM10, timestamp */
+ struct {
+ s32 data[4]; /* PM1, PM2P5, PM4, PM10 */
+ s64 ts;
+ } scan;
mutex_lock(&state->lock);
- ret = sps30_do_meas(state, data, 4);
+ ret = sps30_do_meas(state, scan.data, ARRAY_SIZE(scan.data));
mutex_unlock(&state->lock);
if (ret)
goto err;
- iio_push_to_buffers_with_timestamp(indio_dev, data,
+ iio_push_to_buffers_with_timestamp(indio_dev, &scan,
iio_get_time_ns(indio_dev));
err:
iio_trigger_notify_done(indio_dev->trig);
@@ -484,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;
diff --git a/drivers/iio/chemical/vz89x.c b/drivers/iio/chemical/vz89x.c
index 415b39339d4e..5586eb8e12cd 100644
--- a/drivers/iio/chemical/vz89x.c
+++ b/drivers/iio/chemical/vz89x.c
@@ -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;
diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
index a66941fdb385..130ab8ce0269 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -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,
diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
index c831915ca7e5..1bc6efa47316 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -72,10 +72,13 @@ static void get_default_min_max_freq(enum motionsensor_type type,
switch (type) {
case MOTIONSENSE_TYPE_ACCEL:
- case MOTIONSENSE_TYPE_GYRO:
*min_freq = 12500;
*max_freq = 100000;
break;
+ case MOTIONSENSE_TYPE_GYRO:
+ *min_freq = 25000;
+ *max_freq = 100000;
+ break;
case MOTIONSENSE_TYPE_MAG:
*min_freq = 5000;
*max_freq = 25000;
@@ -281,7 +284,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 +354,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 +826,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");
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
index 906d87780419..ff375790b7e8 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
@@ -13,6 +13,8 @@
#include <linux/hid-sensor-hub.h>
#include <linux/iio/iio.h>
#include <linux/iio/trigger.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
#include <linux/iio/buffer.h>
#include <linux/iio/sysfs.h>
#include "hid-sensor-trigger.h"
@@ -222,7 +224,8 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig,
return hid_sensor_power_state(iio_trigger_get_drvdata(trig), state);
}
-void hid_sensor_remove_trigger(struct hid_sensor_common *attrb)
+void hid_sensor_remove_trigger(struct iio_dev *indio_dev,
+ struct hid_sensor_common *attrb)
{
if (atomic_read(&attrb->runtime_pm_enable))
pm_runtime_disable(&attrb->pdev->dev);
@@ -233,6 +236,7 @@ void hid_sensor_remove_trigger(struct hid_sensor_common *attrb)
cancel_work_sync(&attrb->work);
iio_trigger_unregister(attrb->trigger);
iio_trigger_free(attrb->trigger);
+ iio_triggered_buffer_cleanup(indio_dev);
}
EXPORT_SYMBOL(hid_sensor_remove_trigger);
@@ -246,11 +250,18 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
int ret;
struct iio_trigger *trig;
+ ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+ NULL, NULL);
+ if (ret) {
+ dev_err(&indio_dev->dev, "Triggered Buffer Setup Failed\n");
+ return ret;
+ }
+
trig = iio_trigger_alloc("%s-dev%d", name, indio_dev->id);
if (trig == NULL) {
dev_err(&indio_dev->dev, "Trigger Allocate Failed\n");
ret = -ENOMEM;
- goto error_ret;
+ goto error_triggered_buffer_cleanup;
}
trig->dev.parent = indio_dev->dev.parent;
@@ -284,7 +295,8 @@ error_unreg_trigger:
iio_trigger_unregister(trig);
error_free_trig:
iio_trigger_free(trig);
-error_ret:
+error_triggered_buffer_cleanup:
+ iio_triggered_buffer_cleanup(indio_dev);
return ret;
}
EXPORT_SYMBOL(hid_sensor_setup_trigger);
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.h b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h
index f47b940ff170..bb45cc89e551 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.h
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h
@@ -13,7 +13,8 @@ extern const struct dev_pm_ops hid_sensor_pm_ops;
int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
struct hid_sensor_common *attrb);
-void hid_sensor_remove_trigger(struct hid_sensor_common *attrb);
+void hid_sensor_remove_trigger(struct iio_dev *indio_dev,
+ struct hid_sensor_common *attrb);
int hid_sensor_power_state(struct hid_sensor_common *st, bool state);
#endif
diff --git a/drivers/iio/common/ms_sensors/ms_sensors_i2c.c b/drivers/iio/common/ms_sensors/ms_sensors_i2c.c
index b52cba1b3c83..b9e2038d05ef 100644
--- a/drivers/iio/common/ms_sensors/ms_sensors_i2c.c
+++ b/drivers/iio/common/ms_sensors/ms_sensors_i2c.c
@@ -165,7 +165,7 @@ static bool ms_sensors_crc_valid(u32 value)
/**
* ms_sensors_read_serial() - Serial number read function
- * @cli: pointer to i2c client
+ * @client: pointer to i2c client
* @sn: pointer to 64-bits destination value
*
* Generic i2c serial number read function for Measurement Specialties devices.
diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c
index 13bdfbbf5f71..7a69c1be7393 100644
--- a/drivers/iio/common/st_sensors/st_sensors_core.c
+++ b/drivers/iio/common/st_sensors/st_sensors_core.c
@@ -20,11 +20,6 @@
#include "st_sensors_core.h"
-static inline u32 st_sensors_get_unaligned_le24(const u8 *p)
-{
- return (s32)((p[0] | p[1] << 8 | p[2] << 16) << 8) >> 8;
-}
-
int st_sensors_write_data_with_mask(struct iio_dev *indio_dev,
u8 reg_addr, u8 mask, u8 data)
{
@@ -150,8 +145,7 @@ static int st_sensors_set_fullscale(struct iio_dev *indio_dev, unsigned int fs)
if (err < 0)
goto st_accel_set_fullscale_error;
- sdata->current_fullscale = (struct st_sensor_fullscale_avl *)
- &sdata->sensor_settings->fs.fs_avl[i];
+ sdata->current_fullscale = &sdata->sensor_settings->fs.fs_avl[i];
return err;
st_accel_set_fullscale_error:
@@ -278,8 +272,7 @@ static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev,
!sdata->sensor_settings->drdy_irq.int2.addr) {
if (pdata->drdy_int_pin)
dev_info(&indio_dev->dev,
- "DRDY on pin INT%d specified, but sensor "
- "does not support interrupts\n",
+ "DRDY on pin INT%d specified, but sensor does not support interrupts\n",
pdata->drdy_int_pin);
return 0;
}
@@ -545,7 +538,7 @@ static int st_sensors_read_axis_data(struct iio_dev *indio_dev,
else if (byte_for_channel == 2)
*data = (s16)get_unaligned_le16(outdata);
else if (byte_for_channel == 3)
- *data = (s32)st_sensors_get_unaligned_le24(outdata);
+ *data = (s32)sign_extend32(get_unaligned_le24(outdata), 23);
st_sensors_free_memory:
kfree(outdata);
diff --git a/drivers/iio/common/st_sensors/st_sensors_i2c.c b/drivers/iio/common/st_sensors/st_sensors_i2c.c
index 286830fb5d35..b9e59ad32a02 100644
--- a/drivers/iio/common/st_sensors/st_sensors_i2c.c
+++ b/drivers/iio/common/st_sensors/st_sensors_i2c.c
@@ -49,14 +49,13 @@ int st_sensors_i2c_configure(struct iio_dev *indio_dev,
sdata->regmap = devm_regmap_init_i2c(client, config);
if (IS_ERR(sdata->regmap)) {
- dev_err(&client->dev, "Failed to register i2c regmap (%d)\n",
- (int)PTR_ERR(sdata->regmap));
+ dev_err(&client->dev, "Failed to register i2c regmap (%ld)\n",
+ PTR_ERR(sdata->regmap));
return PTR_ERR(sdata->regmap);
}
i2c_set_clientdata(client, indio_dev);
- indio_dev->dev.parent = &client->dev;
indio_dev->name = client->name;
sdata->dev = &client->dev;
diff --git a/drivers/iio/common/st_sensors/st_sensors_spi.c b/drivers/iio/common/st_sensors/st_sensors_spi.c
index 1275fb0eda31..48fc41dc5633 100644
--- a/drivers/iio/common/st_sensors/st_sensors_spi.c
+++ b/drivers/iio/common/st_sensors/st_sensors_spi.c
@@ -44,7 +44,7 @@ static bool st_sensors_is_spi_3_wire(struct spi_device *spi)
if (device_property_read_bool(dev, "spi-3wire"))
return true;
- pdata = (struct st_sensors_platform_data *)dev->platform_data;
+ pdata = dev_get_platdata(dev);
if (pdata && pdata->spi_3wire)
return true;
@@ -101,14 +101,13 @@ int st_sensors_spi_configure(struct iio_dev *indio_dev,
sdata->regmap = devm_regmap_init_spi(spi, config);
if (IS_ERR(sdata->regmap)) {
- dev_err(&spi->dev, "Failed to register spi regmap (%d)\n",
- (int)PTR_ERR(sdata->regmap));
+ dev_err(&spi->dev, "Failed to register spi regmap (%ld)\n",
+ PTR_ERR(sdata->regmap));
return PTR_ERR(sdata->regmap);
}
spi_set_drvdata(spi, indio_dev);
- indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi->modalias;
sdata->dev = &spi->dev;
diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c
index e817537cdfb5..0507283bd4c1 100644
--- a/drivers/iio/common/st_sensors/st_sensors_trigger.c
+++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c
@@ -44,8 +44,7 @@ static int st_sensors_new_samples_available(struct iio_dev *indio_dev,
sdata->sensor_settings->drdy_irq.stat_drdy.addr,
&status);
if (ret < 0) {
- dev_err(sdata->dev,
- "error checking samples available\n");
+ dev_err(sdata->dev, "error checking samples available\n");
return ret;
}
@@ -148,9 +147,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
case IRQF_TRIGGER_LOW:
if (!sdata->sensor_settings->drdy_irq.addr_ihl) {
dev_err(&indio_dev->dev,
- "falling/low specified for IRQ "
- "but hardware supports only rising/high: "
- "will request rising/high\n");
+ "falling/low specified for IRQ but hardware supports only rising/high: will request rising/high\n");
if (irq_trig == IRQF_TRIGGER_FALLING)
irq_trig = IRQF_TRIGGER_RISING;
if (irq_trig == IRQF_TRIGGER_LOW)
@@ -163,8 +160,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
if (err < 0)
goto iio_trigger_free;
dev_info(&indio_dev->dev,
- "interrupts on the falling edge or "
- "active low level\n");
+ "interrupts on the falling edge or active low level\n");
}
break;
case IRQF_TRIGGER_RISING:
@@ -178,8 +174,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
default:
/* This is the most preferred mode, if possible */
dev_err(&indio_dev->dev,
- "unsupported IRQ trigger specified (%lx), enforce "
- "rising edge\n", irq_trig);
+ "unsupported IRQ trigger specified (%lx), enforce rising edge\n", irq_trig);
irq_trig = IRQF_TRIGGER_RISING;
}
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index 93744011b63f..dae8d27e772d 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -279,12 +279,12 @@ config LTC1660
module will be called ltc1660.
config LTC2632
- tristate "Linear Technology LTC2632-12/10/8 and LTC2636-12/10/8 DAC spi driver"
+ tristate "Linear Technology LTC2632-12/10/8 and similar DAC spi driver"
depends on SPI
help
Say yes here to build support for Linear Technology
- LTC2632-12, LTC2632-10, LTC2632-8, LTC2636-12, LTC2636-10 and
- LTC2636-8 converters (DAC).
+ LTC2632, LTC2634 and LTC2636 DAC resolution 12/10/8 bit
+ low 0-2.5V and high 0-4.096V range converters.
To compile this driver as a module, choose M here: the
module will be called ltc2632.
@@ -325,7 +325,7 @@ config MAX5821
config MCP4725
tristate "MCP4725/6 DAC driver"
depends on I2C
- ---help---
+ help
Say Y here if you want to build a driver for the Microchip
MCP 4725/6 12-bit digital-to-analog converter (DAC) with I2C
interface.
diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c
index d33642de9720..fef503f8012d 100644
--- a/drivers/iio/dac/ad5064.c
+++ b/drivers/iio/dac/ad5064.c
@@ -787,7 +787,7 @@ static const char * const ad5064_vref_names[] = {
"vrefD",
};
-static const char * const ad5064_vref_name(struct ad5064_state *st,
+static const char *ad5064_vref_name(struct ad5064_state *st,
unsigned int vref)
{
return st->chip_info->shared_vref ? "vref" : ad5064_vref_names[vref];
@@ -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;
diff --git a/drivers/iio/dac/ad5360.c b/drivers/iio/dac/ad5360.c
index 2ac428b957e3..602dd2ba61b5 100644
--- a/drivers/iio/dac/ad5360.c
+++ b/drivers/iio/dac/ad5360.c
@@ -67,6 +67,7 @@ struct ad5360_chip_info {
* @chip_info: chip model specific constants, available modes etc
* @vref_reg: vref supply regulators
* @ctrl: control register cache
+ * @lock: lock to protect the data buffer during SPI ops
* @data: spi transfer buffers
*/
@@ -75,6 +76,7 @@ struct ad5360_state {
const struct ad5360_chip_info *chip_info;
struct regulator_bulk_data vref_reg[3];
unsigned int ctrl;
+ struct mutex lock;
/*
* DMA (thus cache coherency maintenance) requires the
@@ -205,10 +207,11 @@ static int ad5360_write(struct iio_dev *indio_dev, unsigned int cmd,
unsigned int addr, unsigned int val, unsigned int shift)
{
int ret;
+ struct ad5360_state *st = iio_priv(indio_dev);
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
ret = ad5360_write_unlocked(indio_dev, cmd, addr, val, shift);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret;
}
@@ -229,7 +232,7 @@ static int ad5360_read(struct iio_dev *indio_dev, unsigned int type,
},
};
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
st->data[0].d32 = cpu_to_be32(AD5360_CMD(AD5360_CMD_SPECIAL_FUNCTION) |
AD5360_ADDR(AD5360_REG_SF_READBACK) |
@@ -240,7 +243,7 @@ static int ad5360_read(struct iio_dev *indio_dev, unsigned int type,
if (ret >= 0)
ret = be32_to_cpu(st->data[1].d32) & 0xffff;
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret;
}
@@ -261,7 +264,7 @@ static int ad5360_update_ctrl(struct iio_dev *indio_dev, unsigned int set,
struct ad5360_state *st = iio_priv(indio_dev);
unsigned int ret;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
st->ctrl |= set;
st->ctrl &= ~clr;
@@ -269,7 +272,7 @@ static int ad5360_update_ctrl(struct iio_dev *indio_dev, unsigned int set,
ret = ad5360_write_unlocked(indio_dev, AD5360_CMD_SPECIAL_FUNCTION,
AD5360_REG_SF_CTRL, st->ctrl, 0);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret;
}
@@ -473,12 +476,13 @@ 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;
indio_dev->num_channels = st->chip_info->num_channels;
+ mutex_init(&st->lock);
+
ret = ad5360_alloc_channels(indio_dev);
if (ret) {
dev_err(&spi->dev, "Failed to allocate channel spec: %d\n", ret);
diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c
index 2ebe08326048..37ef653564b0 100644
--- a/drivers/iio/dac/ad5380.c
+++ b/drivers/iio/dac/ad5380.c
@@ -51,6 +51,7 @@ struct ad5380_chip_info {
* @vref_reg: vref supply regulator
* @vref: actual reference voltage used in uA
* @pwr_down: whether the chip is currently in power down mode
+ * @lock: lock to protect the data buffer during regmap ops
*/
struct ad5380_state {
@@ -59,6 +60,7 @@ struct ad5380_state {
struct regulator *vref_reg;
int vref;
bool pwr_down;
+ struct mutex lock;
};
enum ad5380_type {
@@ -98,7 +100,7 @@ static ssize_t ad5380_write_dac_powerdown(struct iio_dev *indio_dev,
if (ret)
return ret;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
if (pwr_down)
ret = regmap_write(st->regmap, AD5380_REG_SF_PWR_DOWN, 0);
@@ -107,7 +109,7 @@ static ssize_t ad5380_write_dac_powerdown(struct iio_dev *indio_dev,
st->pwr_down = pwr_down;
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret ? ret : len;
}
@@ -238,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,
@@ -384,12 +386,13 @@ 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;
indio_dev->num_channels = st->chip_info->num_channels;
+ mutex_init(&st->lock);
+
ret = ad5380_alloc_channels(indio_dev);
if (ret) {
dev_err(dev, "Failed to allocate channel spec: %d\n", ret);
diff --git a/drivers/iio/dac/ad5421.c b/drivers/iio/dac/ad5421.c
index 63063e85cd0a..eedf661d32b2 100644
--- a/drivers/iio/dac/ad5421.c
+++ b/drivers/iio/dac/ad5421.c
@@ -62,12 +62,14 @@
* @current_range: current range which the device is configured for
* @data: spi transfer buffers
* @fault_mask: software masking of events
+ * @lock: lock to protect the data buffer during SPI ops
*/
struct ad5421_state {
struct spi_device *spi;
unsigned int ctrl;
enum ad5421_current_range current_range;
unsigned int fault_mask;
+ struct mutex lock;
/*
* DMA (thus cache coherency maintenance) requires the
@@ -142,11 +144,12 @@ static int ad5421_write_unlocked(struct iio_dev *indio_dev,
static int ad5421_write(struct iio_dev *indio_dev, unsigned int reg,
unsigned int val)
{
+ struct ad5421_state *st = iio_priv(indio_dev);
int ret;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
ret = ad5421_write_unlocked(indio_dev, reg, val);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret;
}
@@ -166,7 +169,7 @@ static int ad5421_read(struct iio_dev *indio_dev, unsigned int reg)
},
};
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
st->data[0].d32 = cpu_to_be32((1 << 23) | (reg << 16));
@@ -174,7 +177,7 @@ static int ad5421_read(struct iio_dev *indio_dev, unsigned int reg)
if (ret >= 0)
ret = be32_to_cpu(st->data[1].d32) & 0xffff;
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret;
}
@@ -185,14 +188,14 @@ static int ad5421_update_ctrl(struct iio_dev *indio_dev, unsigned int set,
struct ad5421_state *st = iio_priv(indio_dev);
unsigned int ret;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
st->ctrl &= ~clr;
st->ctrl |= set;
ret = ad5421_write_unlocked(indio_dev, AD5421_REG_CTRL, st->ctrl);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret;
}
@@ -400,12 +403,12 @@ static int ad5421_write_event_config(struct iio_dev *indio_dev,
return -EINVAL;
}
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
if (state)
st->fault_mask |= mask;
else
st->fault_mask &= ~mask;
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return 0;
}
@@ -484,13 +487,14 @@ 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;
indio_dev->channels = ad5421_channels;
indio_dev->num_channels = ARRAY_SIZE(ad5421_channels);
+ mutex_init(&st->lock);
+
st->ctrl = AD5421_CTRL_WATCHDOG_DISABLE |
AD5421_CTRL_AUTO_FAULT_READBACK;
diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c
index 61c670f7fc5f..935a6177569f 100644
--- a/drivers/iio/dac/ad5446.c
+++ b/drivers/iio/dac/ad5446.c
@@ -21,16 +21,22 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <asm/unaligned.h>
+
#define MODE_PWRDWN_1k 0x1
#define MODE_PWRDWN_100k 0x2
#define MODE_PWRDWN_TRISTATE 0x3
/**
* struct ad5446_state - driver instance specific data
- * @spi: spi_device
+ * @dev: this device
* @chip_info: chip model specific constants, available modes etc
* @reg: supply regulator
* @vref_mv: actual reference voltage used
+ * @cached_val: store/retrieve values during power down
+ * @pwr_down_mode: power down mode (1k, 100k or tristate)
+ * @pwr_down: true if the device is in power down
+ * @lock: lock to protect the data buffer during write ops
*/
struct ad5446_state {
@@ -41,6 +47,7 @@ struct ad5446_state {
unsigned cached_val;
unsigned pwr_down_mode;
unsigned pwr_down;
+ struct mutex lock;
};
/**
@@ -110,7 +117,7 @@ static ssize_t ad5446_write_dac_powerdown(struct iio_dev *indio_dev,
if (ret)
return ret;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
st->pwr_down = powerdown;
if (st->pwr_down) {
@@ -121,7 +128,7 @@ static ssize_t ad5446_write_dac_powerdown(struct iio_dev *indio_dev,
}
ret = st->chip_info->write(st, val);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret ? ret : len;
}
@@ -195,11 +202,11 @@ static int ad5446_write_raw(struct iio_dev *indio_dev,
return -EINVAL;
val <<= chan->scan_type.shift;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
st->cached_val = val;
if (!st->pwr_down)
ret = st->chip_info->write(st, val);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
break;
default:
ret = -EINVAL;
@@ -246,14 +253,14 @@ 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;
indio_dev->channels = &st->chip_info->channel;
indio_dev->num_channels = 1;
+ mutex_init(&st->lock);
+
st->pwr_down_mode = MODE_PWRDWN_1k;
if (st->chip_info->int_vref_mv)
@@ -302,14 +309,12 @@ static int ad5660_write(struct ad5446_state *st, unsigned val)
struct spi_device *spi = to_spi_device(st->dev);
uint8_t data[3];
- data[0] = (val >> 16) & 0xFF;
- data[1] = (val >> 8) & 0xFF;
- data[2] = val & 0xFF;
+ put_unaligned_be24(val, &data[0]);
return spi_write(spi, data, sizeof(data));
}
-/**
+/*
* ad5446_supported_spi_device_ids:
* The AD5620/40/60 parts are available in different fixed internal reference
* voltage options. The actual part numbers may look differently
@@ -531,7 +536,7 @@ static int ad5622_write(struct ad5446_state *st, unsigned val)
return i2c_master_send(client, (char *)&data, sizeof(data));
}
-/**
+/*
* ad5446_supported_i2c_device_ids:
* The AD5620/40/60 parts are available in different fixed internal reference
* voltage options. The actual part numbers may look differently
diff --git a/drivers/iio/dac/ad5449.c b/drivers/iio/dac/ad5449.c
index fed3ebaccac4..f5e93c6acc9d 100644
--- a/drivers/iio/dac/ad5449.c
+++ b/drivers/iio/dac/ad5449.c
@@ -56,11 +56,13 @@ struct ad5449_chip_info {
* @has_sdo: whether the SDO line is connected
* @dac_cache: Cache for the DAC values
* @data: spi transfer buffers
+ * @lock: lock to protect the data buffer during SPI ops
*/
struct ad5449 {
struct spi_device *spi;
const struct ad5449_chip_info *chip_info;
struct regulator_bulk_data vref_reg[AD5449_MAX_VREFS];
+ struct mutex lock;
bool has_sdo;
uint16_t dac_cache[AD5449_MAX_CHANNELS];
@@ -87,10 +89,10 @@ static int ad5449_write(struct iio_dev *indio_dev, unsigned int addr,
struct ad5449 *st = iio_priv(indio_dev);
int ret;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
st->data[0] = cpu_to_be16((addr << 12) | val);
ret = spi_write(st->spi, st->data, 2);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret;
}
@@ -112,7 +114,7 @@ static int ad5449_read(struct iio_dev *indio_dev, unsigned int addr,
},
};
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
st->data[0] = cpu_to_be16(addr << 12);
st->data[1] = cpu_to_be16(AD5449_CMD_NOOP);
@@ -123,7 +125,7 @@ static int ad5449_read(struct iio_dev *indio_dev, unsigned int addr,
*val = be16_to_cpu(st->data[1]);
out_unlock:
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret;
}
@@ -295,13 +297,14 @@ 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;
indio_dev->channels = st->chip_info->channels;
indio_dev->num_channels = st->chip_info->num_channels;
+ mutex_init(&st->lock);
+
if (st->chip_info->has_ctrl) {
unsigned int ctrl = 0x00;
if (pdata) {
diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c
index c64e6898ff20..28921b62e642 100644
--- a/drivers/iio/dac/ad5504.c
+++ b/drivers/iio/dac/ad5504.c
@@ -43,8 +43,8 @@
* @spi: spi_device
* @reg: supply regulator
* @vref_mv: actual reference voltage used
- * @pwr_down_mask power down mask
- * @pwr_down_mode current power down mode
+ * @pwr_down_mask: power down mask
+ * @pwr_down_mode: current power down mode
* @data: transfer buffer
*/
struct ad5504_state {
@@ -57,10 +57,9 @@ struct ad5504_state {
__be16 data[2] ____cacheline_aligned;
};
-/**
+/*
* ad5504_supported_device_ids:
*/
-
enum ad5504_supported_device_ids {
ID_AD5504,
ID_AD5501,
@@ -304,7 +303,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)
diff --git a/drivers/iio/dac/ad5592r-base.c b/drivers/iio/dac/ad5592r-base.c
index e2110113e884..1fd75c02a7cd 100644
--- a/drivers/iio/dac/ad5592r-base.c
+++ b/drivers/iio/dac/ad5592r-base.c
@@ -156,7 +156,6 @@ static void ad5592r_gpio_cleanup(struct ad5592r_state *st)
static int ad5592r_reset(struct ad5592r_state *st)
{
struct gpio_desc *gpio;
- struct iio_dev *iio_dev = iio_priv_to_dev(st);
gpio = devm_gpiod_get_optional(st->dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(gpio))
@@ -166,10 +165,10 @@ static int ad5592r_reset(struct ad5592r_state *st)
udelay(1);
gpiod_set_value(gpio, 1);
} else {
- mutex_lock(&iio_dev->mlock);
+ mutex_lock(&st->lock);
/* Writing this magic value resets the device */
st->ops->reg_write(st, AD5592R_REG_RESET, 0xdac);
- mutex_unlock(&iio_dev->mlock);
+ mutex_unlock(&st->lock);
}
udelay(250);
@@ -197,7 +196,6 @@ static int ad5592r_set_channel_modes(struct ad5592r_state *st)
const struct ad5592r_rw_ops *ops = st->ops;
int ret;
unsigned i;
- struct iio_dev *iio_dev = iio_priv_to_dev(st);
u8 pulldown = 0, tristate = 0, dac = 0, adc = 0;
u16 read_back;
@@ -222,7 +220,6 @@ static int ad5592r_set_channel_modes(struct ad5592r_state *st)
break;
case CH_MODE_UNUSED:
- /* fall-through */
default:
switch (st->channel_offstate[i]) {
case CH_OFFSTATE_OUT_TRISTATE:
@@ -239,7 +236,6 @@ static int ad5592r_set_channel_modes(struct ad5592r_state *st)
break;
case CH_OFFSTATE_PULLDOWN:
- /* fall-through */
default:
pulldown |= BIT(i);
break;
@@ -247,7 +243,7 @@ static int ad5592r_set_channel_modes(struct ad5592r_state *st)
}
}
- mutex_lock(&iio_dev->mlock);
+ mutex_lock(&st->lock);
/* Pull down unused pins to GND */
ret = ops->reg_write(st, AD5592R_REG_PULLDOWN, pulldown);
@@ -285,7 +281,7 @@ static int ad5592r_set_channel_modes(struct ad5592r_state *st)
ret = -EIO;
err_unlock:
- mutex_unlock(&iio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret;
}
@@ -314,11 +310,11 @@ static int ad5592r_write_raw(struct iio_dev *iio_dev,
if (!chan->output)
return -EINVAL;
- mutex_lock(&iio_dev->mlock);
+ mutex_lock(&st->lock);
ret = st->ops->write_dac(st, chan->channel, val);
if (!ret)
st->cached_dac[chan->channel] = val;
- mutex_unlock(&iio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret;
case IIO_CHAN_INFO_SCALE:
if (chan->type == IIO_VOLTAGE) {
@@ -333,12 +329,12 @@ static int ad5592r_write_raw(struct iio_dev *iio_dev,
else
return -EINVAL;
- mutex_lock(&iio_dev->mlock);
+ mutex_lock(&st->lock);
ret = st->ops->reg_read(st, AD5592R_REG_CTRL,
&st->cached_gp_ctrl);
if (ret < 0) {
- mutex_unlock(&iio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret;
}
@@ -360,7 +356,7 @@ static int ad5592r_write_raw(struct iio_dev *iio_dev,
ret = st->ops->reg_write(st, AD5592R_REG_CTRL,
st->cached_gp_ctrl);
- mutex_unlock(&iio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret;
}
@@ -382,7 +378,7 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev,
switch (m) {
case IIO_CHAN_INFO_RAW:
- mutex_lock(&iio_dev->mlock);
+ mutex_lock(&st->lock);
if (!chan->output) {
ret = st->ops->read_adc(st, chan->channel, &read_val);
@@ -415,11 +411,11 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev,
s64 tmp = *val * (3767897513LL / 25LL);
*val = div_s64_rem(tmp, 1000000000LL, val2);
- ret = IIO_VAL_INT_PLUS_MICRO;
+ return IIO_VAL_INT_PLUS_MICRO;
} else {
int mult;
- mutex_lock(&iio_dev->mlock);
+ mutex_lock(&st->lock);
if (chan->output)
mult = !!(st->cached_gp_ctrl &
@@ -437,7 +433,7 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev,
case IIO_CHAN_INFO_OFFSET:
ret = ad5592r_get_vref(st);
- mutex_lock(&iio_dev->mlock);
+ mutex_lock(&st->lock);
if (st->cached_gp_ctrl & AD5592R_REG_CTRL_ADC_RANGE)
*val = (-34365 * 25) / ret;
@@ -446,11 +442,11 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev,
ret = IIO_VAL_INT;
break;
default:
- ret = -EINVAL;
+ return -EINVAL;
}
unlock:
- mutex_unlock(&iio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret;
}
@@ -486,7 +482,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,
@@ -510,11 +506,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;
@@ -620,11 +616,12 @@ 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;
+ mutex_init(&st->lock);
+
ad5592r_init_scales(st, ad5592r_get_vref(st));
ret = ad5592r_reset(st);
@@ -636,7 +633,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;
diff --git a/drivers/iio/dac/ad5592r-base.h b/drivers/iio/dac/ad5592r-base.h
index 4774e4cd9c11..23dac2f1ff8a 100644
--- a/drivers/iio/dac/ad5592r-base.h
+++ b/drivers/iio/dac/ad5592r-base.h
@@ -52,6 +52,7 @@ struct ad5592r_state {
struct regulator *reg;
struct gpio_chip gpiochip;
struct mutex gpio_lock; /* Protect cached gpio_out, gpio_val, etc. */
+ struct mutex lock;
unsigned int num_channels;
const struct ad5592r_rw_ops *ops;
int scale_avail[2][2];
diff --git a/drivers/iio/dac/ad5592r.c b/drivers/iio/dac/ad5592r.c
index 34ba059a77da..49308ad13c4b 100644
--- a/drivers/iio/dac/ad5592r.c
+++ b/drivers/iio/dac/ad5592r.c
@@ -98,7 +98,7 @@ static int ad5592r_reg_read(struct ad5592r_state *st, u8 reg, u16 *value)
return 0;
}
-static int ad5593r_gpio_read(struct ad5592r_state *st, u8 *value)
+static int ad5592r_gpio_read(struct ad5592r_state *st, u8 *value)
{
int ret;
@@ -121,7 +121,7 @@ static const struct ad5592r_rw_ops ad5592r_rw_ops = {
.read_adc = ad5592r_read_adc,
.reg_write = ad5592r_reg_write,
.reg_read = ad5592r_reg_read,
- .gpio_read = ad5593r_gpio_read,
+ .gpio_read = ad5592r_gpio_read,
};
static int ad5592r_spi_probe(struct spi_device *spi)
diff --git a/drivers/iio/dac/ad5593r.c b/drivers/iio/dac/ad5593r.c
index 44ea3b8117d0..1fbe9c019c7f 100644
--- a/drivers/iio/dac/ad5593r.c
+++ b/drivers/iio/dac/ad5593r.c
@@ -134,5 +134,5 @@ static struct i2c_driver ad5593r_driver = {
module_i2c_driver(ad5593r_driver);
MODULE_AUTHOR("Paul Cercueil <paul.cercueil@analog.com>");
-MODULE_DESCRIPTION("Analog Devices AD5592R multi-channel converters");
+MODULE_DESCRIPTION("Analog Devices AD5593R multi-channel converters");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c
index e6c022e1dc1c..2b2b8edfd258 100644
--- a/drivers/iio/dac/ad5624r_spi.c
+++ b/drivers/iio/dac/ad5624r_spi.c
@@ -18,6 +18,8 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <asm/unaligned.h>
+
#include "ad5624r.h"
static int ad5624r_spi_write(struct spi_device *spi,
@@ -35,11 +37,9 @@ static int ad5624r_spi_write(struct spi_device *spi,
* for the AD5664R, AD5644R, and AD5624R, respectively.
*/
data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << shift);
- msg[0] = data >> 16;
- msg[1] = data >> 8;
- msg[2] = data;
+ put_unaligned_be24(data, &msg[0]);
- return spi_write(spi, msg, 3);
+ return spi_write(spi, msg, sizeof(msg));
}
static int ad5624r_read_raw(struct iio_dev *indio_dev,
@@ -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;
diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index e06b29c565b9..56cf9344d187 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -127,9 +127,9 @@ static int ad5686_read_raw(struct iio_dev *indio_dev,
switch (m) {
case IIO_CHAN_INFO_RAW:
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
ret = st->read(st, chan->address);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
if (ret < 0)
return ret;
*val = (ret >> chan->scan_type.shift) &
@@ -157,12 +157,12 @@ static int ad5686_write_raw(struct iio_dev *indio_dev,
if (val > (1 << chan->scan_type.realbits) || val < 0)
return -EINVAL;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
ret = st->write(st,
AD5686_CMD_WRITE_INPUT_N_UPDATE_N,
chan->address,
val << chan->scan_type.shift);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
break;
default:
ret = -EINVAL;
@@ -461,13 +461,14 @@ 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;
indio_dev->channels = st->chip_info->channels;
indio_dev->num_channels = st->chip_info->num_channels;
+ mutex_init(&st->lock);
+
switch (st->chip_info->regmap_type) {
case AD5310_REGMAP:
cmd = AD5686_CMD_CONTROL_REG;
diff --git a/drivers/iio/dac/ad5686.h b/drivers/iio/dac/ad5686.h
index 70a779939ddb..52009b5eef88 100644
--- a/drivers/iio/dac/ad5686.h
+++ b/drivers/iio/dac/ad5686.h
@@ -117,6 +117,7 @@ struct ad5686_chip_info {
* @pwr_down_mask: power down mask
* @pwr_down_mode: current power down mode
* @use_internal_vref: set to true if the internal reference voltage is used
+ * @lock lock to protect the data buffer during regmap ops
* @data: spi transfer buffers
*/
@@ -130,6 +131,7 @@ struct ad5686_state {
ad5686_write_func write;
ad5686_read_func read;
bool use_internal_vref;
+ struct mutex lock;
/*
* DMA (thus cache coherency maintenance) requires the
diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c
index 388ddd14bfd0..0df28acf074a 100644
--- a/drivers/iio/dac/ad5755.c
+++ b/drivers/iio/dac/ad5755.c
@@ -82,6 +82,7 @@ struct ad5755_chip_info {
* @pwr_down: bitmask which contains hether a channel is powered down or not
* @ctrl: software shadow of the channel ctrl registers
* @channels: iio channel spec for the device
+ * @lock: lock to protect the data buffer during SPI ops
* @data: spi transfer buffers
*/
struct ad5755_state {
@@ -90,6 +91,7 @@ struct ad5755_state {
unsigned int pwr_down;
unsigned int ctrl[AD5755_NUM_CHANNELS];
struct iio_chan_spec channels[AD5755_NUM_CHANNELS];
+ struct mutex lock;
/*
* DMA (thus cache coherency maintenance) requires the
@@ -174,11 +176,12 @@ static int ad5755_write_ctrl_unlocked(struct iio_dev *indio_dev,
static int ad5755_write(struct iio_dev *indio_dev, unsigned int reg,
unsigned int val)
{
+ struct ad5755_state *st = iio_priv(indio_dev);
int ret;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
ret = ad5755_write_unlocked(indio_dev, reg, val);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret;
}
@@ -186,11 +189,12 @@ static int ad5755_write(struct iio_dev *indio_dev, unsigned int reg,
static int ad5755_write_ctrl(struct iio_dev *indio_dev, unsigned int channel,
unsigned int reg, unsigned int val)
{
+ struct ad5755_state *st = iio_priv(indio_dev);
int ret;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
ret = ad5755_write_ctrl_unlocked(indio_dev, channel, reg, val);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret;
}
@@ -211,7 +215,7 @@ static int ad5755_read(struct iio_dev *indio_dev, unsigned int addr)
},
};
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
st->data[0].d32 = cpu_to_be32(AD5755_READ_FLAG | (addr << 16));
st->data[1].d32 = cpu_to_be32(AD5755_NOOP);
@@ -220,7 +224,7 @@ static int ad5755_read(struct iio_dev *indio_dev, unsigned int addr)
if (ret >= 0)
ret = be32_to_cpu(st->data[1].d32) & 0xffff;
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret;
}
@@ -246,7 +250,7 @@ static int ad5755_set_channel_pwr_down(struct iio_dev *indio_dev,
struct ad5755_state *st = iio_priv(indio_dev);
unsigned int mask = BIT(channel);
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
if ((bool)(st->pwr_down & mask) == pwr_down)
goto out_unlock;
@@ -266,7 +270,7 @@ static int ad5755_set_channel_pwr_down(struct iio_dev *indio_dev,
}
out_unlock:
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return 0;
}
@@ -740,12 +744,13 @@ 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;
indio_dev->num_channels = AD5755_NUM_CHANNELS;
+ mutex_init(&st->lock);
+
if (spi->dev.of_node)
pdata = ad5755_parse_dt(&spi->dev);
else
diff --git a/drivers/iio/dac/ad5758.c b/drivers/iio/dac/ad5758.c
index 475646c82b40..bd9ac8359d98 100644
--- a/drivers/iio/dac/ad5758.c
+++ b/drivers/iio/dac/ad5758.c
@@ -92,24 +92,24 @@
#define AD5758_FULL_SCALE_MICRO 65535000000ULL
+struct ad5758_range {
+ int reg;
+ int min;
+ int max;
+};
+
/**
* struct ad5758_state - driver instance specific data
* @spi: spi_device
* @lock: mutex lock
+ * @gpio_reset: gpio descriptor for the reset line
* @out_range: struct which stores the output range
* @dc_dc_mode: variable which stores the mode of operation
* @dc_dc_ilim: variable which stores the dc-to-dc converter current limit
* @slew_time: variable which stores the target slew time
* @pwr_down: variable which contains whether a channel is powered down or not
- * @data: spi transfer buffers
+ * @d32: spi transfer buffers
*/
-
-struct ad5758_range {
- int reg;
- int min;
- int max;
-};
-
struct ad5758_state {
struct spi_device *spi;
struct mutex lock;
@@ -122,7 +122,7 @@ struct ad5758_state {
__be32 d32[3];
};
-/**
+/*
* Output ranges corresponding to bits [3:0] from DAC_CONFIG register
* 0000: 0 V to 5 V voltage range
* 0001: 0 V to 10 V voltage range
@@ -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;
diff --git a/drivers/iio/dac/ad5761.c b/drivers/iio/dac/ad5761.c
index 4fb42b743f0f..e37e095e94fc 100644
--- a/drivers/iio/dac/ad5761.c
+++ b/drivers/iio/dac/ad5761.c
@@ -3,7 +3,7 @@
* AD5721, AD5721R, AD5761, AD5761R, Voltage Output Digital to Analog Converter
*
* Copyright 2016 Qtechnology A/S
- * 2016 Ricardo Ribalda <ricardo.ribalda@gmail.com>
+ * 2016 Ricardo Ribalda <ribalda@kernel.org>
*/
#include <linux/kernel.h>
#include <linux/module.h>
@@ -57,11 +57,13 @@ enum ad5761_supported_device_ids {
* @use_intref: true when the internal voltage reference is used
* @vref: actual voltage reference in mVolts
* @range: output range mode used
+ * @lock: lock to protect the data buffer during SPI ops
* @data: cache aligned spi buffer
*/
struct ad5761_state {
struct spi_device *spi;
struct regulator *vref_reg;
+ struct mutex lock;
bool use_intref;
int vref;
@@ -124,9 +126,9 @@ static int ad5761_spi_write(struct iio_dev *indio_dev, u8 addr, u16 val)
struct ad5761_state *st = iio_priv(indio_dev);
int ret;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
ret = _ad5761_spi_write(st, addr, val);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret;
}
@@ -163,9 +165,9 @@ static int ad5761_spi_read(struct iio_dev *indio_dev, u8 addr, u16 *val)
struct ad5761_state *st = iio_priv(indio_dev);
int ret;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
ret = _ad5761_spi_read(st, addr, val);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret;
}
@@ -368,11 +370,12 @@ static int ad5761_probe(struct spi_device *spi)
if (pdata)
voltage_range = pdata->voltage_range;
+ mutex_init(&st->lock);
+
ret = ad5761_spi_set_range(st, voltage_range);
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;
@@ -423,6 +426,6 @@ static struct spi_driver ad5761_driver = {
};
module_spi_driver(ad5761_driver);
-MODULE_AUTHOR("Ricardo Ribalda <ricardo.ribalda@gmail.com>");
+MODULE_AUTHOR("Ricardo Ribalda <ribalda@kernel.org>");
MODULE_DESCRIPTION("Analog Devices AD5721, AD5721R, AD5761, AD5761R driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/dac/ad5764.c b/drivers/iio/dac/ad5764.c
index f7ab211604a1..ae089b9145cb 100644
--- a/drivers/iio/dac/ad5764.c
+++ b/drivers/iio/dac/ad5764.c
@@ -33,9 +33,8 @@
* struct ad5764_chip_info - chip specific information
* @int_vref: Value of the internal reference voltage in uV - 0 if external
* reference voltage is used
- * @channel channel specification
+ * @channels: channel specification
*/
-
struct ad5764_chip_info {
unsigned long int_vref;
const struct iio_chan_spec *channels;
@@ -46,6 +45,7 @@ struct ad5764_chip_info {
* @spi: spi_device
* @chip_info: chip info
* @vref_reg: vref supply regulators
+ * @lock: lock to protect the data buffer during SPI ops
* @data: spi transfer buffers
*/
@@ -53,6 +53,7 @@ struct ad5764_state {
struct spi_device *spi;
const struct ad5764_chip_info *chip_info;
struct regulator_bulk_data vref_reg[2];
+ struct mutex lock;
/*
* DMA (thus cache coherency maintenance) requires the
@@ -126,11 +127,11 @@ static int ad5764_write(struct iio_dev *indio_dev, unsigned int reg,
struct ad5764_state *st = iio_priv(indio_dev);
int ret;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
st->data[0].d32 = cpu_to_be32((reg << 16) | val);
ret = spi_write(st->spi, &st->data[0].d8[1], 3);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret;
}
@@ -151,7 +152,7 @@ static int ad5764_read(struct iio_dev *indio_dev, unsigned int reg,
},
};
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&st->lock);
st->data[0].d32 = cpu_to_be32((1 << 23) | (reg << 16));
@@ -159,7 +160,7 @@ static int ad5764_read(struct iio_dev *indio_dev, unsigned int reg,
if (ret >= 0)
*val = be32_to_cpu(st->data[1].d32) & 0xffff;
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&st->lock);
return ret;
}
@@ -288,13 +289,14 @@ 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;
indio_dev->num_channels = AD5764_NUM_CHANNELS;
indio_dev->channels = st->chip_info->channels;
+ mutex_init(&st->lock);
+
if (st->chip_info->int_vref == 0) {
st->vref_reg[0].supply = "vrefAB";
st->vref_reg[1].supply = "vrefCD";
diff --git a/drivers/iio/dac/ad5770r.c b/drivers/iio/dac/ad5770r.c
index 2d7623b9b2c0..84dcf149261f 100644
--- a/drivers/iio/dac/ad5770r.c
+++ b/drivers/iio/dac/ad5770r.c
@@ -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;
diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c
index 1d11f39ed047..e3ffa4b9f84c 100644
--- a/drivers/iio/dac/ad5791.c
+++ b/drivers/iio/dac/ad5791.c
@@ -76,9 +76,11 @@ struct ad5791_chip_info {
* @chip_info: chip model specific constants
* @vref_mv: actual reference voltage used
* @vref_neg_mv: voltage of the negative supply
- * @pwr_down_mode current power down mode
+ * @ctrl: control regster cache
+ * @pwr_down_mode: current power down mode
+ * @pwr_down: true if device is powered down
+ * @data: spi transfer buffers
*/
-
struct ad5791_state {
struct spi_device *spi;
struct regulator *reg_vdd;
@@ -96,10 +98,6 @@ struct ad5791_state {
} data[3] ____cacheline_aligned;
};
-/**
- * ad5791_supported_device_ids:
- */
-
enum ad5791_supported_device_ids {
ID_AD5760,
ID_AD5780,
@@ -409,7 +407,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
diff --git a/drivers/iio/dac/ad7303.c b/drivers/iio/dac/ad7303.c
index 15af8a1cce3e..4460aa57a33f 100644
--- a/drivers/iio/dac/ad7303.c
+++ b/drivers/iio/dac/ad7303.c
@@ -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;
diff --git a/drivers/iio/dac/ad8801.c b/drivers/iio/dac/ad8801.c
index 0789c9100a8f..6354b7c8f052 100644
--- a/drivers/iio/dac/ad8801.c
+++ b/drivers/iio/dac/ad8801.c
@@ -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;
diff --git a/drivers/iio/dac/cio-dac.c b/drivers/iio/dac/cio-dac.c
index 81677795e57a..95813569f394 100644
--- a/drivers/iio/dac/cio-dac.c
+++ b/drivers/iio/dac/cio-dac.c
@@ -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];
diff --git a/drivers/iio/dac/dpot-dac.c b/drivers/iio/dac/dpot-dac.c
index 4a6111b7e86c..1a9609eda5c5 100644
--- a/drivers/iio/dac/dpot-dac.c
+++ b/drivers/iio/dac/dpot-dac.c
@@ -74,11 +74,12 @@ static int dpot_dac_read_raw(struct iio_dev *indio_dev,
case IIO_VAL_INT:
/*
* Convert integer scale to fractional scale by
- * setting the denominator (val2) to one, and...
+ * setting the denominator (val2) to one...
*/
*val2 = 1;
ret = IIO_VAL_FRACTIONAL;
- /* fall through */
+ /* ...and fall through. Say it again for GCC. */
+ fallthrough;
case IIO_VAL_FRACTIONAL:
*val *= regulator_get_voltage(dac->vref) / 1000;
*val2 *= dac->max_ohms;
@@ -177,7 +178,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;
diff --git a/drivers/iio/dac/ds4424.c b/drivers/iio/dac/ds4424.c
index 26d206681472..79527fbc250a 100644
--- a/drivers/iio/dac/ds4424.c
+++ b/drivers/iio/dac/ds4424.c
@@ -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)) {
diff --git a/drivers/iio/dac/lpc18xx_dac.c b/drivers/iio/dac/lpc18xx_dac.c
index 0ab357bd3633..9e38607a189e 100644
--- a/drivers/iio/dac/lpc18xx_dac.c
+++ b/drivers/iio/dac/lpc18xx_dac.c
@@ -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;
diff --git a/drivers/iio/dac/ltc1660.c b/drivers/iio/dac/ltc1660.c
index 10866838c72a..dc10188540ca 100644
--- a/drivers/iio/dac/ltc1660.c
+++ b/drivers/iio/dac/ltc1660.c
@@ -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];
diff --git a/drivers/iio/dac/ltc2632.c b/drivers/iio/dac/ltc2632.c
index 7adc91056aa1..4002ed0868be 100644
--- a/drivers/iio/dac/ltc2632.c
+++ b/drivers/iio/dac/ltc2632.c
@@ -12,6 +12,8 @@
#include <linux/iio/iio.h>
#include <linux/regulator/consumer.h>
+#include <asm/unaligned.h>
+
#define LTC2632_CMD_WRITE_INPUT_N 0x0
#define LTC2632_CMD_UPDATE_DAC_N 0x1
#define LTC2632_CMD_WRITE_INPUT_N_UPDATE_ALL 0x2
@@ -24,6 +26,7 @@
/**
* struct ltc2632_chip_info - chip specific information
* @channels: channel spec for the DAC
+ * @num_channels: DAC channel count of the chip
* @vref_mv: internal reference voltage
*/
struct ltc2632_chip_info {
@@ -35,9 +38,9 @@ struct ltc2632_chip_info {
/**
* struct ltc2632_state - driver instance specific data
* @spi_dev: pointer to the spi_device struct
- * @powerdown_cache_mask used to show current channel powerdown state
- * @vref_mv used reference voltage (internal or external)
- * @vref_reg regulator for the reference voltage
+ * @powerdown_cache_mask: used to show current channel powerdown state
+ * @vref_mv: used reference voltage (internal or external)
+ * @vref_reg: regulator for the reference voltage
*/
struct ltc2632_state {
struct spi_device *spi_dev;
@@ -53,6 +56,12 @@ enum ltc2632_supported_device_ids {
ID_LTC2632H12,
ID_LTC2632H10,
ID_LTC2632H8,
+ ID_LTC2634L12,
+ ID_LTC2634L10,
+ ID_LTC2634L8,
+ ID_LTC2634H12,
+ ID_LTC2634H10,
+ ID_LTC2634H8,
ID_LTC2636L12,
ID_LTC2636L10,
ID_LTC2636L8,
@@ -75,9 +84,7 @@ static int ltc2632_spi_write(struct spi_device *spi,
* 10-, 8-bit input code followed by 4, 6, or 8 don't care bits.
*/
data = (cmd << 20) | (addr << 16) | (val << shift);
- msg[0] = data >> 16;
- msg[1] = data >> 8;
- msg[2] = data;
+ put_unaligned_be24(data, &msg[0]);
return spi_write(spi, msg, sizeof(msg));
}
@@ -235,6 +242,36 @@ static const struct ltc2632_chip_info ltc2632_chip_info_tbl[] = {
.num_channels = 2,
.vref_mv = 4096,
},
+ [ID_LTC2634L12] = {
+ .channels = ltc2632x12_channels,
+ .num_channels = 4,
+ .vref_mv = 2500,
+ },
+ [ID_LTC2634L10] = {
+ .channels = ltc2632x10_channels,
+ .num_channels = 4,
+ .vref_mv = 2500,
+ },
+ [ID_LTC2634L8] = {
+ .channels = ltc2632x8_channels,
+ .num_channels = 4,
+ .vref_mv = 2500,
+ },
+ [ID_LTC2634H12] = {
+ .channels = ltc2632x12_channels,
+ .num_channels = 4,
+ .vref_mv = 4096,
+ },
+ [ID_LTC2634H10] = {
+ .channels = ltc2632x10_channels,
+ .num_channels = 4,
+ .vref_mv = 4096,
+ },
+ [ID_LTC2634H8] = {
+ .channels = ltc2632x8_channels,
+ .num_channels = 4,
+ .vref_mv = 4096,
+ },
[ID_LTC2636L12] = {
.channels = ltc2632x12_channels,
.num_channels = 8,
@@ -325,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;
@@ -356,6 +392,12 @@ static const struct spi_device_id ltc2632_id[] = {
{ "ltc2632-h12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H12] },
{ "ltc2632-h10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H10] },
{ "ltc2632-h8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H8] },
+ { "ltc2634-l12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634L12] },
+ { "ltc2634-l10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634L10] },
+ { "ltc2634-l8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634L8] },
+ { "ltc2634-h12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634H12] },
+ { "ltc2634-h10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634H10] },
+ { "ltc2634-h8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634H8] },
{ "ltc2636-l12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636L12] },
{ "ltc2636-l10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636L10] },
{ "ltc2636-l8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636L8] },
@@ -386,6 +428,24 @@ static const struct of_device_id ltc2632_of_match[] = {
.compatible = "lltc,ltc2632-h8",
.data = &ltc2632_chip_info_tbl[ID_LTC2632H8]
}, {
+ .compatible = "lltc,ltc2634-l12",
+ .data = &ltc2632_chip_info_tbl[ID_LTC2634L12]
+ }, {
+ .compatible = "lltc,ltc2634-l10",
+ .data = &ltc2632_chip_info_tbl[ID_LTC2634L10]
+ }, {
+ .compatible = "lltc,ltc2634-l8",
+ .data = &ltc2632_chip_info_tbl[ID_LTC2634L8]
+ }, {
+ .compatible = "lltc,ltc2634-h12",
+ .data = &ltc2632_chip_info_tbl[ID_LTC2634H12]
+ }, {
+ .compatible = "lltc,ltc2634-h10",
+ .data = &ltc2632_chip_info_tbl[ID_LTC2634H10]
+ }, {
+ .compatible = "lltc,ltc2634-h8",
+ .data = &ltc2632_chip_info_tbl[ID_LTC2634H8]
+ }, {
.compatible = "lltc,ltc2636-l12",
.data = &ltc2632_chip_info_tbl[ID_LTC2636L12]
}, {
diff --git a/drivers/iio/dac/m62332.c b/drivers/iio/dac/m62332.c
index 3205ca98c32d..225b1a374dc1 100644
--- a/drivers/iio/dac/m62332.c
+++ b/drivers/iio/dac/m62332.c
@@ -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;
diff --git a/drivers/iio/dac/max517.c b/drivers/iio/dac/max517.c
index 7e01838ef4d0..daa60386bf0c 100644
--- a/drivers/iio/dac/max517.c
+++ b/drivers/iio/dac/max517.c
@@ -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;
diff --git a/drivers/iio/dac/max5821.c b/drivers/iio/dac/max5821.c
index 2da086e372af..d6bb24db49c4 100644
--- a/drivers/iio/dac/max5821.c
+++ b/drivers/iio/dac/max5821.c
@@ -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;
diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c
index ed455e801e80..ee174d224110 100644
--- a/drivers/iio/dac/mcp4725.c
+++ b/drivers/iio/dac/mcp4725.c
@@ -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];
diff --git a/drivers/iio/dac/mcp4922.c b/drivers/iio/dac/mcp4922.c
index f9194b3ddc9c..c4e430b4050e 100644
--- a/drivers/iio/dac/mcp4922.c
+++ b/drivers/iio/dac/mcp4922.c
@@ -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];
diff --git a/drivers/iio/dac/stm32-dac.c b/drivers/iio/dac/stm32-dac.c
index f22c1d9129b2..092c796fa3d9 100644
--- a/drivers/iio/dac/stm32-dac.c
+++ b/drivers/iio/dac/stm32-dac.c
@@ -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;
diff --git a/drivers/iio/dac/ti-dac082s085.c b/drivers/iio/dac/ti-dac082s085.c
index 57b498d2a2a5..86bfb1c3f9b9 100644
--- a/drivers/iio/dac/ti-dac082s085.c
+++ b/drivers/iio/dac/ti-dac082s085.c
@@ -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;
diff --git a/drivers/iio/dac/ti-dac5571.c b/drivers/iio/dac/ti-dac5571.c
index 3a2bb0efe50d..00fc7db8eb65 100644
--- a/drivers/iio/dac/ti-dac5571.c
+++ b/drivers/iio/dac/ti-dac5571.c
@@ -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;
diff --git a/drivers/iio/dac/ti-dac7311.c b/drivers/iio/dac/ti-dac7311.c
index 6f5df1a30a1c..63171e42f987 100644
--- a/drivers/iio/dac/ti-dac7311.c
+++ b/drivers/iio/dac/ti-dac7311.c
@@ -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;
diff --git a/drivers/iio/dac/ti-dac7612.c b/drivers/iio/dac/ti-dac7612.c
index c46805144dd4..07c9f39d54f1 100644
--- a/drivers/iio/dac/ti-dac7612.c
+++ b/drivers/iio/dac/ti-dac7612.c
@@ -3,7 +3,7 @@
* DAC7612 Dual, 12-Bit Serial input Digital-to-Analog Converter
*
* Copyright 2019 Qtechnology A/S
- * 2019 Ricardo Ribalda <ricardo@ribalda.com>
+ * 2019 Ricardo Ribalda <ribalda@kernel.org>
*
* Licensed under the GPL-2.
*/
@@ -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;
@@ -179,6 +178,6 @@ static struct spi_driver dac7612_driver = {
};
module_spi_driver(dac7612_driver);
-MODULE_AUTHOR("Ricardo Ribalda <ricardo@ribalda.com>");
+MODULE_AUTHOR("Ricardo Ribalda <ribalda@kernel.org>");
MODULE_DESCRIPTION("Texas Instruments DAC7612 DAC driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/dac/vf610_dac.c b/drivers/iio/dac/vf610_dac.c
index 7f1e9317c3f3..636b4009f763 100644
--- a/drivers/iio/dac/vf610_dac.c
+++ b/drivers/iio/dac/vf610_dac.c
@@ -36,6 +36,7 @@ struct vf610_dac {
struct device *dev;
enum vf610_conversion_mode_sel conv_mode;
void __iomem *regs;
+ struct mutex lock;
};
static void vf610_dac_init(struct vf610_dac *info)
@@ -64,7 +65,7 @@ static int vf610_set_conversion_mode(struct iio_dev *indio_dev,
struct vf610_dac *info = iio_priv(indio_dev);
int val;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&info->lock);
info->conv_mode = mode;
val = readl(info->regs + VF610_DACx_STATCTRL);
if (mode)
@@ -72,7 +73,7 @@ static int vf610_set_conversion_mode(struct iio_dev *indio_dev,
else
val &= ~VF610_DAC_LPEN;
writel(val, info->regs + VF610_DACx_STATCTRL);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&info->lock);
return 0;
}
@@ -147,9 +148,9 @@ static int vf610_write_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&info->lock);
writel(VF610_DAC_DAT0(val), info->regs);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&info->lock);
return 0;
default:
@@ -198,13 +199,13 @@ 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;
indio_dev->num_channels = ARRAY_SIZE(vf610_dac_iio_channels);
+ mutex_init(&info->lock);
+
ret = clk_prepare_enable(info->clk);
if (ret) {
dev_err(&pdev->dev,
diff --git a/drivers/iio/dummy/iio_dummy_evgen.c b/drivers/iio/dummy/iio_dummy_evgen.c
index a6edf30567aa..ee85d596e528 100644
--- a/drivers/iio/dummy/iio_dummy_evgen.c
+++ b/drivers/iio/dummy/iio_dummy_evgen.c
@@ -37,8 +37,7 @@ struct iio_dummy_eventgen {
struct iio_dummy_regs regs[IIO_EVENTGEN_NO];
struct mutex lock;
bool inuse[IIO_EVENTGEN_NO];
- struct irq_sim irq_sim;
- int base;
+ struct irq_domain *irq_sim_domain;
};
/* We can only ever have one instance of this 'device' */
@@ -52,13 +51,14 @@ static int iio_dummy_evgen_create(void)
if (!iio_evgen)
return -ENOMEM;
- ret = irq_sim_init(&iio_evgen->irq_sim, IIO_EVENTGEN_NO);
- if (ret < 0) {
+ iio_evgen->irq_sim_domain = irq_domain_create_sim(NULL,
+ IIO_EVENTGEN_NO);
+ if (IS_ERR(iio_evgen->irq_sim_domain)) {
+ ret = PTR_ERR(iio_evgen->irq_sim_domain);
kfree(iio_evgen);
return ret;
}
- iio_evgen->base = irq_sim_irqnum(&iio_evgen->irq_sim, 0);
mutex_init(&iio_evgen->lock);
return 0;
@@ -80,7 +80,7 @@ int iio_dummy_evgen_get_irq(void)
mutex_lock(&iio_evgen->lock);
for (i = 0; i < IIO_EVENTGEN_NO; i++) {
if (!iio_evgen->inuse[i]) {
- ret = irq_sim_irqnum(&iio_evgen->irq_sim, i);
+ ret = irq_create_mapping(iio_evgen->irq_sim_domain, i);
iio_evgen->inuse[i] = true;
break;
}
@@ -101,21 +101,27 @@ EXPORT_SYMBOL_GPL(iio_dummy_evgen_get_irq);
*/
void iio_dummy_evgen_release_irq(int irq)
{
+ struct irq_data *irqd = irq_get_irq_data(irq);
+
mutex_lock(&iio_evgen->lock);
- iio_evgen->inuse[irq - iio_evgen->base] = false;
+ iio_evgen->inuse[irqd_to_hwirq(irqd)] = false;
+ irq_dispose_mapping(irq);
mutex_unlock(&iio_evgen->lock);
}
EXPORT_SYMBOL_GPL(iio_dummy_evgen_release_irq);
struct iio_dummy_regs *iio_dummy_evgen_get_regs(int irq)
{
- return &iio_evgen->regs[irq - iio_evgen->base];
+ struct irq_data *irqd = irq_get_irq_data(irq);
+
+ return &iio_evgen->regs[irqd_to_hwirq(irqd)];
+
}
EXPORT_SYMBOL_GPL(iio_dummy_evgen_get_regs);
static void iio_dummy_evgen_free(void)
{
- irq_sim_fini(&iio_evgen->irq_sim);
+ irq_domain_remove_sim(iio_evgen->irq_sim_domain);
kfree(iio_evgen);
}
@@ -131,7 +137,7 @@ static ssize_t iio_evgen_poke(struct device *dev,
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
unsigned long event;
- int ret;
+ int ret, irq;
ret = kstrtoul(buf, 10, &event);
if (ret)
@@ -140,7 +146,10 @@ static ssize_t iio_evgen_poke(struct device *dev,
iio_evgen->regs[this_attr->address].reg_id = this_attr->address;
iio_evgen->regs[this_attr->address].reg_data = event;
- irq_sim_fire(&iio_evgen->irq_sim, this_attr->address);
+ irq = irq_find_mapping(iio_evgen->irq_sim_domain, this_attr->address);
+ ret = irq_set_irqchip_state(irq, IRQCHIP_STATE_PENDING, true);
+ if (ret)
+ return ret;
return len;
}
diff --git a/drivers/iio/dummy/iio_simple_dummy.c b/drivers/iio/dummy/iio_simple_dummy.c
index 6cb02299a215..c0b7ef900735 100644
--- a/drivers/iio/dummy/iio_simple_dummy.c
+++ b/drivers/iio/dummy/iio_simple_dummy.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
-/**
+/*
* Copyright (c) 2011 Jonathan Cameron
*
* A reference industrial I/O driver to illustrate the functionality available.
@@ -553,7 +553,7 @@ static int iio_dummy_init_device(struct iio_dev *indio_dev)
/**
* iio_dummy_probe() - device instance probe
- * @index: an id number for this instance.
+ * @name: name of this instance.
*
* Arguments are bus type specific.
* I2C: iio_dummy_probe(struct i2c_client *client,
@@ -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.
@@ -687,7 +689,8 @@ static int iio_dummy_remove(struct iio_sw_device *swd)
return 0;
}
-/**
+
+/*
* module_iio_sw_device_driver() - device driver registration
*
* Varies depending on bus type of the device. As there is no device
diff --git a/drivers/iio/dummy/iio_simple_dummy_buffer.c b/drivers/iio/dummy/iio_simple_dummy_buffer.c
index 17606eca42b4..5512d5edc707 100644
--- a/drivers/iio/dummy/iio_simple_dummy_buffer.c
+++ b/drivers/iio/dummy/iio_simple_dummy_buffer.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
-/**
+/*
* Copyright (c) 2011 Jonathan Cameron
*
* Buffer handling elements of industrial I/O reference driver.
@@ -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)
@@ -179,7 +165,7 @@ error_ret:
/**
* iio_simple_dummy_unconfigure_buffer() - release buffer resources
- * @indo_dev: device instance state
+ * @indio_dev: device instance state
*/
void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev)
{
diff --git a/drivers/iio/dummy/iio_simple_dummy_events.c b/drivers/iio/dummy/iio_simple_dummy_events.c
index b3abaaca6f5e..63a2b844be50 100644
--- a/drivers/iio/dummy/iio_simple_dummy_events.c
+++ b/drivers/iio/dummy/iio_simple_dummy_events.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
-/**
+/*
* Copyright (c) 2011 Jonathan Cameron
*
* Event handling elements of industrial I/O reference driver.
@@ -107,6 +107,7 @@ int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev,
* @dir: direction of the vent whose value is being read
* @info: info type of the event whose value is being read
* @val: value for the event code.
+ * @val2: unused
*
* Many devices provide a large set of events of which only a subset may
* be enabled at a time, with value registers whose meaning changes depending
@@ -136,6 +137,7 @@ int iio_simple_dummy_read_event_value(struct iio_dev *indio_dev,
* @dir: direction of the vent whose value is being set
* @info: info type of the event whose value is being set
* @val: the value to be set.
+ * @val2: unused
*/
int iio_simple_dummy_write_event_value(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c
index a7322184cbdd..334e1d779d6d 100644
--- a/drivers/iio/frequency/ad9523.c
+++ b/drivers/iio/frequency/ad9523.c
@@ -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;
diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c
index 1c2dc9b00f31..409c9c47161e 100644
--- a/drivers/iio/frequency/adf4350.c
+++ b/drivers/iio/frequency/adf4350.c
@@ -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;
diff --git a/drivers/iio/frequency/adf4371.c b/drivers/iio/frequency/adf4371.c
index ff82863cbf42..ecd5e18995ad 100644
--- a/drivers/iio/frequency/adf4371.c
+++ b/drivers/iio/frequency/adf4371.c
@@ -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;
diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig
index 7eaf77707b0b..6daeddf37f60 100644
--- a/drivers/iio/gyro/Kconfig
+++ b/drivers/iio/gyro/Kconfig
@@ -61,7 +61,7 @@ config BMG160
help
Say yes here to build support for BOSCH BMG160 Tri-axis Gyro Sensor
driver connected via I2C or SPI. This driver also supports BMI055
- gyroscope.
+ and BMI088 gyroscope.
This driver can also be built as a module. If so, the module
will be called bmg160_i2c or bmg160_spi.
diff --git a/drivers/iio/gyro/adis16080.c b/drivers/iio/gyro/adis16080.c
index 1b84b8e112fe..6e5e2d98943c 100644
--- a/drivers/iio/gyro/adis16080.c
+++ b/drivers/iio/gyro/adis16080.c
@@ -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;
diff --git a/drivers/iio/gyro/adis16130.c b/drivers/iio/gyro/adis16130.c
index 79e63c8a2ea8..b9c952e65b55 100644
--- a/drivers/iio/gyro/adis16130.c
+++ b/drivers/iio/gyro/adis16130.c
@@ -12,6 +12,8 @@
#include <linux/iio/iio.h>
+#include <asm/unaligned.h>
+
#define ADIS16130_CON 0x0
#define ADIS16130_CON_RD (1 << 6)
#define ADIS16130_IOP 0x1
@@ -59,7 +61,7 @@ static int adis16130_spi_read(struct iio_dev *indio_dev, u8 reg_addr, u32 *val)
ret = spi_sync_transfer(st->us, &xfer, 1);
if (ret == 0)
- *val = (st->buf[1] << 16) | (st->buf[2] << 8) | st->buf[3];
+ *val = get_unaligned_be24(&st->buf[1]);
mutex_unlock(&st->buf_lock);
return ret;
@@ -153,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;
diff --git a/drivers/iio/gyro/adis16136.c b/drivers/iio/gyro/adis16136.c
index a4c967a5fc5c..d8a96f6bbae2 100644
--- a/drivers/iio/gyro/adis16136.c
+++ b/drivers/iio/gyro/adis16136.c
@@ -148,16 +148,14 @@ DEFINE_DEBUGFS_ATTRIBUTE(adis16136_flash_count_fops,
static int adis16136_debugfs_init(struct iio_dev *indio_dev)
{
struct adis16136 *adis16136 = iio_priv(indio_dev);
+ struct dentry *d = iio_get_debugfs_dentry(indio_dev);
debugfs_create_file_unsafe("serial_number", 0400,
- indio_dev->debugfs_dentry, adis16136,
- &adis16136_serial_fops);
+ d, adis16136, &adis16136_serial_fops);
debugfs_create_file_unsafe("product_id", 0400,
- indio_dev->debugfs_dentry,
- adis16136, &adis16136_product_id_fops);
+ d, adis16136, &adis16136_product_id_fops);
debugfs_create_file_unsafe("flash_count", 0400,
- indio_dev->debugfs_dentry,
- adis16136, &adis16136_flash_count_fops);
+ d, adis16136, &adis16136_flash_count_fops);
return 0;
}
@@ -542,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);
diff --git a/drivers/iio/gyro/adis16260.c b/drivers/iio/gyro/adis16260.c
index 9823573e811a..e638d56e1574 100644
--- a/drivers/iio/gyro/adis16260.c
+++ b/drivers/iio/gyro/adis16260.c
@@ -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;
diff --git a/drivers/iio/gyro/adxrs450.c b/drivers/iio/gyro/adxrs450.c
index b00c0eb44249..04f350025215 100644
--- a/drivers/iio/gyro/adxrs450.c
+++ b/drivers/iio/gyro/adxrs450.c
@@ -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 =
diff --git a/drivers/iio/gyro/bmg160_core.c b/drivers/iio/gyro/bmg160_core.c
index 428ddfc13acb..8ddda96455fc 100644
--- a/drivers/iio/gyro/bmg160_core.c
+++ b/drivers/iio/gyro/bmg160_core.c
@@ -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;
diff --git a/drivers/iio/gyro/bmg160_i2c.c b/drivers/iio/gyro/bmg160_i2c.c
index 4fc9c6a3321f..b3fa46bd02cb 100644
--- a/drivers/iio/gyro/bmg160_i2c.c
+++ b/drivers/iio/gyro/bmg160_i2c.c
@@ -21,8 +21,8 @@ static int bmg160_i2c_probe(struct i2c_client *client,
regmap = devm_regmap_init_i2c(client, &bmg160_regmap_i2c_conf);
if (IS_ERR(regmap)) {
- dev_err(&client->dev, "Failed to register i2c regmap %d\n",
- (int)PTR_ERR(regmap));
+ dev_err(&client->dev, "Failed to register i2c regmap: %pe\n",
+ regmap);
return PTR_ERR(regmap);
}
@@ -42,6 +42,7 @@ static int bmg160_i2c_remove(struct i2c_client *client)
static const struct acpi_device_id bmg160_acpi_match[] = {
{"BMG0160", 0},
{"BMI055B", 0},
+ {"BMI088B", 0},
{},
};
@@ -50,6 +51,7 @@ MODULE_DEVICE_TABLE(acpi, bmg160_acpi_match);
static const struct i2c_device_id bmg160_i2c_id[] = {
{"bmg160", 0},
{"bmi055_gyro", 0},
+ {"bmi088_gyro", 0},
{}
};
diff --git a/drivers/iio/gyro/bmg160_spi.c b/drivers/iio/gyro/bmg160_spi.c
index 182a59c42507..745962e1e423 100644
--- a/drivers/iio/gyro/bmg160_spi.c
+++ b/drivers/iio/gyro/bmg160_spi.c
@@ -19,8 +19,8 @@ static int bmg160_spi_probe(struct spi_device *spi)
regmap = devm_regmap_init_spi(spi, &bmg160_regmap_spi_conf);
if (IS_ERR(regmap)) {
- dev_err(&spi->dev, "Failed to register spi regmap %d\n",
- (int)PTR_ERR(regmap));
+ dev_err(&spi->dev, "Failed to register spi regmap: %pe\n",
+ regmap);
return PTR_ERR(regmap);
}
@@ -37,6 +37,7 @@ static int bmg160_spi_remove(struct spi_device *spi)
static const struct spi_device_id bmg160_spi_id[] = {
{"bmg160", 0},
{"bmi055_gyro", 0},
+ {"bmi088_gyro", 0},
{}
};
diff --git a/drivers/iio/gyro/fxas21002c.h b/drivers/iio/gyro/fxas21002c.h
index 566d92de2676..c81cecee121c 100644
--- a/drivers/iio/gyro/fxas21002c.h
+++ b/drivers/iio/gyro/fxas21002c.h
@@ -76,72 +76,6 @@ enum fxas21002c_fields {
F_MAX_FIELDS,
};
-static const struct reg_field fxas21002c_reg_fields[] = {
- [F_DR_STATUS] = REG_FIELD(FXAS21002C_REG_STATUS, 0, 7),
- [F_OUT_X_MSB] = REG_FIELD(FXAS21002C_REG_OUT_X_MSB, 0, 7),
- [F_OUT_X_LSB] = REG_FIELD(FXAS21002C_REG_OUT_X_LSB, 0, 7),
- [F_OUT_Y_MSB] = REG_FIELD(FXAS21002C_REG_OUT_Y_MSB, 0, 7),
- [F_OUT_Y_LSB] = REG_FIELD(FXAS21002C_REG_OUT_Y_LSB, 0, 7),
- [F_OUT_Z_MSB] = REG_FIELD(FXAS21002C_REG_OUT_Z_MSB, 0, 7),
- [F_OUT_Z_LSB] = REG_FIELD(FXAS21002C_REG_OUT_Z_LSB, 0, 7),
- [F_ZYX_OW] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 7, 7),
- [F_Z_OW] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 6, 6),
- [F_Y_OW] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 5, 5),
- [F_X_OW] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 4, 4),
- [F_ZYX_DR] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 3, 3),
- [F_Z_DR] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 2, 2),
- [F_Y_DR] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 1, 1),
- [F_X_DR] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 0, 0),
- [F_OVF] = REG_FIELD(FXAS21002C_REG_F_STATUS, 7, 7),
- [F_WMKF] = REG_FIELD(FXAS21002C_REG_F_STATUS, 6, 6),
- [F_CNT] = REG_FIELD(FXAS21002C_REG_F_STATUS, 0, 5),
- [F_MODE] = REG_FIELD(FXAS21002C_REG_F_SETUP, 6, 7),
- [F_WMRK] = REG_FIELD(FXAS21002C_REG_F_SETUP, 0, 5),
- [F_EVENT] = REG_FIELD(FXAS21002C_REG_F_EVENT, 5, 5),
- [FE_TIME] = REG_FIELD(FXAS21002C_REG_F_EVENT, 0, 4),
- [F_BOOTEND] = REG_FIELD(FXAS21002C_REG_INT_SRC_FLAG, 3, 3),
- [F_SRC_FIFO] = REG_FIELD(FXAS21002C_REG_INT_SRC_FLAG, 2, 2),
- [F_SRC_RT] = REG_FIELD(FXAS21002C_REG_INT_SRC_FLAG, 1, 1),
- [F_SRC_DRDY] = REG_FIELD(FXAS21002C_REG_INT_SRC_FLAG, 0, 0),
- [F_WHO_AM_I] = REG_FIELD(FXAS21002C_REG_WHO_AM_I, 0, 7),
- [F_BW] = REG_FIELD(FXAS21002C_REG_CTRL0, 6, 7),
- [F_SPIW] = REG_FIELD(FXAS21002C_REG_CTRL0, 5, 5),
- [F_SEL] = REG_FIELD(FXAS21002C_REG_CTRL0, 3, 4),
- [F_HPF_EN] = REG_FIELD(FXAS21002C_REG_CTRL0, 2, 2),
- [F_FS] = REG_FIELD(FXAS21002C_REG_CTRL0, 0, 1),
- [F_ELE] = REG_FIELD(FXAS21002C_REG_RT_CFG, 3, 3),
- [F_ZTEFE] = REG_FIELD(FXAS21002C_REG_RT_CFG, 2, 2),
- [F_YTEFE] = REG_FIELD(FXAS21002C_REG_RT_CFG, 1, 1),
- [F_XTEFE] = REG_FIELD(FXAS21002C_REG_RT_CFG, 0, 0),
- [F_EA] = REG_FIELD(FXAS21002C_REG_RT_SRC, 6, 6),
- [F_ZRT] = REG_FIELD(FXAS21002C_REG_RT_SRC, 5, 5),
- [F_ZRT_POL] = REG_FIELD(FXAS21002C_REG_RT_SRC, 4, 4),
- [F_YRT] = REG_FIELD(FXAS21002C_REG_RT_SRC, 3, 3),
- [F_YRT_POL] = REG_FIELD(FXAS21002C_REG_RT_SRC, 2, 2),
- [F_XRT] = REG_FIELD(FXAS21002C_REG_RT_SRC, 1, 1),
- [F_XRT_POL] = REG_FIELD(FXAS21002C_REG_RT_SRC, 0, 0),
- [F_DBCNTM] = REG_FIELD(FXAS21002C_REG_RT_THS, 7, 7),
- [F_THS] = REG_FIELD(FXAS21002C_REG_RT_SRC, 0, 6),
- [F_RT_COUNT] = REG_FIELD(FXAS21002C_REG_RT_COUNT, 0, 7),
- [F_TEMP] = REG_FIELD(FXAS21002C_REG_TEMP, 0, 7),
- [F_RST] = REG_FIELD(FXAS21002C_REG_CTRL1, 6, 6),
- [F_ST] = REG_FIELD(FXAS21002C_REG_CTRL1, 5, 5),
- [F_DR] = REG_FIELD(FXAS21002C_REG_CTRL1, 2, 4),
- [F_ACTIVE] = REG_FIELD(FXAS21002C_REG_CTRL1, 1, 1),
- [F_READY] = REG_FIELD(FXAS21002C_REG_CTRL1, 0, 0),
- [F_INT_CFG_FIFO] = REG_FIELD(FXAS21002C_REG_CTRL2, 7, 7),
- [F_INT_EN_FIFO] = REG_FIELD(FXAS21002C_REG_CTRL2, 6, 6),
- [F_INT_CFG_RT] = REG_FIELD(FXAS21002C_REG_CTRL2, 5, 5),
- [F_INT_EN_RT] = REG_FIELD(FXAS21002C_REG_CTRL2, 4, 4),
- [F_INT_CFG_DRDY] = REG_FIELD(FXAS21002C_REG_CTRL2, 3, 3),
- [F_INT_EN_DRDY] = REG_FIELD(FXAS21002C_REG_CTRL2, 2, 2),
- [F_IPOL] = REG_FIELD(FXAS21002C_REG_CTRL2, 1, 1),
- [F_PP_OD] = REG_FIELD(FXAS21002C_REG_CTRL2, 0, 0),
- [F_WRAPTOONE] = REG_FIELD(FXAS21002C_REG_CTRL3, 3, 3),
- [F_EXTCTRLEN] = REG_FIELD(FXAS21002C_REG_CTRL3, 2, 2),
- [F_FS_DOUBLE] = REG_FIELD(FXAS21002C_REG_CTRL3, 0, 0),
-};
-
extern const struct dev_pm_ops fxas21002c_pm_ops;
int fxas21002c_core_probe(struct device *dev, struct regmap *regmap, int irq,
diff --git a/drivers/iio/gyro/fxas21002c_core.c b/drivers/iio/gyro/fxas21002c_core.c
index 89d2bb2282ea..129eead8febc 100644
--- a/drivers/iio/gyro/fxas21002c_core.c
+++ b/drivers/iio/gyro/fxas21002c_core.c
@@ -42,6 +42,72 @@ enum fxas21002c_mode_state {
#define FXAS21002C_AXIS_TO_REG(axis) (FXAS21002C_REG_OUT_X_MSB + ((axis) * 2))
+static const struct reg_field fxas21002c_reg_fields[] = {
+ [F_DR_STATUS] = REG_FIELD(FXAS21002C_REG_STATUS, 0, 7),
+ [F_OUT_X_MSB] = REG_FIELD(FXAS21002C_REG_OUT_X_MSB, 0, 7),
+ [F_OUT_X_LSB] = REG_FIELD(FXAS21002C_REG_OUT_X_LSB, 0, 7),
+ [F_OUT_Y_MSB] = REG_FIELD(FXAS21002C_REG_OUT_Y_MSB, 0, 7),
+ [F_OUT_Y_LSB] = REG_FIELD(FXAS21002C_REG_OUT_Y_LSB, 0, 7),
+ [F_OUT_Z_MSB] = REG_FIELD(FXAS21002C_REG_OUT_Z_MSB, 0, 7),
+ [F_OUT_Z_LSB] = REG_FIELD(FXAS21002C_REG_OUT_Z_LSB, 0, 7),
+ [F_ZYX_OW] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 7, 7),
+ [F_Z_OW] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 6, 6),
+ [F_Y_OW] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 5, 5),
+ [F_X_OW] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 4, 4),
+ [F_ZYX_DR] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 3, 3),
+ [F_Z_DR] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 2, 2),
+ [F_Y_DR] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 1, 1),
+ [F_X_DR] = REG_FIELD(FXAS21002C_REG_DR_STATUS, 0, 0),
+ [F_OVF] = REG_FIELD(FXAS21002C_REG_F_STATUS, 7, 7),
+ [F_WMKF] = REG_FIELD(FXAS21002C_REG_F_STATUS, 6, 6),
+ [F_CNT] = REG_FIELD(FXAS21002C_REG_F_STATUS, 0, 5),
+ [F_MODE] = REG_FIELD(FXAS21002C_REG_F_SETUP, 6, 7),
+ [F_WMRK] = REG_FIELD(FXAS21002C_REG_F_SETUP, 0, 5),
+ [F_EVENT] = REG_FIELD(FXAS21002C_REG_F_EVENT, 5, 5),
+ [FE_TIME] = REG_FIELD(FXAS21002C_REG_F_EVENT, 0, 4),
+ [F_BOOTEND] = REG_FIELD(FXAS21002C_REG_INT_SRC_FLAG, 3, 3),
+ [F_SRC_FIFO] = REG_FIELD(FXAS21002C_REG_INT_SRC_FLAG, 2, 2),
+ [F_SRC_RT] = REG_FIELD(FXAS21002C_REG_INT_SRC_FLAG, 1, 1),
+ [F_SRC_DRDY] = REG_FIELD(FXAS21002C_REG_INT_SRC_FLAG, 0, 0),
+ [F_WHO_AM_I] = REG_FIELD(FXAS21002C_REG_WHO_AM_I, 0, 7),
+ [F_BW] = REG_FIELD(FXAS21002C_REG_CTRL0, 6, 7),
+ [F_SPIW] = REG_FIELD(FXAS21002C_REG_CTRL0, 5, 5),
+ [F_SEL] = REG_FIELD(FXAS21002C_REG_CTRL0, 3, 4),
+ [F_HPF_EN] = REG_FIELD(FXAS21002C_REG_CTRL0, 2, 2),
+ [F_FS] = REG_FIELD(FXAS21002C_REG_CTRL0, 0, 1),
+ [F_ELE] = REG_FIELD(FXAS21002C_REG_RT_CFG, 3, 3),
+ [F_ZTEFE] = REG_FIELD(FXAS21002C_REG_RT_CFG, 2, 2),
+ [F_YTEFE] = REG_FIELD(FXAS21002C_REG_RT_CFG, 1, 1),
+ [F_XTEFE] = REG_FIELD(FXAS21002C_REG_RT_CFG, 0, 0),
+ [F_EA] = REG_FIELD(FXAS21002C_REG_RT_SRC, 6, 6),
+ [F_ZRT] = REG_FIELD(FXAS21002C_REG_RT_SRC, 5, 5),
+ [F_ZRT_POL] = REG_FIELD(FXAS21002C_REG_RT_SRC, 4, 4),
+ [F_YRT] = REG_FIELD(FXAS21002C_REG_RT_SRC, 3, 3),
+ [F_YRT_POL] = REG_FIELD(FXAS21002C_REG_RT_SRC, 2, 2),
+ [F_XRT] = REG_FIELD(FXAS21002C_REG_RT_SRC, 1, 1),
+ [F_XRT_POL] = REG_FIELD(FXAS21002C_REG_RT_SRC, 0, 0),
+ [F_DBCNTM] = REG_FIELD(FXAS21002C_REG_RT_THS, 7, 7),
+ [F_THS] = REG_FIELD(FXAS21002C_REG_RT_SRC, 0, 6),
+ [F_RT_COUNT] = REG_FIELD(FXAS21002C_REG_RT_COUNT, 0, 7),
+ [F_TEMP] = REG_FIELD(FXAS21002C_REG_TEMP, 0, 7),
+ [F_RST] = REG_FIELD(FXAS21002C_REG_CTRL1, 6, 6),
+ [F_ST] = REG_FIELD(FXAS21002C_REG_CTRL1, 5, 5),
+ [F_DR] = REG_FIELD(FXAS21002C_REG_CTRL1, 2, 4),
+ [F_ACTIVE] = REG_FIELD(FXAS21002C_REG_CTRL1, 1, 1),
+ [F_READY] = REG_FIELD(FXAS21002C_REG_CTRL1, 0, 0),
+ [F_INT_CFG_FIFO] = REG_FIELD(FXAS21002C_REG_CTRL2, 7, 7),
+ [F_INT_EN_FIFO] = REG_FIELD(FXAS21002C_REG_CTRL2, 6, 6),
+ [F_INT_CFG_RT] = REG_FIELD(FXAS21002C_REG_CTRL2, 5, 5),
+ [F_INT_EN_RT] = REG_FIELD(FXAS21002C_REG_CTRL2, 4, 4),
+ [F_INT_CFG_DRDY] = REG_FIELD(FXAS21002C_REG_CTRL2, 3, 3),
+ [F_INT_EN_DRDY] = REG_FIELD(FXAS21002C_REG_CTRL2, 2, 2),
+ [F_IPOL] = REG_FIELD(FXAS21002C_REG_CTRL2, 1, 1),
+ [F_PP_OD] = REG_FIELD(FXAS21002C_REG_CTRL2, 0, 0),
+ [F_WRAPTOONE] = REG_FIELD(FXAS21002C_REG_CTRL3, 3, 3),
+ [F_EXTCTRLEN] = REG_FIELD(FXAS21002C_REG_CTRL3, 2, 2),
+ [F_FS_DOUBLE] = REG_FIELD(FXAS21002C_REG_CTRL3, 0, 0),
+};
+
static const int fxas21002c_odr_values[] = {
800, 400, 200, 100, 50, 25, 12, 12
};
@@ -905,7 +971,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;
diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
index 08cacbbf31e6..6698f5f535f6 100644
--- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -14,8 +14,6 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
-#include <linux/iio/trigger_consumer.h>
-#include <linux/iio/triggered_buffer.h>
#include "../common/hid-sensors/hid-sensor-trigger.h"
enum gyro_3d_channel {
@@ -321,23 +319,17 @@ 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;
- ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
- NULL, NULL);
- if (ret) {
- dev_err(&pdev->dev, "failed to initialize trigger buffer\n");
- goto error_free_dev_mem;
- }
atomic_set(&gyro_state->common_attributes.data_ready, 0);
+
ret = hid_sensor_setup_trigger(indio_dev, name,
&gyro_state->common_attributes);
if (ret < 0) {
dev_err(&pdev->dev, "trigger setup failed\n");
- goto error_unreg_buffer_funcs;
+ goto error_free_dev_mem;
}
ret = iio_device_register(indio_dev);
@@ -361,9 +353,7 @@ static int hid_gyro_3d_probe(struct platform_device *pdev)
error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
- hid_sensor_remove_trigger(&gyro_state->common_attributes);
-error_unreg_buffer_funcs:
- iio_triggered_buffer_cleanup(indio_dev);
+ hid_sensor_remove_trigger(indio_dev, &gyro_state->common_attributes);
error_free_dev_mem:
kfree(indio_dev->channels);
return ret;
@@ -378,8 +368,7 @@ static int hid_gyro_3d_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_GYRO_3D);
iio_device_unregister(indio_dev);
- hid_sensor_remove_trigger(&gyro_state->common_attributes);
- iio_triggered_buffer_cleanup(indio_dev);
+ hid_sensor_remove_trigger(indio_dev, &gyro_state->common_attributes);
kfree(indio_dev->channels);
return 0;
diff --git a/drivers/iio/gyro/itg3200_core.c b/drivers/iio/gyro/itg3200_core.c
index b3afa556f973..e9804664db73 100644
--- a/drivers/iio/gyro/itg3200_core.c
+++ b/drivers/iio/gyro/itg3200_core.c
@@ -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);
diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-core.c
index 8e908a749f95..00e58060968c 100644
--- a/drivers/iio/gyro/mpu3050-core.c
+++ b/drivers/iio/gyro/mpu3050-core.c
@@ -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;
diff --git a/drivers/iio/gyro/mpu3050-i2c.c b/drivers/iio/gyro/mpu3050-i2c.c
index afa8018b9238..ef5bcbc4b45b 100644
--- a/drivers/iio/gyro/mpu3050-i2c.c
+++ b/drivers/iio/gyro/mpu3050-i2c.c
@@ -51,8 +51,8 @@ static int mpu3050_i2c_probe(struct i2c_client *client,
regmap = devm_regmap_init_i2c(client, &mpu3050_i2c_regmap_config);
if (IS_ERR(regmap)) {
- dev_err(&client->dev, "Failed to register i2c regmap %d\n",
- (int)PTR_ERR(regmap));
+ dev_err(&client->dev, "Failed to register i2c regmap: %pe\n",
+ regmap);
return PTR_ERR(regmap);
}
diff --git a/drivers/iio/gyro/ssp_gyro_sensor.c b/drivers/iio/gyro/ssp_gyro_sensor.c
index 4e4ee4167544..ac7c170a20de 100644
--- a/drivers/iio/gyro/ssp_gyro_sensor.c
+++ b/drivers/iio/gyro/ssp_gyro_sensor.c
@@ -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;
diff --git a/drivers/iio/gyro/st_gyro_buffer.c b/drivers/iio/gyro/st_gyro_buffer.c
index 7465ad62391c..4feb7ada7195 100644
--- a/drivers/iio/gyro/st_gyro_buffer.c
+++ b/drivers/iio/gyro/st_gyro_buffer.c
@@ -33,15 +33,10 @@ static int st_gyro_buffer_postenable(struct iio_dev *indio_dev)
{
int err;
- err = iio_triggered_buffer_postenable(indio_dev);
+ err = st_sensors_set_axis_enable(indio_dev, indio_dev->active_scan_mask[0]);
if (err < 0)
return err;
- err = st_sensors_set_axis_enable(indio_dev,
- (u8)indio_dev->active_scan_mask[0]);
- if (err < 0)
- goto st_gyro_buffer_predisable;
-
err = st_sensors_set_enable(indio_dev, true);
if (err < 0)
goto st_gyro_buffer_enable_all_axis;
@@ -50,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 = {
diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c
index 26c50b24bc08..c8aa051995d3 100644
--- a/drivers/iio/gyro/st_gyro_core.c
+++ b/drivers/iio/gyro/st_gyro_core.c
@@ -460,6 +460,7 @@ EXPORT_SYMBOL(st_gyro_get_settings);
int st_gyro_common_probe(struct iio_dev *indio_dev)
{
struct st_sensor_data *gdata = iio_priv(indio_dev);
+ struct st_sensors_platform_data *pdata;
int err;
indio_dev->modes = INDIO_DIRECT_MODE;
@@ -477,12 +478,12 @@ int st_gyro_common_probe(struct iio_dev *indio_dev)
indio_dev->channels = gdata->sensor_settings->ch;
indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
- gdata->current_fullscale = (struct st_sensor_fullscale_avl *)
- &gdata->sensor_settings->fs.fs_avl[0];
+ gdata->current_fullscale = &gdata->sensor_settings->fs.fs_avl[0];
gdata->odr = gdata->sensor_settings->odr.odr_avl[0].hz;
- err = st_sensors_init_sensor(indio_dev,
- (struct st_sensors_platform_data *)&gyro_pdata);
+ pdata = (struct st_sensors_platform_data *)&gyro_pdata;
+
+ err = st_sensors_init_sensor(indio_dev, pdata);
if (err < 0)
goto st_gyro_power_off;
diff --git a/drivers/iio/health/afe4403.c b/drivers/iio/health/afe4403.c
index dc22dc363a99..38734e4ce360 100644
--- a/drivers/iio/health/afe4403.c
+++ b/drivers/iio/health/afe4403.c
@@ -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>
*/
@@ -23,6 +23,8 @@
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.h>
+#include <asm/unaligned.h>
+
#include "afe440x.h"
#define AFE4403_DRIVER_NAME "afe4403"
@@ -63,6 +65,7 @@ static const struct reg_field afe4403_reg_fields[] = {
* @regulator: Pointer to the regulator for the IC
* @trig: IIO trigger for this device
* @irq: ADC_RDY line interrupt number
+ * @buffer: Used to construct data layout to push into IIO buffer.
*/
struct afe4403_data {
struct device *dev;
@@ -72,6 +75,8 @@ struct afe4403_data {
struct regulator *regulator;
struct iio_trigger *trig;
int irq;
+ /* Ensure suitable alignment for timestamp */
+ s32 buffer[8] __aligned(8);
};
enum afe4403_chan_id {
@@ -220,13 +225,11 @@ static int afe4403_read(struct afe4403_data *afe, unsigned int reg, u32 *val)
if (ret)
return ret;
- ret = spi_write_then_read(afe->spi, &reg, 1, rx, 3);
+ ret = spi_write_then_read(afe->spi, &reg, 1, rx, sizeof(rx));
if (ret)
return ret;
- *val = (rx[0] << 16) |
- (rx[1] << 8) |
- (rx[2]);
+ *val = get_unaligned_be24(&rx[0]);
/* Disable reading from the device */
tx[3] = AFE440X_CONTROL0_WRITE;
@@ -309,7 +312,6 @@ static irqreturn_t afe4403_trigger_handler(int irq, void *private)
struct iio_dev *indio_dev = pf->indio_dev;
struct afe4403_data *afe = iio_priv(indio_dev);
int ret, bit, i = 0;
- s32 buffer[8];
u8 tx[4] = {AFE440X_CONTROL0, 0x0, 0x0, AFE440X_CONTROL0_READ};
u8 rx[3];
@@ -322,13 +324,11 @@ static irqreturn_t afe4403_trigger_handler(int irq, void *private)
indio_dev->masklength) {
ret = spi_write_then_read(afe->spi,
&afe4403_channel_values[bit], 1,
- rx, 3);
+ rx, sizeof(rx));
if (ret)
goto err;
- buffer[i++] = (rx[0] << 16) |
- (rx[1] << 8) |
- (rx[2]);
+ afe->buffer[i++] = get_unaligned_be24(&rx[0]);
}
/* Disable reading from the device */
@@ -337,7 +337,8 @@ static irqreturn_t afe4403_trigger_handler(int irq, void *private)
if (ret)
goto err;
- iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp);
+ iio_push_to_buffers_with_timestamp(indio_dev, afe->buffer,
+ pf->timestamp);
err:
iio_trigger_notify_done(indio_dev->trig);
@@ -511,7 +512,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;
diff --git a/drivers/iio/health/afe4404.c b/drivers/iio/health/afe4404.c
index e728bbb21ca8..61fe4932d81d 100644
--- a/drivers/iio/health/afe4404.c
+++ b/drivers/iio/health/afe4404.c
@@ -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>
*/
@@ -83,6 +83,7 @@ static const struct reg_field afe4404_reg_fields[] = {
* @regulator: Pointer to the regulator for the IC
* @trig: IIO trigger for this device
* @irq: ADC_RDY line interrupt number
+ * @buffer: Used to construct a scan to push to the iio buffer.
*/
struct afe4404_data {
struct device *dev;
@@ -91,6 +92,7 @@ struct afe4404_data {
struct regulator *regulator;
struct iio_trigger *trig;
int irq;
+ s32 buffer[10] __aligned(8);
};
enum afe4404_chan_id {
@@ -328,17 +330,17 @@ static irqreturn_t afe4404_trigger_handler(int irq, void *private)
struct iio_dev *indio_dev = pf->indio_dev;
struct afe4404_data *afe = iio_priv(indio_dev);
int ret, bit, i = 0;
- s32 buffer[10];
for_each_set_bit(bit, indio_dev->active_scan_mask,
indio_dev->masklength) {
ret = regmap_read(afe->regmap, afe4404_channel_values[bit],
- &buffer[i++]);
+ &afe->buffer[i++]);
if (ret)
goto err;
}
- iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp);
+ iio_push_to_buffers_with_timestamp(indio_dev, afe->buffer,
+ pf->timestamp);
err:
iio_trigger_notify_done(indio_dev->trig);
@@ -517,7 +519,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;
diff --git a/drivers/iio/health/afe440x.h b/drivers/iio/health/afe440x.h
index 7829c4fcd03b..0adea0047eba 100644
--- a/drivers/iio/health/afe440x.h
+++ b/drivers/iio/health/afe440x.h
@@ -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>
*/
diff --git a/drivers/iio/health/max30100.c b/drivers/iio/health/max30100.c
index 84010501762d..38aa2030f3c6 100644
--- a/drivers/iio/health/max30100.c
+++ b/drivers/iio/health/max30100.c
@@ -16,7 +16,7 @@
#include <linux/irq.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
-#include <linux/of.h>
+#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
@@ -267,11 +267,10 @@ static int max30100_get_current_idx(unsigned int val, int *reg)
static int max30100_led_init(struct max30100_data *data)
{
struct device *dev = &data->client->dev;
- struct device_node *np = dev->of_node;
unsigned int val[2];
int reg, ret;
- ret = of_property_read_u32_array(np, "maxim,led-current-microamp",
+ ret = device_property_read_u32_array(dev, "maxim,led-current-microamp",
(unsigned int *) &val, 2);
if (ret) {
/* Default to 24 mA RED LED, 50 mA IR LED */
@@ -440,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;
@@ -502,7 +500,7 @@ MODULE_DEVICE_TABLE(of, max30100_dt_ids);
static struct i2c_driver max30100_driver = {
.driver = {
.name = MAX30100_DRV_NAME,
- .of_match_table = of_match_ptr(max30100_dt_ids),
+ .of_match_table = max30100_dt_ids,
},
.probe = max30100_probe,
.remove = max30100_remove,
diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
index 74fc260b957e..d9b2ed80882a 100644
--- a/drivers/iio/health/max30102.c
+++ b/drivers/iio/health/max30102.c
@@ -273,10 +273,10 @@ static int max30102_read_measurement(struct max30102_data *data,
switch (measurements) {
case 3:
MAX30102_COPY_DATA(2);
- /* fall through */
+ fallthrough;
case 2:
MAX30102_COPY_DATA(1);
- /* fall through */
+ fallthrough;
case 1:
MAX30102_COPY_DATA(0);
break;
@@ -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;
diff --git a/drivers/iio/humidity/am2315.c b/drivers/iio/humidity/am2315.c
index 3bac98e731d9..02ad1767c845 100644
--- a/drivers/iio/humidity/am2315.c
+++ b/drivers/iio/humidity/am2315.c
@@ -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;
diff --git a/drivers/iio/humidity/dht11.c b/drivers/iio/humidity/dht11.c
index d05c6fdb758b..9a7819817488 100644
--- a/drivers/iio/humidity/dht11.c
+++ b/drivers/iio/humidity/dht11.c
@@ -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;
diff --git a/drivers/iio/humidity/hdc100x.c b/drivers/iio/humidity/hdc100x.c
index 7ecd2ffa3132..071cb2b12bb6 100644
--- a/drivers/iio/humidity/hdc100x.c
+++ b/drivers/iio/humidity/hdc100x.c
@@ -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>
@@ -38,6 +38,11 @@ struct hdc100x_data {
/* integration time of the sensor */
int adc_int_us[2];
+ /* Ensure natural alignment of timestamp */
+ struct {
+ __be16 channels[2];
+ s64 ts __aligned(8);
+ } scan;
};
/* integration time in us */
@@ -278,17 +283,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 +295,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;
}
@@ -322,7 +317,6 @@ static irqreturn_t hdc100x_trigger_handler(int irq, void *p)
struct i2c_client *client = data->client;
int delay = data->adc_int_us[0] + data->adc_int_us[1];
int ret;
- s16 buf[8]; /* 2x s16 + padding + 8 byte timestamp */
/* dual read starts at temp register */
mutex_lock(&data->lock);
@@ -333,13 +327,13 @@ static irqreturn_t hdc100x_trigger_handler(int irq, void *p)
}
usleep_range(delay, delay + 1000);
- ret = i2c_master_recv(client, (u8 *)buf, 4);
+ ret = i2c_master_recv(client, (u8 *)data->scan.channels, 4);
if (ret < 0) {
dev_err(&client->dev, "cannot read sensor data\n");
goto err;
}
- iio_push_to_buffers_with_timestamp(indio_dev, buf,
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
iio_get_time_ns(indio_dev));
err:
mutex_unlock(&data->lock);
@@ -374,7 +368,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;
diff --git a/drivers/iio/humidity/hid-sensor-humidity.c b/drivers/iio/humidity/hid-sensor-humidity.c
index c99b54b0568d..52f605114ef7 100644
--- a/drivers/iio/humidity/hid-sensor-humidity.c
+++ b/drivers/iio/humidity/hid-sensor-humidity.c
@@ -7,8 +7,6 @@
#include <linux/hid-sensor-hub.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
-#include <linux/iio/triggered_buffer.h>
-#include <linux/iio/trigger_consumer.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@@ -228,17 +226,12 @@ 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;
- ret = devm_iio_triggered_buffer_setup(&pdev->dev, indio_dev,
- &iio_pollfunc_store_time, NULL, NULL);
- if (ret)
- return ret;
-
atomic_set(&humid_st->common_attributes.data_ready, 0);
+
ret = hid_sensor_setup_trigger(indio_dev, name,
&humid_st->common_attributes);
if (ret)
@@ -261,7 +254,7 @@ static int hid_humidity_probe(struct platform_device *pdev)
error_remove_callback:
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_HUMIDITY);
error_remove_trigger:
- hid_sensor_remove_trigger(&humid_st->common_attributes);
+ hid_sensor_remove_trigger(indio_dev, &humid_st->common_attributes);
return ret;
}
@@ -274,7 +267,7 @@ static int hid_humidity_remove(struct platform_device *pdev)
iio_device_unregister(indio_dev);
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_HUMIDITY);
- hid_sensor_remove_trigger(&humid_st->common_attributes);
+ hid_sensor_remove_trigger(indio_dev, &humid_st->common_attributes);
return 0;
}
diff --git a/drivers/iio/humidity/hts221.h b/drivers/iio/humidity/hts221.h
index 7d6771f7cf47..721359e226cb 100644
--- a/drivers/iio/humidity/hts221.h
+++ b/drivers/iio/humidity/hts221.h
@@ -14,8 +14,6 @@
#include <linux/iio/iio.h>
-#define HTS221_DATA_SIZE 2
-
enum hts221_sensor_type {
HTS221_SENSOR_H,
HTS221_SENSOR_T,
@@ -39,6 +37,11 @@ struct hts221_hw {
bool enabled;
u8 odr;
+ /* Ensure natural alignment of timestamp */
+ struct {
+ __le16 channels[2];
+ s64 ts __aligned(8);
+ } scan;
};
extern const struct dev_pm_ops hts221_pm_ops;
@@ -46,7 +49,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 */
diff --git a/drivers/iio/humidity/hts221_buffer.c b/drivers/iio/humidity/hts221_buffer.c
index 81d50a861c22..95e56917677f 100644
--- a/drivers/iio/humidity/hts221_buffer.c
+++ b/drivers/iio/humidity/hts221_buffer.c
@@ -72,12 +72,11 @@ 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 iio_dev *iio_dev = iio_priv_to_dev(hw);
+ struct hts221_hw *hw = iio_priv(iio_dev);
+ struct st_sensors_platform_data *pdata = dev_get_platdata(hw->dev);
bool irq_active_low = false, open_drain = false;
- struct device_node *np = hw->dev->of_node;
- struct st_sensors_platform_data *pdata;
unsigned long irq_type;
int err;
@@ -106,8 +105,7 @@ int hts221_allocate_trigger(struct hts221_hw *hw)
if (err < 0)
return err;
- pdata = (struct st_sensors_platform_data *)hw->dev->platform_data;
- if ((np && of_property_read_bool(np, "drive-open-drain")) ||
+ if (device_property_read_bool(hw->dev, "drive-open-drain") ||
(pdata && pdata->open_drain)) {
irq_type |= IRQF_SHARED;
open_drain = true;
@@ -155,14 +153,11 @@ 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,
};
static irqreturn_t hts221_buffer_handler_thread(int irq, void *p)
{
- u8 buffer[ALIGN(2 * HTS221_DATA_SIZE, sizeof(s64)) + sizeof(s64)];
struct iio_poll_func *pf = p;
struct iio_dev *iio_dev = pf->indio_dev;
struct hts221_hw *hw = iio_priv(iio_dev);
@@ -172,18 +167,20 @@ static irqreturn_t hts221_buffer_handler_thread(int irq, void *p)
/* humidity data */
ch = &iio_dev->channels[HTS221_SENSOR_H];
err = regmap_bulk_read(hw->regmap, ch->address,
- buffer, HTS221_DATA_SIZE);
+ &hw->scan.channels[0],
+ sizeof(hw->scan.channels[0]));
if (err < 0)
goto out;
/* temperature data */
ch = &iio_dev->channels[HTS221_SENSOR_T];
err = regmap_bulk_read(hw->regmap, ch->address,
- buffer + HTS221_DATA_SIZE, HTS221_DATA_SIZE);
+ &hw->scan.channels[1],
+ sizeof(hw->scan.channels[1]));
if (err < 0)
goto out;
- iio_push_to_buffers_with_timestamp(iio_dev, buffer,
+ iio_push_to_buffers_with_timestamp(iio_dev, &hw->scan,
iio_get_time_ns(iio_dev));
out:
@@ -192,9 +189,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);
}
diff --git a/drivers/iio/humidity/hts221_core.c b/drivers/iio/humidity/hts221_core.c
index 9003671f14fb..16657789dc45 100644
--- a/drivers/iio/humidity/hts221_core.c
+++ b/drivers/iio/humidity/hts221_core.c
@@ -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;
}
diff --git a/drivers/iio/humidity/hts221_i2c.c b/drivers/iio/humidity/hts221_i2c.c
index 4272b7030c44..cab39c4756f8 100644
--- a/drivers/iio/humidity/hts221_i2c.c
+++ b/drivers/iio/humidity/hts221_i2c.c
@@ -32,8 +32,8 @@ static int hts221_i2c_probe(struct i2c_client *client,
regmap = devm_regmap_init_i2c(client, &hts221_i2c_regmap_config);
if (IS_ERR(regmap)) {
- dev_err(&client->dev, "Failed to register i2c regmap %d\n",
- (int)PTR_ERR(regmap));
+ dev_err(&client->dev, "Failed to register i2c regmap %ld\n",
+ PTR_ERR(regmap));
return PTR_ERR(regmap);
}
@@ -63,7 +63,7 @@ static struct i2c_driver hts221_driver = {
.driver = {
.name = "hts221_i2c",
.pm = &hts221_pm_ops,
- .of_match_table = of_match_ptr(hts221_i2c_of_match),
+ .of_match_table = hts221_i2c_of_match,
.acpi_match_table = ACPI_PTR(hts221_acpi_match),
},
.probe = hts221_i2c_probe,
diff --git a/drivers/iio/humidity/hts221_spi.c b/drivers/iio/humidity/hts221_spi.c
index 055dba8897d2..729e86e433b1 100644
--- a/drivers/iio/humidity/hts221_spi.c
+++ b/drivers/iio/humidity/hts221_spi.c
@@ -31,8 +31,8 @@ static int hts221_spi_probe(struct spi_device *spi)
regmap = devm_regmap_init_spi(spi, &hts221_spi_regmap_config);
if (IS_ERR(regmap)) {
- dev_err(&spi->dev, "Failed to register spi regmap %d\n",
- (int)PTR_ERR(regmap));
+ dev_err(&spi->dev, "Failed to register spi regmap %ld\n",
+ PTR_ERR(regmap));
return PTR_ERR(regmap);
}
@@ -56,7 +56,7 @@ static struct spi_driver hts221_driver = {
.driver = {
.name = "hts221_spi",
.pm = &hts221_pm_ops,
- .of_match_table = of_match_ptr(hts221_spi_of_match),
+ .of_match_table = hts221_spi_of_match,
},
.probe = hts221_spi_probe,
.id_table = hts221_spi_id_table,
diff --git a/drivers/iio/humidity/htu21.c b/drivers/iio/humidity/htu21.c
index d4c0589844dd..4f5d9d1c05ab 100644
--- a/drivers/iio/humidity/htu21.c
+++ b/drivers/iio/humidity/htu21.c
@@ -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) {
diff --git a/drivers/iio/humidity/si7005.c b/drivers/iio/humidity/si7005.c
index d5aef0bfef01..160b3d92df61 100644
--- a/drivers/iio/humidity/si7005.c
+++ b/drivers/iio/humidity/si7005.c
@@ -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;
diff --git a/drivers/iio/humidity/si7020.c b/drivers/iio/humidity/si7020.c
index b938f07eed64..a09b5773d377 100644
--- a/drivers/iio/humidity/si7020.c
+++ b/drivers/iio/humidity/si7020.c
@@ -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;
diff --git a/drivers/iio/iio_core_trigger.h b/drivers/iio/iio_core_trigger.h
index e59fe2f36bbb..9d1a92cc6480 100644
--- a/drivers/iio/iio_core_trigger.h
+++ b/drivers/iio/iio_core_trigger.h
@@ -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 */
diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
index 60bb1029e759..f02883b08480 100644
--- a/drivers/iio/imu/Kconfig
+++ b/drivers/iio/imu/Kconfig
@@ -29,6 +29,19 @@ config ADIS16460
To compile this driver as a module, choose M here: the module will be
called adis16460.
+config ADIS16475
+ tristate "Analog Devices ADIS16475 and similar IMU driver"
+ depends on SPI
+ select IIO_ADIS_LIB
+ select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
+ help
+ Say yes here to build support for Analog Devices ADIS16470, ADIS16475,
+ ADIS16477, ADIS16465, ADIS16467, ADIS16500, ADIS16505, ADIS16507 inertial
+ sensors.
+
+ To compile this driver as a module, choose M here: the module will be
+ called adis16475.
+
config ADIS16480
tristate "Analog Devices ADIS16480 and similar IMU driver"
depends on SPI
@@ -78,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"
diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
index 5237fd4bc384..13e9ff442b11 100644
--- a/drivers/iio/imu/Makefile
+++ b/drivers/iio/imu/Makefile
@@ -6,6 +6,7 @@
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_ADIS16400) += adis16400.o
obj-$(CONFIG_ADIS16460) += adis16460.o
+obj-$(CONFIG_ADIS16475) += adis16475.o
obj-$(CONFIG_ADIS16480) += adis16480.o
adis_lib-y += adis.o
@@ -19,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
diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c
index a8afd01de4f3..319b64b2fd88 100644
--- a/drivers/iio/imu/adis.c
+++ b/drivers/iio/imu/adis.c
@@ -97,11 +97,11 @@ int __adis_write_reg(struct adis *adis, unsigned int reg,
adis->tx[9] = (value >> 24) & 0xff;
adis->tx[6] = ADIS_WRITE_REG(reg + 2);
adis->tx[7] = (value >> 16) & 0xff;
- /* fall through */
+ fallthrough;
case 2:
adis->tx[4] = ADIS_WRITE_REG(reg + 1);
adis->tx[5] = (value >> 8) & 0xff;
- /* fall through */
+ fallthrough;
case 1:
adis->tx[2] = ADIS_WRITE_REG(reg);
adis->tx[3] = value & 0xff;
@@ -191,7 +191,7 @@ int __adis_read_reg(struct adis *adis, unsigned int reg,
adis->tx[2] = ADIS_READ_REG(reg + 2);
adis->tx[3] = 0;
spi_message_add_tail(&xfers[1], &msg);
- /* fall through */
+ fallthrough;
case 2:
adis->tx[4] = ADIS_READ_REG(reg);
adis->tx[5] = 0;
@@ -223,6 +223,31 @@ int __adis_read_reg(struct adis *adis, unsigned int reg,
return ret;
}
EXPORT_SYMBOL_GPL(__adis_read_reg);
+/**
+ * __adis_update_bits_base() - ADIS Update bits function - Unlocked version
+ * @adis: The adis device
+ * @reg: The address of the lower of the two registers
+ * @mask: Bitmask to change
+ * @val: Value to be written
+ * @size: Size of the register to update
+ *
+ * Updates the desired bits of @reg in accordance with @mask and @val.
+ */
+int __adis_update_bits_base(struct adis *adis, unsigned int reg, const u32 mask,
+ const u32 val, u8 size)
+{
+ int ret;
+ u32 __val;
+
+ ret = __adis_read_reg(adis, reg, &__val, size);
+ if (ret)
+ return ret;
+
+ __val = (__val & ~mask) | (val & mask);
+
+ return __adis_write_reg(adis, reg, __val, size);
+}
+EXPORT_SYMBOL_GPL(__adis_update_bits_base);
#ifdef CONFIG_DEBUG_FS
@@ -419,7 +444,7 @@ int __adis_initial_startup(struct adis *adis)
if (prod_id != adis->data->prod_id)
dev_warn(&adis->spi->dev,
- "Device ID(%u) and product ID(%u) do not match.",
+ "Device ID(%u) and product ID(%u) do not match.\n",
adis->data->prod_id, prod_id);
return 0;
diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c
index 05e70c1c4835..1ebe3e50d3e6 100644
--- a/drivers/iio/imu/adis16400.c
+++ b/drivers/iio/imu/adis16400.c
@@ -258,7 +258,7 @@ static int adis16400_show_product_id(void *arg, u64 *val)
return 0;
}
-DEFINE_SIMPLE_ATTRIBUTE(adis16400_product_id_fops,
+DEFINE_DEBUGFS_ATTRIBUTE(adis16400_product_id_fops,
adis16400_show_product_id, NULL, "%lld\n");
static int adis16400_show_flash_count(void *arg, u64 *val)
@@ -275,23 +275,22 @@ static int adis16400_show_flash_count(void *arg, u64 *val)
return 0;
}
-DEFINE_SIMPLE_ATTRIBUTE(adis16400_flash_count_fops,
+DEFINE_DEBUGFS_ATTRIBUTE(adis16400_flash_count_fops,
adis16400_show_flash_count, NULL, "%lld\n");
static int adis16400_debugfs_init(struct iio_dev *indio_dev)
{
struct adis16400_state *st = iio_priv(indio_dev);
+ struct dentry *d = iio_get_debugfs_dentry(indio_dev);
if (st->variant->flags & ADIS16400_HAS_SERIAL_NUMBER)
- debugfs_create_file("serial_number", 0400,
- indio_dev->debugfs_dentry, st,
- &adis16400_serial_number_fops);
+ debugfs_create_file_unsafe("serial_number", 0400,
+ d, st, &adis16400_serial_number_fops);
if (st->variant->flags & ADIS16400_HAS_PROD_ID)
- debugfs_create_file("product_id", 0400,
- indio_dev->debugfs_dentry, st,
- &adis16400_product_id_fops);
- debugfs_create_file("flash_count", 0400, indio_dev->debugfs_dentry,
- st, &adis16400_flash_count_fops);
+ debugfs_create_file_unsafe("product_id", 0400,
+ d, st, &adis16400_product_id_fops);
+ debugfs_create_file_unsafe("flash_count", 0400,
+ d, st, &adis16400_flash_count_fops);
return 0;
}
@@ -1182,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;
@@ -1194,7 +1192,7 @@ static int adis16400_probe(struct spi_device *spi)
indio_dev->available_scan_masks = st->avail_scan_mask;
st->adis.burst = &adis16400_burst;
if (st->variant->flags & ADIS16400_BURST_DIAG_STAT)
- st->adis.burst->extra_len = sizeof(u16);
+ st->adis.burst_extra_len = sizeof(u16);
}
adis16400_data = &st->variant->adis_data;
diff --git a/drivers/iio/imu/adis16460.c b/drivers/iio/imu/adis16460.c
index 0027683d0256..b26a5f1bc51a 100644
--- a/drivers/iio/imu/adis16460.c
+++ b/drivers/iio/imu/adis16460.c
@@ -87,8 +87,8 @@ static int adis16460_show_serial_number(void *arg, u64 *val)
return 0;
}
-DEFINE_SIMPLE_ATTRIBUTE(adis16460_serial_number_fops,
- adis16460_show_serial_number, NULL, "0x%.4llx\n");
+DEFINE_DEBUGFS_ATTRIBUTE(adis16460_serial_number_fops,
+ adis16460_show_serial_number, NULL, "0x%.4llx\n");
static int adis16460_show_product_id(void *arg, u64 *val)
{
@@ -105,8 +105,8 @@ static int adis16460_show_product_id(void *arg, u64 *val)
return 0;
}
-DEFINE_SIMPLE_ATTRIBUTE(adis16460_product_id_fops,
- adis16460_show_product_id, NULL, "%llu\n");
+DEFINE_DEBUGFS_ATTRIBUTE(adis16460_product_id_fops,
+ adis16460_show_product_id, NULL, "%llu\n");
static int adis16460_show_flash_count(void *arg, u64 *val)
{
@@ -123,19 +123,20 @@ static int adis16460_show_flash_count(void *arg, u64 *val)
return 0;
}
-DEFINE_SIMPLE_ATTRIBUTE(adis16460_flash_count_fops,
- adis16460_show_flash_count, NULL, "%lld\n");
+DEFINE_DEBUGFS_ATTRIBUTE(adis16460_flash_count_fops,
+ adis16460_show_flash_count, NULL, "%lld\n");
static int adis16460_debugfs_init(struct iio_dev *indio_dev)
{
struct adis16460 *adis16460 = iio_priv(indio_dev);
+ struct dentry *d = iio_get_debugfs_dentry(indio_dev);
- debugfs_create_file("serial_number", 0400, indio_dev->debugfs_dentry,
- adis16460, &adis16460_serial_number_fops);
- debugfs_create_file("product_id", 0400, indio_dev->debugfs_dentry,
- adis16460, &adis16460_product_id_fops);
- debugfs_create_file("flash_count", 0400, indio_dev->debugfs_dentry,
- adis16460, &adis16460_flash_count_fops);
+ debugfs_create_file_unsafe("serial_number", 0400,
+ d, adis16460, &adis16460_serial_number_fops);
+ debugfs_create_file_unsafe("product_id", 0400,
+ d, adis16460, &adis16460_product_id_fops);
+ debugfs_create_file_unsafe("flash_count", 0400,
+ d, adis16460, &adis16460_flash_count_fops);
return 0;
}
@@ -392,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;
diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c
new file mode 100644
index 000000000000..35d10ccb66c2
--- /dev/null
+++ b/drivers/iio/imu/adis16475.c
@@ -0,0 +1,1337 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ADIS16475 IMU driver
+ *
+ * Copyright 2019 Analog Devices Inc.
+ */
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/imu/adis.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/property.h>
+#include <linux/spi/spi.h>
+
+#define ADIS16475_REG_DIAG_STAT 0x02
+#define ADIS16475_REG_X_GYRO_L 0x04
+#define ADIS16475_REG_Y_GYRO_L 0x08
+#define ADIS16475_REG_Z_GYRO_L 0x0C
+#define ADIS16475_REG_X_ACCEL_L 0x10
+#define ADIS16475_REG_Y_ACCEL_L 0x14
+#define ADIS16475_REG_Z_ACCEL_L 0x18
+#define ADIS16475_REG_TEMP_OUT 0x1c
+#define ADIS16475_REG_X_GYRO_BIAS_L 0x40
+#define ADIS16475_REG_Y_GYRO_BIAS_L 0x44
+#define ADIS16475_REG_Z_GYRO_BIAS_L 0x48
+#define ADIS16475_REG_X_ACCEL_BIAS_L 0x4c
+#define ADIS16475_REG_Y_ACCEL_BIAS_L 0x50
+#define ADIS16475_REG_Z_ACCEL_BIAS_L 0x54
+#define ADIS16475_REG_FILT_CTRL 0x5c
+#define ADIS16475_FILT_CTRL_MASK GENMASK(2, 0)
+#define ADIS16475_FILT_CTRL(x) FIELD_PREP(ADIS16475_FILT_CTRL_MASK, x)
+#define ADIS16475_REG_MSG_CTRL 0x60
+#define ADIS16475_MSG_CTRL_DR_POL_MASK BIT(0)
+#define ADIS16475_MSG_CTRL_DR_POL(x) \
+ FIELD_PREP(ADIS16475_MSG_CTRL_DR_POL_MASK, x)
+#define ADIS16475_SYNC_MODE_MASK GENMASK(4, 2)
+#define ADIS16475_SYNC_MODE(x) FIELD_PREP(ADIS16475_SYNC_MODE_MASK, x)
+#define ADIS16475_REG_UP_SCALE 0x62
+#define ADIS16475_REG_DEC_RATE 0x64
+#define ADIS16475_REG_GLOB_CMD 0x68
+#define ADIS16475_REG_FIRM_REV 0x6c
+#define ADIS16475_REG_FIRM_DM 0x6e
+#define ADIS16475_REG_FIRM_Y 0x70
+#define ADIS16475_REG_PROD_ID 0x72
+#define ADIS16475_REG_SERIAL_NUM 0x74
+#define ADIS16475_REG_FLASH_CNT 0x7c
+#define ADIS16500_BURST32_MASK BIT(9)
+#define ADIS16500_BURST32(x) FIELD_PREP(ADIS16500_BURST32_MASK, x)
+/* number of data elements in burst mode */
+#define ADIS16475_BURST32_MAX_DATA 32
+#define ADIS16475_BURST_MAX_DATA 20
+#define ADIS16475_MAX_SCAN_DATA 20
+/* spi max speed in brust mode */
+#define ADIS16475_BURST_MAX_SPEED 1000000
+#define ADIS16475_LSB_DEC_MASK BIT(0)
+#define ADIS16475_LSB_FIR_MASK BIT(1)
+
+enum {
+ ADIS16475_SYNC_DIRECT = 1,
+ ADIS16475_SYNC_SCALED,
+ ADIS16475_SYNC_OUTPUT,
+ ADIS16475_SYNC_PULSE = 5,
+};
+
+struct adis16475_sync {
+ u16 sync_mode;
+ u16 min_rate;
+ u16 max_rate;
+};
+
+struct adis16475_chip_info {
+ const struct iio_chan_spec *channels;
+ const struct adis16475_sync *sync;
+ const struct adis_data adis_data;
+ const char *name;
+ u32 num_channels;
+ u32 gyro_max_val;
+ u32 gyro_max_scale;
+ u32 accel_max_val;
+ u32 accel_max_scale;
+ u32 temp_scale;
+ u32 int_clk;
+ u16 max_dec;
+ u8 num_sync;
+ bool has_burst32;
+};
+
+struct adis16475 {
+ const struct adis16475_chip_info *info;
+ struct adis adis;
+ u32 clk_freq;
+ bool burst32;
+ unsigned long lsb_flag;
+ /* Alignment needed for the timestamp */
+ __be16 data[ADIS16475_MAX_SCAN_DATA] __aligned(8);
+};
+
+enum {
+ ADIS16475_SCAN_GYRO_X,
+ ADIS16475_SCAN_GYRO_Y,
+ ADIS16475_SCAN_GYRO_Z,
+ ADIS16475_SCAN_ACCEL_X,
+ ADIS16475_SCAN_ACCEL_Y,
+ ADIS16475_SCAN_ACCEL_Z,
+ ADIS16475_SCAN_TEMP,
+ ADIS16475_SCAN_DIAG_S_FLAGS,
+ ADIS16475_SCAN_CRC_FAILURE,
+};
+
+#ifdef CONFIG_DEBUG_FS
+static ssize_t adis16475_show_firmware_revision(struct file *file,
+ char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct adis16475 *st = file->private_data;
+ char buf[7];
+ size_t len;
+ u16 rev;
+ int ret;
+
+ ret = adis_read_reg_16(&st->adis, ADIS16475_REG_FIRM_REV, &rev);
+ if (ret)
+ return ret;
+
+ len = scnprintf(buf, sizeof(buf), "%x.%x\n", rev >> 8, rev & 0xff);
+
+ return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+
+static const struct file_operations adis16475_firmware_revision_fops = {
+ .open = simple_open,
+ .read = adis16475_show_firmware_revision,
+ .llseek = default_llseek,
+ .owner = THIS_MODULE,
+};
+
+static ssize_t adis16475_show_firmware_date(struct file *file,
+ char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct adis16475 *st = file->private_data;
+ u16 md, year;
+ char buf[12];
+ size_t len;
+ int ret;
+
+ ret = adis_read_reg_16(&st->adis, ADIS16475_REG_FIRM_Y, &year);
+ if (ret)
+ return ret;
+
+ ret = adis_read_reg_16(&st->adis, ADIS16475_REG_FIRM_DM, &md);
+ if (ret)
+ return ret;
+
+ len = snprintf(buf, sizeof(buf), "%.2x-%.2x-%.4x\n", md >> 8, md & 0xff,
+ year);
+
+ return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+
+static const struct file_operations adis16475_firmware_date_fops = {
+ .open = simple_open,
+ .read = adis16475_show_firmware_date,
+ .llseek = default_llseek,
+ .owner = THIS_MODULE,
+};
+
+static int adis16475_show_serial_number(void *arg, u64 *val)
+{
+ struct adis16475 *st = arg;
+ u16 serial;
+ int ret;
+
+ ret = adis_read_reg_16(&st->adis, ADIS16475_REG_SERIAL_NUM, &serial);
+ if (ret)
+ return ret;
+
+ *val = serial;
+
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(adis16475_serial_number_fops,
+ adis16475_show_serial_number, NULL, "0x%.4llx\n");
+
+static int adis16475_show_product_id(void *arg, u64 *val)
+{
+ struct adis16475 *st = arg;
+ u16 prod_id;
+ int ret;
+
+ ret = adis_read_reg_16(&st->adis, ADIS16475_REG_PROD_ID, &prod_id);
+ if (ret)
+ return ret;
+
+ *val = prod_id;
+
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(adis16475_product_id_fops,
+ adis16475_show_product_id, NULL, "%llu\n");
+
+static int adis16475_show_flash_count(void *arg, u64 *val)
+{
+ struct adis16475 *st = arg;
+ u32 flash_count;
+ int ret;
+
+ ret = adis_read_reg_32(&st->adis, ADIS16475_REG_FLASH_CNT,
+ &flash_count);
+ if (ret)
+ return ret;
+
+ *val = flash_count;
+
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(adis16475_flash_count_fops,
+ adis16475_show_flash_count, NULL, "%lld\n");
+
+static void adis16475_debugfs_init(struct iio_dev *indio_dev)
+{
+ struct adis16475 *st = iio_priv(indio_dev);
+ struct dentry *d = iio_get_debugfs_dentry(indio_dev);
+
+ debugfs_create_file_unsafe("serial_number", 0400,
+ d, st, &adis16475_serial_number_fops);
+ debugfs_create_file_unsafe("product_id", 0400,
+ d, st, &adis16475_product_id_fops);
+ debugfs_create_file_unsafe("flash_count", 0400,
+ d, st, &adis16475_flash_count_fops);
+ debugfs_create_file("firmware_revision", 0400,
+ d, st, &adis16475_firmware_revision_fops);
+ debugfs_create_file("firmware_date", 0400, d,
+ st, &adis16475_firmware_date_fops);
+}
+#else
+static void adis16475_debugfs_init(struct iio_dev *indio_dev)
+{
+}
+#endif
+
+static int adis16475_get_freq(struct adis16475 *st, u32 *freq)
+{
+ int ret;
+ u16 dec;
+
+ ret = adis_read_reg_16(&st->adis, ADIS16475_REG_DEC_RATE, &dec);
+ if (ret)
+ return -EINVAL;
+
+ *freq = DIV_ROUND_CLOSEST(st->clk_freq, dec + 1);
+
+ return 0;
+}
+
+static int adis16475_set_freq(struct adis16475 *st, const u32 freq)
+{
+ u16 dec;
+ int ret;
+
+ if (!freq)
+ return -EINVAL;
+
+ dec = DIV_ROUND_CLOSEST(st->clk_freq, freq);
+
+ if (dec)
+ dec--;
+
+ if (dec > st->info->max_dec)
+ dec = st->info->max_dec;
+
+ ret = adis_write_reg_16(&st->adis, ADIS16475_REG_DEC_RATE, dec);
+ if (ret)
+ return ret;
+
+ /*
+ * If decimation is used, then gyro and accel data will have meaningful
+ * bits on the LSB registers. This info is used on the trigger handler.
+ */
+ assign_bit(ADIS16475_LSB_DEC_MASK, &st->lsb_flag, dec);
+
+ return 0;
+}
+
+/* The values are approximated. */
+static const u32 adis16475_3db_freqs[] = {
+ [0] = 720, /* Filter disabled, full BW (~720Hz) */
+ [1] = 360,
+ [2] = 164,
+ [3] = 80,
+ [4] = 40,
+ [5] = 20,
+ [6] = 10,
+};
+
+static int adis16475_get_filter(struct adis16475 *st, u32 *filter)
+{
+ u16 filter_sz;
+ int ret;
+ const int mask = ADIS16475_FILT_CTRL_MASK;
+
+ ret = adis_read_reg_16(&st->adis, ADIS16475_REG_FILT_CTRL, &filter_sz);
+ if (ret)
+ return ret;
+
+ *filter = adis16475_3db_freqs[filter_sz & mask];
+
+ return 0;
+}
+
+static int adis16475_set_filter(struct adis16475 *st, const u32 filter)
+{
+ int i = ARRAY_SIZE(adis16475_3db_freqs);
+ int ret;
+
+ while (--i) {
+ if (adis16475_3db_freqs[i] >= filter)
+ break;
+ }
+
+ ret = adis_write_reg_16(&st->adis, ADIS16475_REG_FILT_CTRL,
+ ADIS16475_FILT_CTRL(i));
+ if (ret)
+ return ret;
+
+ /*
+ * If FIR is used, then gyro and accel data will have meaningful
+ * bits on the LSB registers. This info is used on the trigger handler.
+ */
+ assign_bit(ADIS16475_LSB_FIR_MASK, &st->lsb_flag, i);
+
+ return 0;
+}
+
+static const u32 adis16475_calib_regs[] = {
+ [ADIS16475_SCAN_GYRO_X] = ADIS16475_REG_X_GYRO_BIAS_L,
+ [ADIS16475_SCAN_GYRO_Y] = ADIS16475_REG_Y_GYRO_BIAS_L,
+ [ADIS16475_SCAN_GYRO_Z] = ADIS16475_REG_Z_GYRO_BIAS_L,
+ [ADIS16475_SCAN_ACCEL_X] = ADIS16475_REG_X_ACCEL_BIAS_L,
+ [ADIS16475_SCAN_ACCEL_Y] = ADIS16475_REG_Y_ACCEL_BIAS_L,
+ [ADIS16475_SCAN_ACCEL_Z] = ADIS16475_REG_Z_ACCEL_BIAS_L,
+};
+
+static int adis16475_read_raw(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ int *val, int *val2, long info)
+{
+ struct adis16475 *st = iio_priv(indio_dev);
+ int ret;
+ u32 tmp;
+
+ switch (info) {
+ case IIO_CHAN_INFO_RAW:
+ return adis_single_conversion(indio_dev, chan, 0, val);
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_ANGL_VEL:
+ *val = st->info->gyro_max_val;
+ *val2 = st->info->gyro_max_scale;
+ return IIO_VAL_FRACTIONAL;
+ case IIO_ACCEL:
+ *val = st->info->accel_max_val;
+ *val2 = st->info->accel_max_scale;
+ return IIO_VAL_FRACTIONAL;
+ case IIO_TEMP:
+ *val = st->info->temp_scale;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_CALIBBIAS:
+ ret = adis_read_reg_32(&st->adis,
+ adis16475_calib_regs[chan->scan_index],
+ val);
+ if (ret)
+ return ret;
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+ ret = adis16475_get_filter(st, val);
+ if (ret)
+ return ret;
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ ret = adis16475_get_freq(st, &tmp);
+ if (ret)
+ return ret;
+
+ *val = tmp / 1000;
+ *val2 = (tmp % 1000) * 1000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int adis16475_write_raw(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ int val, int val2, long info)
+{
+ struct adis16475 *st = iio_priv(indio_dev);
+ u32 tmp;
+
+ switch (info) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ tmp = val * 1000 + val2 / 1000;
+ return adis16475_set_freq(st, tmp);
+ case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+ return adis16475_set_filter(st, val);
+ case IIO_CHAN_INFO_CALIBBIAS:
+ return adis_write_reg_32(&st->adis,
+ adis16475_calib_regs[chan->scan_index],
+ val);
+ default:
+ return -EINVAL;
+ }
+}
+
+#define ADIS16475_MOD_CHAN(_type, _mod, _address, _si, _r_bits, _s_bits) \
+ { \
+ .type = (_type), \
+ .modified = 1, \
+ .channel2 = (_mod), \
+ .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_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
+ .address = (_address), \
+ .scan_index = (_si), \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = (_r_bits), \
+ .storagebits = (_s_bits), \
+ .endianness = IIO_BE, \
+ }, \
+ }
+
+#define ADIS16475_GYRO_CHANNEL(_mod) \
+ ADIS16475_MOD_CHAN(IIO_ANGL_VEL, IIO_MOD_ ## _mod, \
+ ADIS16475_REG_ ## _mod ## _GYRO_L, \
+ ADIS16475_SCAN_GYRO_ ## _mod, 32, 32)
+
+#define ADIS16475_ACCEL_CHANNEL(_mod) \
+ ADIS16475_MOD_CHAN(IIO_ACCEL, IIO_MOD_ ## _mod, \
+ ADIS16475_REG_ ## _mod ## _ACCEL_L, \
+ ADIS16475_SCAN_ACCEL_ ## _mod, 32, 32)
+
+#define ADIS16475_TEMP_CHANNEL() { \
+ .type = IIO_TEMP, \
+ .indexed = 1, \
+ .channel = 0, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
+ .address = ADIS16475_REG_TEMP_OUT, \
+ .scan_index = ADIS16475_SCAN_TEMP, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_BE, \
+ }, \
+ }
+
+static const struct iio_chan_spec adis16475_channels[] = {
+ ADIS16475_GYRO_CHANNEL(X),
+ ADIS16475_GYRO_CHANNEL(Y),
+ ADIS16475_GYRO_CHANNEL(Z),
+ ADIS16475_ACCEL_CHANNEL(X),
+ ADIS16475_ACCEL_CHANNEL(Y),
+ ADIS16475_ACCEL_CHANNEL(Z),
+ ADIS16475_TEMP_CHANNEL(),
+ IIO_CHAN_SOFT_TIMESTAMP(7)
+};
+
+enum adis16475_variant {
+ ADIS16470,
+ ADIS16475_1,
+ ADIS16475_2,
+ ADIS16475_3,
+ ADIS16477_1,
+ ADIS16477_2,
+ ADIS16477_3,
+ ADIS16465_1,
+ ADIS16465_2,
+ ADIS16465_3,
+ ADIS16467_1,
+ ADIS16467_2,
+ ADIS16467_3,
+ ADIS16500,
+ ADIS16505_1,
+ ADIS16505_2,
+ ADIS16505_3,
+ ADIS16507_1,
+ ADIS16507_2,
+ ADIS16507_3,
+};
+
+enum {
+ ADIS16475_DIAG_STAT_DATA_PATH = 1,
+ ADIS16475_DIAG_STAT_FLASH_MEM,
+ ADIS16475_DIAG_STAT_SPI,
+ ADIS16475_DIAG_STAT_STANDBY,
+ ADIS16475_DIAG_STAT_SENSOR,
+ ADIS16475_DIAG_STAT_MEMORY,
+ ADIS16475_DIAG_STAT_CLK,
+};
+
+static const char * const adis16475_status_error_msgs[] = {
+ [ADIS16475_DIAG_STAT_DATA_PATH] = "Data Path Overrun",
+ [ADIS16475_DIAG_STAT_FLASH_MEM] = "Flash memory update failure",
+ [ADIS16475_DIAG_STAT_SPI] = "SPI communication error",
+ [ADIS16475_DIAG_STAT_STANDBY] = "Standby mode",
+ [ADIS16475_DIAG_STAT_SENSOR] = "Sensor failure",
+ [ADIS16475_DIAG_STAT_MEMORY] = "Memory failure",
+ [ADIS16475_DIAG_STAT_CLK] = "Clock error",
+};
+
+static int adis16475_enable_irq(struct adis *adis, bool enable)
+{
+ /*
+ * There is no way to gate the data-ready signal internally inside the
+ * ADIS16475. We can only control it's polarity...
+ */
+ if (enable)
+ enable_irq(adis->spi->irq);
+ else
+ disable_irq(adis->spi->irq);
+
+ return 0;
+}
+
+#define ADIS16475_DATA(_prod_id, _timeouts) \
+{ \
+ .msc_ctrl_reg = ADIS16475_REG_MSG_CTRL, \
+ .glob_cmd_reg = ADIS16475_REG_GLOB_CMD, \
+ .diag_stat_reg = ADIS16475_REG_DIAG_STAT, \
+ .prod_id_reg = ADIS16475_REG_PROD_ID, \
+ .prod_id = (_prod_id), \
+ .self_test_mask = BIT(2), \
+ .self_test_reg = ADIS16475_REG_GLOB_CMD, \
+ .cs_change_delay = 16, \
+ .read_delay = 5, \
+ .write_delay = 5, \
+ .status_error_msgs = adis16475_status_error_msgs, \
+ .status_error_mask = BIT(ADIS16475_DIAG_STAT_DATA_PATH) | \
+ BIT(ADIS16475_DIAG_STAT_FLASH_MEM) | \
+ BIT(ADIS16475_DIAG_STAT_SPI) | \
+ BIT(ADIS16475_DIAG_STAT_STANDBY) | \
+ BIT(ADIS16475_DIAG_STAT_SENSOR) | \
+ BIT(ADIS16475_DIAG_STAT_MEMORY) | \
+ BIT(ADIS16475_DIAG_STAT_CLK), \
+ .enable_irq = adis16475_enable_irq, \
+ .timeouts = (_timeouts), \
+}
+
+static const struct adis16475_sync adis16475_sync_mode[] = {
+ { ADIS16475_SYNC_OUTPUT },
+ { ADIS16475_SYNC_DIRECT, 1900, 2100 },
+ { ADIS16475_SYNC_SCALED, 1, 128 },
+ { ADIS16475_SYNC_PULSE, 1000, 2100 },
+};
+
+static const struct adis_timeout adis16475_timeouts = {
+ .reset_ms = 200,
+ .sw_reset_ms = 200,
+ .self_test_ms = 20,
+};
+
+static const struct adis_timeout adis1650x_timeouts = {
+ .reset_ms = 260,
+ .sw_reset_ms = 260,
+ .self_test_ms = 30,
+};
+
+static const struct adis16475_chip_info adis16475_chip_info[] = {
+ [ADIS16470] = {
+ .name = "adis16470",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16470, &adis16475_timeouts),
+ },
+ [ADIS16475_1] = {
+ .name = "adis16475-1",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts),
+ },
+ [ADIS16475_2] = {
+ .name = "adis16475-2",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts),
+ },
+ [ADIS16475_3] = {
+ .name = "adis16475-3",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts),
+ },
+ [ADIS16477_1] = {
+ .name = "adis16477-1",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts),
+ },
+ [ADIS16477_2] = {
+ .name = "adis16477-2",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts),
+ },
+ [ADIS16477_3] = {
+ .name = "adis16477-3",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts),
+ },
+ [ADIS16465_1] = {
+ .name = "adis16465-1",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts),
+ },
+ [ADIS16465_2] = {
+ .name = "adis16465-2",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts),
+ },
+ [ADIS16465_3] = {
+ .name = "adis16465-3",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts),
+ },
+ [ADIS16467_1] = {
+ .name = "adis16467-1",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts),
+ },
+ [ADIS16467_2] = {
+ .name = "adis16467-2",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts),
+ },
+ [ADIS16467_3] = {
+ .name = "adis16467-3",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode),
+ .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts),
+ },
+ [ADIS16500] = {
+ .name = "adis16500",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
+ .accel_max_val = 392,
+ .accel_max_scale = 32000 << 16,
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ /* pulse sync not supported */
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
+ .has_burst32 = true,
+ .adis_data = ADIS16475_DATA(16500, &adis1650x_timeouts),
+ },
+ [ADIS16505_1] = {
+ .name = "adis16505-1",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16),
+ .accel_max_val = 78,
+ .accel_max_scale = 32000 << 16,
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ /* pulse sync not supported */
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
+ .has_burst32 = true,
+ .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts),
+ },
+ [ADIS16505_2] = {
+ .name = "adis16505-2",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
+ .accel_max_val = 78,
+ .accel_max_scale = 32000 << 16,
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ /* pulse sync not supported */
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
+ .has_burst32 = true,
+ .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts),
+ },
+ [ADIS16505_3] = {
+ .name = "adis16505-3",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
+ .accel_max_val = 78,
+ .accel_max_scale = 32000 << 16,
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ /* pulse sync not supported */
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
+ .has_burst32 = true,
+ .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts),
+ },
+ [ADIS16507_1] = {
+ .name = "adis16507-1",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16),
+ .accel_max_val = 392,
+ .accel_max_scale = 32000 << 16,
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ /* pulse sync not supported */
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
+ .has_burst32 = true,
+ .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts),
+ },
+ [ADIS16507_2] = {
+ .name = "adis16507-2",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
+ .accel_max_val = 392,
+ .accel_max_scale = 32000 << 16,
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ /* pulse sync not supported */
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
+ .has_burst32 = true,
+ .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts),
+ },
+ [ADIS16507_3] = {
+ .name = "adis16507-3",
+ .num_channels = ARRAY_SIZE(adis16475_channels),
+ .channels = adis16475_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
+ .accel_max_val = 392,
+ .accel_max_scale = 32000 << 16,
+ .temp_scale = 100,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ /* pulse sync not supported */
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
+ .has_burst32 = true,
+ .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts),
+ },
+};
+
+static const struct iio_info adis16475_info = {
+ .read_raw = &adis16475_read_raw,
+ .write_raw = &adis16475_write_raw,
+ .update_scan_mode = adis_update_scan_mode,
+ .debugfs_reg_access = adis_debugfs_reg_access,
+};
+
+static struct adis_burst adis16475_burst = {
+ .en = true,
+ .reg_cmd = ADIS16475_REG_GLOB_CMD,
+ /*
+ * adis_update_scan_mode_burst() sets the burst length in respect with
+ * the number of channels and allocates 16 bits for each. However,
+ * adis1647x devices also need space for DIAG_STAT, DATA_CNTR or
+ * TIME_STAMP (depending on the clock mode but for us these bytes are
+ * don't care...) and CRC.
+ */
+ .extra_len = 3 * sizeof(u16),
+ .burst_max_len = ADIS16475_BURST32_MAX_DATA,
+};
+
+static bool adis16475_validate_crc(const u8 *buffer, u16 crc,
+ const bool burst32)
+{
+ int i;
+ /* extra 6 elements for low gyro and accel */
+ const u16 sz = burst32 ? ADIS16475_BURST32_MAX_DATA :
+ ADIS16475_BURST_MAX_DATA;
+
+ for (i = 0; i < sz - 2; i++)
+ crc -= buffer[i];
+
+ return crc == 0;
+}
+
+static void adis16475_burst32_check(struct adis16475 *st)
+{
+ int ret;
+ struct adis *adis = &st->adis;
+
+ if (!st->info->has_burst32)
+ return;
+
+ if (st->lsb_flag && !st->burst32) {
+ const u16 en = ADIS16500_BURST32(1);
+
+ ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL,
+ ADIS16500_BURST32_MASK, en);
+ if (ret)
+ return;
+
+ st->burst32 = true;
+
+ /*
+ * In 32-bit mode we need extra 2 bytes for all gyro
+ * and accel channels.
+ */
+ adis->burst_extra_len = 6 * sizeof(u16);
+ adis->xfer[1].len += 6 * sizeof(u16);
+ dev_dbg(&adis->spi->dev, "Enable burst32 mode, xfer:%d",
+ adis->xfer[1].len);
+
+ } else if (!st->lsb_flag && st->burst32) {
+ const u16 en = ADIS16500_BURST32(0);
+
+ ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL,
+ ADIS16500_BURST32_MASK, en);
+ if (ret)
+ return;
+
+ st->burst32 = false;
+
+ /* Remove the extra bits */
+ adis->burst_extra_len = 0;
+ adis->xfer[1].len -= 6 * sizeof(u16);
+ dev_dbg(&adis->spi->dev, "Disable burst32 mode, xfer:%d\n",
+ adis->xfer[1].len);
+ }
+}
+
+static irqreturn_t adis16475_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct adis16475 *st = iio_priv(indio_dev);
+ struct adis *adis = &st->adis;
+ int ret, bit, i = 0;
+ __be16 *buffer;
+ u16 crc;
+ bool valid;
+ /* offset until the first element after gyro and accel */
+ const u8 offset = st->burst32 ? 13 : 7;
+ const u32 cached_spi_speed_hz = adis->spi->max_speed_hz;
+
+ adis->spi->max_speed_hz = ADIS16475_BURST_MAX_SPEED;
+
+ ret = spi_sync(adis->spi, &adis->msg);
+ if (ret)
+ return ret;
+
+ adis->spi->max_speed_hz = cached_spi_speed_hz;
+ buffer = adis->buffer;
+
+ crc = be16_to_cpu(buffer[offset + 2]);
+ valid = adis16475_validate_crc(adis->buffer, crc, st->burst32);
+ if (!valid) {
+ dev_err(&adis->spi->dev, "Invalid crc\n");
+ goto check_burst32;
+ }
+
+ for_each_set_bit(bit, indio_dev->active_scan_mask,
+ indio_dev->masklength) {
+ /*
+ * When burst mode is used, system flags is the first data
+ * channel in the sequence, but the scan index is 7.
+ */
+ switch (bit) {
+ case ADIS16475_SCAN_TEMP:
+ st->data[i++] = buffer[offset];
+ break;
+ case ADIS16475_SCAN_GYRO_X ... ADIS16475_SCAN_ACCEL_Z:
+ /*
+ * The first 2 bytes on the received data are the
+ * DIAG_STAT reg, hence the +1 offset here...
+ */
+ if (st->burst32) {
+ /* upper 16 */
+ st->data[i++] = buffer[bit * 2 + 2];
+ /* lower 16 */
+ st->data[i++] = buffer[bit * 2 + 1];
+ } else {
+ st->data[i++] = buffer[bit + 1];
+ /*
+ * Don't bother in doing the manual read if the
+ * device supports burst32. burst32 will be
+ * enabled in the next call to
+ * adis16475_burst32_check()...
+ */
+ if (st->lsb_flag && !st->info->has_burst32) {
+ u16 val = 0;
+ const u32 reg = ADIS16475_REG_X_GYRO_L +
+ bit * 4;
+
+ adis_read_reg_16(adis, reg, &val);
+ st->data[i++] = cpu_to_be16(val);
+ } else {
+ /* lower not used */
+ st->data[i++] = 0;
+ }
+ }
+ break;
+ }
+ }
+
+ iio_push_to_buffers_with_timestamp(indio_dev, st->data, pf->timestamp);
+check_burst32:
+ /*
+ * We only check the burst mode at the end of the current capture since
+ * it takes a full data ready cycle for the device to update the burst
+ * array.
+ */
+ adis16475_burst32_check(st);
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static void adis16475_disable_clk(void *data)
+{
+ clk_disable_unprepare((struct clk *)data);
+}
+
+static int adis16475_config_sync_mode(struct adis16475 *st)
+{
+ int ret;
+ struct device *dev = &st->adis.spi->dev;
+ const struct adis16475_sync *sync;
+ u32 sync_mode;
+
+ /* default to internal clk */
+ st->clk_freq = st->info->int_clk * 1000;
+
+ ret = device_property_read_u32(dev, "adi,sync-mode", &sync_mode);
+ if (ret)
+ return 0;
+
+ if (sync_mode >= st->info->num_sync) {
+ dev_err(dev, "Invalid sync mode: %u for %s\n", sync_mode,
+ st->info->name);
+ return -EINVAL;
+ }
+
+ sync = &st->info->sync[sync_mode];
+
+ /* All the other modes require external input signal */
+ if (sync->sync_mode != ADIS16475_SYNC_OUTPUT) {
+ struct clk *clk = devm_clk_get(dev, NULL);
+
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ ret = clk_prepare_enable(clk);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(dev, adis16475_disable_clk, clk);
+ if (ret)
+ return ret;
+
+ st->clk_freq = clk_get_rate(clk);
+ if (st->clk_freq < sync->min_rate ||
+ st->clk_freq > sync->max_rate) {
+ dev_err(dev,
+ "Clk rate:%u not in a valid range:[%u %u]\n",
+ st->clk_freq, sync->min_rate, sync->max_rate);
+ return -EINVAL;
+ }
+
+ if (sync->sync_mode == ADIS16475_SYNC_SCALED) {
+ u16 up_scale;
+ u32 scaled_out_freq = 0;
+ /*
+ * If we are in scaled mode, we must have an up_scale.
+ * In scaled mode the allowable input clock range is
+ * 1 Hz to 128 Hz, and the allowable output range is
+ * 1900 to 2100 Hz. Hence, a scale must be given to
+ * get the allowable output.
+ */
+ ret = device_property_read_u32(dev,
+ "adi,scaled-output-hz",
+ &scaled_out_freq);
+ if (ret) {
+ dev_err(dev, "adi,scaled-output-hz must be given when in scaled sync mode");
+ return -EINVAL;
+ } else if (scaled_out_freq < 1900 ||
+ scaled_out_freq > 2100) {
+ dev_err(dev, "Invalid value: %u for adi,scaled-output-hz",
+ scaled_out_freq);
+ return -EINVAL;
+ }
+
+ up_scale = DIV_ROUND_CLOSEST(scaled_out_freq,
+ st->clk_freq);
+
+ ret = __adis_write_reg_16(&st->adis,
+ ADIS16475_REG_UP_SCALE,
+ up_scale);
+ if (ret)
+ return ret;
+
+ st->clk_freq = scaled_out_freq;
+ }
+
+ st->clk_freq *= 1000;
+ }
+ /*
+ * Keep in mind that the mask for the clk modes in adis1650*
+ * chips is different (1100 instead of 11100). However, we
+ * are not configuring BIT(4) in these chips and the default
+ * value is 0, so we are fine in doing the below operations.
+ * I'm keeping this for simplicity and avoiding extra variables
+ * in chip_info.
+ */
+ ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL,
+ ADIS16475_SYNC_MODE_MASK, sync->sync_mode);
+ if (ret)
+ return ret;
+
+ usleep_range(250, 260);
+
+ return 0;
+}
+
+static int adis16475_config_irq_pin(struct adis16475 *st)
+{
+ int ret;
+ struct irq_data *desc;
+ u32 irq_type;
+ u16 val = 0;
+ u8 polarity;
+ struct spi_device *spi = st->adis.spi;
+
+ desc = irq_get_irq_data(spi->irq);
+ if (!desc) {
+ dev_err(&spi->dev, "Could not find IRQ %d\n", spi->irq);
+ return -EINVAL;
+ }
+ /*
+ * It is possible to configure the data ready polarity. Furthermore, we
+ * need to update the adis struct if we want data ready as active low.
+ */
+ irq_type = irqd_get_trigger_type(desc);
+ if (irq_type == IRQ_TYPE_EDGE_RISING) {
+ polarity = 1;
+ st->adis.irq_flag = IRQF_TRIGGER_RISING;
+ } else if (irq_type == IRQ_TYPE_EDGE_FALLING) {
+ polarity = 0;
+ st->adis.irq_flag = IRQF_TRIGGER_FALLING;
+ } else {
+ dev_err(&spi->dev, "Invalid interrupt type 0x%x specified\n",
+ irq_type);
+ return -EINVAL;
+ }
+
+ val = ADIS16475_MSG_CTRL_DR_POL(polarity);
+ ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL,
+ ADIS16475_MSG_CTRL_DR_POL_MASK, val);
+ if (ret)
+ return ret;
+ /*
+ * There is a delay writing to any bits written to the MSC_CTRL
+ * register. It should not be bigger than 200us, so 250 should be more
+ * than enough!
+ */
+ usleep_range(250, 260);
+
+ return 0;
+}
+
+static const struct of_device_id adis16475_of_match[] = {
+ { .compatible = "adi,adis16470",
+ .data = &adis16475_chip_info[ADIS16470] },
+ { .compatible = "adi,adis16475-1",
+ .data = &adis16475_chip_info[ADIS16475_1] },
+ { .compatible = "adi,adis16475-2",
+ .data = &adis16475_chip_info[ADIS16475_2] },
+ { .compatible = "adi,adis16475-3",
+ .data = &adis16475_chip_info[ADIS16475_3] },
+ { .compatible = "adi,adis16477-1",
+ .data = &adis16475_chip_info[ADIS16477_1] },
+ { .compatible = "adi,adis16477-2",
+ .data = &adis16475_chip_info[ADIS16477_2] },
+ { .compatible = "adi,adis16477-3",
+ .data = &adis16475_chip_info[ADIS16477_3] },
+ { .compatible = "adi,adis16465-1",
+ .data = &adis16475_chip_info[ADIS16465_1] },
+ { .compatible = "adi,adis16465-2",
+ .data = &adis16475_chip_info[ADIS16465_2] },
+ { .compatible = "adi,adis16465-3",
+ .data = &adis16475_chip_info[ADIS16465_3] },
+ { .compatible = "adi,adis16467-1",
+ .data = &adis16475_chip_info[ADIS16467_1] },
+ { .compatible = "adi,adis16467-2",
+ .data = &adis16475_chip_info[ADIS16467_2] },
+ { .compatible = "adi,adis16467-3",
+ .data = &adis16475_chip_info[ADIS16467_3] },
+ { .compatible = "adi,adis16500",
+ .data = &adis16475_chip_info[ADIS16500] },
+ { .compatible = "adi,adis16505-1",
+ .data = &adis16475_chip_info[ADIS16505_1] },
+ { .compatible = "adi,adis16505-2",
+ .data = &adis16475_chip_info[ADIS16505_2] },
+ { .compatible = "adi,adis16505-3",
+ .data = &adis16475_chip_info[ADIS16505_3] },
+ { .compatible = "adi,adis16507-1",
+ .data = &adis16475_chip_info[ADIS16507_1] },
+ { .compatible = "adi,adis16507-2",
+ .data = &adis16475_chip_info[ADIS16507_2] },
+ { .compatible = "adi,adis16507-3",
+ .data = &adis16475_chip_info[ADIS16507_3] },
+ { },
+};
+MODULE_DEVICE_TABLE(of, adis16475_of_match);
+
+static int adis16475_probe(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev;
+ struct adis16475 *st;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+ spi_set_drvdata(spi, indio_dev);
+ st->adis.burst = &adis16475_burst;
+
+ st->info = device_get_match_data(&spi->dev);
+ if (!st->info)
+ return -EINVAL;
+
+ ret = adis_init(&st->adis, indio_dev, spi, &st->info->adis_data);
+ if (ret)
+ return ret;
+
+ indio_dev->name = st->info->name;
+ indio_dev->channels = st->info->channels;
+ indio_dev->num_channels = st->info->num_channels;
+ indio_dev->info = &adis16475_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ ret = __adis_initial_startup(&st->adis);
+ if (ret)
+ return ret;
+
+ ret = adis16475_config_irq_pin(st);
+ if (ret)
+ return ret;
+
+ ret = adis16475_config_sync_mode(st);
+ if (ret)
+ return ret;
+
+ ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev,
+ adis16475_trigger_handler);
+ if (ret)
+ return ret;
+
+ adis16475_enable_irq(&st->adis, false);
+
+ ret = devm_iio_device_register(&spi->dev, indio_dev);
+ if (ret)
+ return ret;
+
+ adis16475_debugfs_init(indio_dev);
+
+ return 0;
+}
+
+static struct spi_driver adis16475_driver = {
+ .driver = {
+ .name = "adis16475",
+ .of_match_table = adis16475_of_match,
+ },
+ .probe = adis16475_probe,
+};
+module_spi_driver(adis16475_driver);
+
+MODULE_AUTHOR("Nuno Sa <nuno.sa@analog.com>");
+MODULE_DESCRIPTION("Analog Devices ADIS16475 IMU driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c
index cfae0e4476e7..1eb4f98076f1 100644
--- a/drivers/iio/imu/adis16480.c
+++ b/drivers/iio/imu/adis16480.c
@@ -284,22 +284,18 @@ DEFINE_DEBUGFS_ATTRIBUTE(adis16480_flash_count_fops,
static int adis16480_debugfs_init(struct iio_dev *indio_dev)
{
struct adis16480 *adis16480 = iio_priv(indio_dev);
+ struct dentry *d = iio_get_debugfs_dentry(indio_dev);
debugfs_create_file_unsafe("firmware_revision", 0400,
- indio_dev->debugfs_dentry, adis16480,
- &adis16480_firmware_revision_fops);
+ d, adis16480, &adis16480_firmware_revision_fops);
debugfs_create_file_unsafe("firmware_date", 0400,
- indio_dev->debugfs_dentry, adis16480,
- &adis16480_firmware_date_fops);
+ d, adis16480, &adis16480_firmware_date_fops);
debugfs_create_file_unsafe("serial_number", 0400,
- indio_dev->debugfs_dentry, adis16480,
- &adis16480_serial_number_fops);
+ d, adis16480, &adis16480_serial_number_fops);
debugfs_create_file_unsafe("product_id", 0400,
- indio_dev->debugfs_dentry, adis16480,
- &adis16480_product_id_fops);
+ d, adis16480, &adis16480_product_id_fops);
debugfs_create_file_unsafe("flash_count", 0400,
- indio_dev->debugfs_dentry, adis16480,
- &adis16480_flash_count_fops);
+ d, adis16480, &adis16480_flash_count_fops);
return 0;
}
@@ -1106,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,
@@ -1233,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;
diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c
index 04e5e2a0fd6b..5b4225ee09b9 100644
--- a/drivers/iio/imu/adis_buffer.c
+++ b/drivers/iio/imu/adis_buffer.c
@@ -23,25 +23,30 @@ static int adis_update_scan_mode_burst(struct iio_dev *indio_dev,
const unsigned long *scan_mask)
{
struct adis *adis = iio_device_get_drvdata(indio_dev);
- unsigned int burst_length;
+ unsigned int burst_length, burst_max_length;
u8 *tx;
/* All but the timestamp channel */
burst_length = (indio_dev->num_channels - 1) * sizeof(u16);
- burst_length += adis->burst->extra_len;
+ burst_length += adis->burst->extra_len + adis->burst_extra_len;
+
+ if (adis->burst->burst_max_len)
+ burst_max_length = adis->burst->burst_max_len;
+ else
+ burst_max_length = burst_length;
adis->xfer = kcalloc(2, sizeof(*adis->xfer), GFP_KERNEL);
if (!adis->xfer)
return -ENOMEM;
- adis->buffer = kzalloc(burst_length + sizeof(u16), GFP_KERNEL);
+ adis->buffer = kzalloc(burst_max_length + sizeof(u16), GFP_KERNEL);
if (!adis->buffer) {
kfree(adis->xfer);
adis->xfer = NULL;
return -ENOMEM;
}
- tx = adis->buffer + burst_length;
+ tx = adis->buffer + burst_max_length;
tx[0] = ADIS_READ_REG(adis->burst->reg_cmd);
tx[1] = 0;
@@ -156,6 +161,14 @@ static irqreturn_t adis_trigger_handler(int irq, void *p)
return IRQ_HANDLED;
}
+static void adis_buffer_cleanup(void *arg)
+{
+ struct adis *adis = arg;
+
+ kfree(adis->buffer);
+ kfree(adis->xfer);
+}
+
/**
* adis_setup_buffer_and_trigger() - Sets up buffer and trigger for the adis device
* @adis: The adis device.
@@ -199,6 +212,43 @@ error_buffer_cleanup:
EXPORT_SYMBOL_GPL(adis_setup_buffer_and_trigger);
/**
+ * devm_adis_setup_buffer_and_trigger() - Sets up buffer and trigger for
+ * the managed adis device
+ * @adis: The adis device
+ * @indio_dev: The IIO device
+ * @trigger_handler: Optional trigger handler, may be NULL.
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ *
+ * This function perfoms exactly the same as adis_setup_buffer_and_trigger()
+ */
+int
+devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev,
+ irq_handler_t trigger_handler)
+{
+ int ret;
+
+ if (!trigger_handler)
+ trigger_handler = adis_trigger_handler;
+
+ ret = devm_iio_triggered_buffer_setup(&adis->spi->dev, indio_dev,
+ &iio_pollfunc_store_time,
+ trigger_handler, NULL);
+ if (ret)
+ return ret;
+
+ if (adis->spi->irq) {
+ ret = devm_adis_probe_trigger(adis, indio_dev);
+ if (ret)
+ return ret;
+ }
+
+ return devm_add_action_or_reset(&adis->spi->dev, adis_buffer_cleanup,
+ adis);
+}
+EXPORT_SYMBOL_GPL(devm_adis_setup_buffer_and_trigger);
+
+/**
* adis_cleanup_buffer_and_trigger() - Free buffer and trigger resources
* @adis: The adis device.
* @indio_dev: The IIO device.
diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c
index 8b9cd02c0f9f..8afe71947c00 100644
--- a/drivers/iio/imu/adis_trigger.c
+++ b/drivers/iio/imu/adis_trigger.c
@@ -27,6 +27,34 @@ static const struct iio_trigger_ops adis_trigger_ops = {
.set_trigger_state = &adis_data_rdy_trigger_set_state,
};
+static void adis_trigger_setup(struct adis *adis)
+{
+ adis->trig->dev.parent = &adis->spi->dev;
+ adis->trig->ops = &adis_trigger_ops;
+ iio_trigger_set_drvdata(adis->trig, adis);
+}
+
+static int adis_validate_irq_flag(struct adis *adis)
+{
+ /*
+ * Typically this devices have data ready either on the rising edge or
+ * on the falling edge of the data ready pin. This checks enforces that
+ * one of those is set in the drivers... It defaults to
+ * IRQF_TRIGGER_RISING for backward compatibility wiht devices that
+ * don't support changing the pin polarity.
+ */
+ if (!adis->irq_flag) {
+ adis->irq_flag = IRQF_TRIGGER_RISING;
+ return 0;
+ } else if (adis->irq_flag != IRQF_TRIGGER_RISING &&
+ adis->irq_flag != IRQF_TRIGGER_FALLING) {
+ dev_err(&adis->spi->dev, "Invalid IRQ mask: %08lx\n",
+ adis->irq_flag);
+ return -EINVAL;
+ }
+
+ return 0;
+}
/**
* adis_probe_trigger() - Sets up trigger for a adis device
* @adis: The adis device
@@ -45,13 +73,15 @@ int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev)
if (adis->trig == NULL)
return -ENOMEM;
- adis->trig->dev.parent = &adis->spi->dev;
- adis->trig->ops = &adis_trigger_ops;
- iio_trigger_set_drvdata(adis->trig, adis);
+ adis_trigger_setup(adis);
+
+ ret = adis_validate_irq_flag(adis);
+ if (ret)
+ return ret;
ret = request_irq(adis->spi->irq,
&iio_trigger_generic_data_rdy_poll,
- IRQF_TRIGGER_RISING,
+ adis->irq_flag,
indio_dev->name,
adis->trig);
if (ret)
@@ -74,6 +104,40 @@ error_free_trig:
EXPORT_SYMBOL_GPL(adis_probe_trigger);
/**
+ * devm_adis_probe_trigger() - Sets up trigger for a managed adis device
+ * @adis: The adis device
+ * @indio_dev: The IIO device
+ *
+ * Returns 0 on success or a negative error code
+ */
+int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev)
+{
+ int ret;
+
+ adis->trig = devm_iio_trigger_alloc(&adis->spi->dev, "%s-dev%d",
+ indio_dev->name, indio_dev->id);
+ if (!adis->trig)
+ return -ENOMEM;
+
+ adis_trigger_setup(adis);
+
+ ret = adis_validate_irq_flag(adis);
+ if (ret)
+ return ret;
+
+ ret = devm_request_irq(&adis->spi->dev, adis->spi->irq,
+ &iio_trigger_generic_data_rdy_poll,
+ adis->irq_flag,
+ indio_dev->name,
+ adis->trig);
+ if (ret)
+ return ret;
+
+ return devm_iio_trigger_register(&adis->spi->dev, adis->trig);
+}
+EXPORT_SYMBOL_GPL(devm_adis_probe_trigger);
+
+/**
* adis_remove_trigger() - Remove trigger for a adis devices
* @adis: The adis device
*
diff --git a/drivers/iio/imu/bmi160/bmi160.h b/drivers/iio/imu/bmi160/bmi160.h
index 621f5309d735..a82e040bd109 100644
--- a/drivers/iio/imu/bmi160/bmi160.h
+++ b/drivers/iio/imu/bmi160/bmi160.h
@@ -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;
diff --git a/drivers/iio/imu/bmi160/bmi160_core.c b/drivers/iio/imu/bmi160/bmi160_core.c
index 6af65d6f1d28..222ebb26f013 100644
--- a/drivers/iio/imu/bmi160/bmi160_core.c
+++ b/drivers/iio/imu/bmi160/bmi160_core.c
@@ -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>
@@ -109,6 +110,7 @@
.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");
diff --git a/drivers/iio/imu/bmi160/bmi160_i2c.c b/drivers/iio/imu/bmi160/bmi160_i2c.c
index e36f5e82d400..26398614eddf 100644
--- a/drivers/iio/imu/bmi160/bmi160_i2c.c
+++ b/drivers/iio/imu/bmi160/bmi160_i2c.c
@@ -24,8 +24,8 @@ static int bmi160_i2c_probe(struct i2c_client *client,
regmap = devm_regmap_init_i2c(client, &bmi160_regmap_config);
if (IS_ERR(regmap)) {
- dev_err(&client->dev, "Failed to register i2c regmap %d\n",
- (int)PTR_ERR(regmap));
+ dev_err(&client->dev, "Failed to register i2c regmap: %pe\n",
+ regmap);
return PTR_ERR(regmap);
}
diff --git a/drivers/iio/imu/bmi160/bmi160_spi.c b/drivers/iio/imu/bmi160/bmi160_spi.c
index c19e3df35559..61389b41c6d9 100644
--- a/drivers/iio/imu/bmi160/bmi160_spi.c
+++ b/drivers/iio/imu/bmi160/bmi160_spi.c
@@ -20,8 +20,8 @@ static int bmi160_spi_probe(struct spi_device *spi)
regmap = devm_regmap_init_spi(spi, &bmi160_regmap_config);
if (IS_ERR(regmap)) {
- dev_err(&spi->dev, "Failed to register spi regmap %d\n",
- (int)PTR_ERR(regmap));
+ dev_err(&spi->dev, "Failed to register spi regmap: %pe\n",
+ regmap);
return PTR_ERR(regmap);
}
return bmi160_core_probe(&spi->dev, regmap, id->name, true);
diff --git a/drivers/iio/imu/fxos8700_core.c b/drivers/iio/imu/fxos8700_core.c
index 7b47be44ea59..ab288186f36e 100644
--- a/drivers/iio/imu/fxos8700_core.c
+++ b/drivers/iio/imu/fxos8700_core.c
@@ -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
index 000000000000..50cbcfcb6cf1
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/Kconfig
@@ -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
index 000000000000..291714d9aa54
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/Makefile
@@ -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
index 000000000000..c0f5059b13b3
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -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
index 000000000000..3441b0d61c5d
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -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
index 000000000000..99576b2c171f
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c
@@ -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
index 000000000000..de2a3949dcc7
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h
@@ -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
index 000000000000..8bd77185ccb7
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
@@ -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
index 000000000000..aee7b9ff4bf4
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
@@ -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
index 000000000000..85b1934cec60
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
@@ -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
index 000000000000..323789697a08
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
@@ -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
index 000000000000..213cce1c3111
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
@@ -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
index 000000000000..3941186512fb
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h
@@ -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
index 000000000000..7f2dc41f807b
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c
@@ -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
index 000000000000..4e4f331d4fe4
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h
@@ -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
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
index 2f8560ba4572..f8f0cf716bc6 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
@@ -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)
@@ -135,6 +131,7 @@ int inv_mpu_acpi_create_mux_client(struct i2c_client *client)
st->mux_client = NULL;
if (ACPI_HANDLE(&client->dev)) {
struct i2c_board_info info;
+ struct i2c_client *mux_client;
struct acpi_device *adev;
int ret = -1;
@@ -172,9 +169,10 @@ int inv_mpu_acpi_create_mux_client(struct i2c_client *client)
} else
return 0; /* no secondary addr, which is OK */
}
- st->mux_client = i2c_new_device(st->muxc->adapter[0], &info);
- if (!st->mux_client)
- return -ENODEV;
+ mux_client = i2c_new_client_device(st->muxc->adapter[0], &info);
+ if (IS_ERR(mux_client))
+ return PTR_ERR(mux_client);
+ st->mux_client = mux_client;
}
return 0;
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 0b8d2f7a0165..3fee3947f772 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -433,7 +433,7 @@ static int inv_mpu6050_set_gyro_fsr(struct inv_mpu6050_state *st,
return regmap_write(st->map, st->reg->gyro_config, data);
}
-/**
+/*
* inv_mpu6050_set_lpf_regs() - set low pass filter registers, chip dependent
*
* MPU60xx/MPU9150 use only 1 register for accelerometer + gyroscope
@@ -467,7 +467,7 @@ static int inv_mpu6050_set_lpf_regs(struct inv_mpu6050_state *st,
return regmap_write(st->map, st->reg->accel_lpf, val);
}
-/**
+/*
* inv_mpu6050_init_config() - Initialize hardware, disable FIFO.
*
* Initial configuration:
@@ -526,7 +526,7 @@ static int inv_mpu6050_sensor_set(struct inv_mpu6050_state *st, int reg,
__be16 d = cpu_to_be16(val);
ind = (axis - IIO_MOD_X) * 2;
- result = regmap_bulk_write(st->map, reg + ind, (u8 *)&d, 2);
+ result = regmap_bulk_write(st->map, reg + ind, &d, sizeof(d));
if (result)
return -EINVAL;
@@ -540,7 +540,7 @@ static int inv_mpu6050_sensor_show(struct inv_mpu6050_state *st, int reg,
__be16 d;
ind = (axis - IIO_MOD_X) * 2;
- result = regmap_bulk_read(st->map, reg + ind, (u8 *)&d, 2);
+ result = regmap_bulk_read(st->map, reg + ind, &d, sizeof(d));
if (result)
return -EINVAL;
*val = (short)be16_to_cpup(&d);
@@ -847,7 +847,7 @@ error_write_raw_unlock:
return result;
}
-/**
+/*
* inv_mpu6050_set_lpf() - set low pass filer based on fifo rate.
*
* Based on the Nyquist principle, the bandwidth of the low
@@ -884,7 +884,7 @@ static int inv_mpu6050_set_lpf(struct inv_mpu6050_state *st, int rate)
return 0;
}
-/**
+/*
* inv_mpu6050_fifo_rate_store() - Set fifo rate.
*/
static ssize_t
@@ -945,7 +945,7 @@ fifo_rate_fail_unlock:
return count;
}
-/**
+/*
* inv_fifo_rate_show() - Get the current sampling rate.
*/
static ssize_t
@@ -962,7 +962,7 @@ inv_fifo_rate_show(struct device *dev, struct device_attribute *attr,
return scnprintf(buf, PAGE_SIZE, "%u\n", fifo_rate);
}
-/**
+/*
* inv_attr_show() - calling this function will show current
* parameters.
*
@@ -1248,15 +1248,34 @@ static const struct attribute_group inv_attribute_group = {
.attrs = inv_attributes
};
+static int inv_mpu6050_reg_access(struct iio_dev *indio_dev,
+ unsigned int reg,
+ unsigned int writeval,
+ unsigned int *readval)
+{
+ struct inv_mpu6050_state *st = iio_priv(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 const struct iio_info mpu_info = {
.read_raw = &inv_mpu6050_read_raw,
.write_raw = &inv_mpu6050_write_raw,
.write_raw_get_fmt = &inv_write_raw_get_fmt,
.attrs = &inv_attribute_group,
.validate_trigger = inv_mpu6050_validate_trigger,
+ .debugfs_reg_access = &inv_mpu6050_reg_access,
};
-/**
+/*
* inv_check_and_setup_chip() - check and setup chip.
*/
static int inv_check_and_setup_chip(struct inv_mpu6050_state *st)
@@ -1511,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;
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
index 6993d3b87bb0..28cfae1e61cf 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
@@ -122,8 +122,8 @@ static int inv_mpu_probe(struct i2c_client *client,
regmap = devm_regmap_init_i2c(client, &inv_mpu_regmap_config);
if (IS_ERR(regmap)) {
- dev_err(&client->dev, "Failed to register i2c regmap %d\n",
- (int)PTR_ERR(regmap));
+ dev_err(&client->dev, "Failed to register i2c regmap: %pe\n",
+ regmap);
return PTR_ERR(regmap);
}
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
index 9511e4715e2c..b533fa2dad0a 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
@@ -111,7 +111,7 @@ reset_fifo_fail:
return result;
}
-/**
+/*
* inv_mpu6050_read_fifo() - Transfer data from hardware FIFO to KFIFO.
*/
irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
index 673b198e6368..6f968ce687e1 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
@@ -53,8 +53,8 @@ static int inv_mpu_probe(struct spi_device *spi)
regmap = devm_regmap_init_spi(spi, &inv_mpu_regmap_config);
if (IS_ERR(regmap)) {
- dev_err(&spi->dev, "Failed to register spi regmap %d\n",
- (int)PTR_ERR(regmap));
+ dev_err(&spi->dev, "Failed to register spi regmap: %pe\n",
+ regmap);
return PTR_ERR(regmap);
}
diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c
index e67466100aff..61885e99d3fc 100644
--- a/drivers/iio/imu/kmx61.c
+++ b/drivers/iio/imu/kmx61.c
@@ -312,10 +312,10 @@ static int kmx61_convert_wake_up_odr_to_bit(int val, int val2)
/**
* kmx61_set_mode() - set KMX61 device operating mode
- * @data - kmx61 device private data pointer
- * @mode - bitmask, indicating operating mode for @device
- * @device - bitmask, indicating device for which @mode needs to be set
- * @update - update stby bits stored in device's private @data
+ * @data: kmx61 device private data pointer
+ * @mode: bitmask, indicating operating mode for @device
+ * @device: bitmask, indicating device for which @mode needs to be set
+ * @update: update stby bits stored in device's private @data
*
* For each sensor (accelerometer/magnetometer) there are two operating modes
* STANDBY and OPERATION. Neither accel nor magn can be disabled independently
@@ -718,9 +718,9 @@ static int kmx61_setup_any_motion_interrupt(struct kmx61_data *data,
/**
* kmx61_set_power_state() - set power state for kmx61 @device
- * @data - kmx61 device private pointer
- * @on - power state to be set for @device
- * @device - bitmask indicating device for which @on state needs to be set
+ * @data: kmx61 device private pointer
+ * @on: power state to be set for @device
+ * @device: bitmask indicating device for which @on state needs to be set
*
* Notice that when ACC power state needs to be set to ON and MAG is in
* OPERATION then we know that kmx61_runtime_resume was already called
@@ -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;
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
index 41cb20cb3809..d80ba2e688ed 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
@@ -111,7 +111,7 @@ struct st_lsm6dsx_odr {
u8 val;
};
-#define ST_LSM6DSX_ODR_LIST_SIZE 6
+#define ST_LSM6DSX_ODR_LIST_SIZE 8
struct st_lsm6dsx_odr_table_entry {
struct st_lsm6dsx_reg reg;
@@ -436,8 +436,7 @@ int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor,
u16 watermark);
int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable);
int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw);
-int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw,
- enum st_lsm6dsx_fifo_mode fifo_mode);
+int st_lsm6dsx_resume_fifo(struct st_lsm6dsx_hw *hw);
int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw);
int st_lsm6dsx_read_tagged_fifo(struct st_lsm6dsx_hw *hw);
int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u32 odr, u8 *val);
@@ -484,7 +483,7 @@ st_lsm6dsx_write_locked(struct st_lsm6dsx_hw *hw, unsigned int addr,
return err;
}
-static const inline struct iio_mount_matrix *
+static inline const struct iio_mount_matrix *
st_lsm6dsx_get_mount_matrix(const struct iio_dev *iio_dev,
const struct iio_chan_spec *chan)
{
@@ -494,7 +493,8 @@ st_lsm6dsx_get_mount_matrix(const struct iio_dev *iio_dev,
return &hw->orientation;
}
-static const struct iio_chan_spec_ext_info st_lsm6dsx_accel_ext_info[] = {
+static const
+struct iio_chan_spec_ext_info __maybe_unused st_lsm6dsx_accel_ext_info[] = {
IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, st_lsm6dsx_get_mount_matrix),
{ }
};
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
index afd00daeefb2..7de10bd636ea 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
@@ -184,8 +184,8 @@ static int st_lsm6dsx_update_decimators(struct st_lsm6dsx_hw *hw)
return err;
}
-int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw,
- enum st_lsm6dsx_fifo_mode fifo_mode)
+static int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw,
+ enum st_lsm6dsx_fifo_mode fifo_mode)
{
unsigned int data;
@@ -302,6 +302,18 @@ static int st_lsm6dsx_reset_hw_ts(struct st_lsm6dsx_hw *hw)
return 0;
}
+int st_lsm6dsx_resume_fifo(struct st_lsm6dsx_hw *hw)
+{
+ int err;
+
+ /* reset hw ts counter */
+ err = st_lsm6dsx_reset_hw_ts(hw);
+ if (err < 0)
+ return err;
+
+ return st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_CONT);
+}
+
/*
* Set max bulk read to ST_LSM6DSX_MAX_WORD_LEN/ST_LSM6DSX_MAX_TAGGED_WORD_LEN
* in order to avoid a kmalloc for each bus access
@@ -675,12 +687,7 @@ int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable)
goto out;
if (fifo_mask) {
- /* reset hw ts counter */
- err = st_lsm6dsx_reset_hw_ts(hw);
- if (err < 0)
- goto out;
-
- err = st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_CONT);
+ err = st_lsm6dsx_resume_fifo(hw);
if (err < 0)
goto out;
}
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
index 4426524b59f2..346c24281d26 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
@@ -27,7 +27,8 @@
* - FIFO size: 4KB
*
* - LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR/ISM330DHCX:
- * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416
+ * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416,
+ * 833
* - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16
* - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000
* - FIFO size: 3KB
@@ -791,7 +792,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.odr_avl[3] = { 104000, 0x04 },
.odr_avl[4] = { 208000, 0x05 },
.odr_avl[5] = { 416000, 0x06 },
- .odr_len = 6,
+ .odr_avl[6] = { 833000, 0x07 },
+ .odr_len = 7,
},
[ST_LSM6DSX_ID_GYRO] = {
.reg = {
@@ -804,7 +806,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.odr_avl[3] = { 104000, 0x04 },
.odr_avl[4] = { 208000, 0x05 },
.odr_avl[5] = { 416000, 0x06 },
- .odr_len = 6,
+ .odr_avl[6] = { 833000, 0x07 },
+ .odr_len = 7,
},
},
.fs_table = {
@@ -994,7 +997,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.odr_avl[3] = { 104000, 0x04 },
.odr_avl[4] = { 208000, 0x05 },
.odr_avl[5] = { 416000, 0x06 },
- .odr_len = 6,
+ .odr_avl[6] = { 833000, 0x07 },
+ .odr_len = 7,
},
[ST_LSM6DSX_ID_GYRO] = {
.reg = {
@@ -1007,7 +1011,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.odr_avl[3] = { 104000, 0x04 },
.odr_avl[4] = { 208000, 0x05 },
.odr_avl[5] = { 416000, 0x06 },
- .odr_len = 6,
+ .odr_avl[6] = { 833000, 0x07 },
+ .odr_len = 7,
},
},
.fs_table = {
@@ -1171,7 +1176,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.odr_avl[3] = { 104000, 0x04 },
.odr_avl[4] = { 208000, 0x05 },
.odr_avl[5] = { 416000, 0x06 },
- .odr_len = 6,
+ .odr_avl[6] = { 833000, 0x07 },
+ .odr_len = 7,
},
[ST_LSM6DSX_ID_GYRO] = {
.reg = {
@@ -1184,7 +1190,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.odr_avl[3] = { 104000, 0x04 },
.odr_avl[4] = { 208000, 0x05 },
.odr_avl[5] = { 416000, 0x06 },
- .odr_len = 6,
+ .odr_avl[6] = { 833000, 0x07 },
+ .odr_len = 7,
},
},
.fs_table = {
@@ -2145,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;
@@ -2451,7 +2457,7 @@ static int __maybe_unused st_lsm6dsx_resume(struct device *dev)
}
if (hw->fifo_mask)
- err = st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_CONT);
+ err = st_lsm6dsx_resume_fifo(hw);
return err;
}
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c
index 1cf98195f84d..ed83471dc7dd 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c
@@ -88,6 +88,69 @@ static const struct st_lsm6dsx_ext_dev_settings st_lsm6dsx_ext_dev_table[] = {
.len = 6,
},
},
+ /* LIS3MDL */
+ {
+ .i2c_addr = { 0x1e },
+ .wai = {
+ .addr = 0x0f,
+ .val = 0x3d,
+ },
+ .id = ST_LSM6DSX_ID_MAGN,
+ .odr_table = {
+ .reg = {
+ .addr = 0x20,
+ .mask = GENMASK(4, 2),
+ },
+ .odr_avl[0] = { 1000, 0x0 },
+ .odr_avl[1] = { 2000, 0x1 },
+ .odr_avl[2] = { 3000, 0x2 },
+ .odr_avl[3] = { 5000, 0x3 },
+ .odr_avl[4] = { 10000, 0x4 },
+ .odr_avl[5] = { 20000, 0x5 },
+ .odr_avl[6] = { 40000, 0x6 },
+ .odr_avl[7] = { 80000, 0x7 },
+ .odr_len = 8,
+ },
+ .fs_table = {
+ .reg = {
+ .addr = 0x21,
+ .mask = GENMASK(6, 5),
+ },
+ .fs_avl[0] = {
+ .gain = 146,
+ .val = 0x00,
+ }, /* 4000 uG/LSB */
+ .fs_avl[1] = {
+ .gain = 292,
+ .val = 0x01,
+ }, /* 8000 uG/LSB */
+ .fs_avl[2] = {
+ .gain = 438,
+ .val = 0x02,
+ }, /* 12000 uG/LSB */
+ .fs_avl[3] = {
+ .gain = 584,
+ .val = 0x03,
+ }, /* 16000 uG/LSB */
+ .fs_len = 4,
+ },
+ .pwr_table = {
+ .reg = {
+ .addr = 0x22,
+ .mask = GENMASK(1, 0),
+ },
+ .off_val = 0x2,
+ .on_val = 0x0,
+ },
+ .bdu = {
+ .addr = 0x24,
+ .mask = BIT(6),
+ },
+ .out = {
+ .addr = 0x28,
+ .len = 6,
+ },
+ },
};
static void st_lsm6dsx_shub_wait_complete(struct st_lsm6dsx_hw *hw)
@@ -100,7 +163,7 @@ static void st_lsm6dsx_shub_wait_complete(struct st_lsm6dsx_hw *hw)
msleep((2000000U / odr) + 1);
}
-/**
+/*
* st_lsm6dsx_shub_read_output - read i2c controller register
*
* Read st_lsm6dsx i2c controller register
@@ -132,7 +195,7 @@ out:
return err;
}
-/**
+/*
* st_lsm6dsx_shub_write_reg - write i2c controller register
*
* Write st_lsm6dsx i2c controller register
@@ -210,7 +273,7 @@ out:
return err;
}
-/**
+/*
* st_lsm6dsx_shub_read - read data from slave device register
*
* Read data from slave device register. SLV0 is used for
@@ -260,7 +323,7 @@ st_lsm6dsx_shub_read(struct st_lsm6dsx_sensor *sensor, u8 addr,
sizeof(config));
}
-/**
+/*
* st_lsm6dsx_shub_write - write data to slave device register
*
* Write data from slave device register. SLV0 is used for
@@ -519,6 +582,36 @@ st_lsm6dsx_shub_read_raw(struct iio_dev *iio_dev,
}
static int
+st_lsm6dsx_shub_set_full_scale(struct st_lsm6dsx_sensor *sensor,
+ u32 gain)
+{
+ const struct st_lsm6dsx_fs_table_entry *fs_table;
+ int i, err;
+
+ fs_table = &sensor->ext_info.settings->fs_table;
+ if (!fs_table->reg.addr)
+ return -ENOTSUPP;
+
+ for (i = 0; i < fs_table->fs_len; i++) {
+ if (fs_table->fs_avl[i].gain == gain)
+ break;
+ }
+
+ if (i == fs_table->fs_len)
+ return -EINVAL;
+
+ err = st_lsm6dsx_shub_write_with_mask(sensor, fs_table->reg.addr,
+ fs_table->reg.mask,
+ fs_table->fs_avl[i].val);
+ if (err < 0)
+ return err;
+
+ sensor->gain = gain;
+
+ return 0;
+}
+
+static int
st_lsm6dsx_shub_write_raw(struct iio_dev *iio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
@@ -554,6 +647,9 @@ st_lsm6dsx_shub_write_raw(struct iio_dev *iio_dev,
}
break;
}
+ case IIO_CHAN_INFO_SCALE:
+ err = st_lsm6dsx_shub_set_full_scale(sensor, val2);
+ break;
default:
err = -EINVAL;
break;
@@ -639,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);
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 4ada5592aa2b..a7d7e5143ed2 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -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>
@@ -189,10 +191,12 @@ __poll_t iio_buffer_poll(struct file *filp,
*/
void iio_buffer_wakeup_poll(struct iio_dev *indio_dev)
{
- if (!indio_dev->buffer)
+ struct iio_buffer *buffer = indio_dev->buffer;
+
+ if (!buffer)
return;
- wake_up(&indio_dev->buffer->pollq);
+ wake_up(&buffer->pollq);
}
void iio_buffer_init(struct iio_buffer *buffer)
@@ -262,10 +266,11 @@ static ssize_t iio_scan_el_show(struct device *dev,
{
int ret;
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct iio_buffer *buffer = indio_dev->buffer;
/* Ensure ret is 0 or 1. */
ret = !!test_bit(to_iio_dev_attr(attr)->address,
- indio_dev->buffer->scan_mask);
+ buffer->scan_mask);
return sprintf(buf, "%d\n", ret);
}
@@ -316,8 +321,7 @@ static int iio_scan_mask_set(struct iio_dev *indio_dev,
const unsigned long *mask;
unsigned long *trialmask;
- trialmask = kcalloc(BITS_TO_LONGS(indio_dev->masklength),
- sizeof(*trialmask), GFP_KERNEL);
+ trialmask = bitmap_zalloc(indio_dev->masklength, GFP_KERNEL);
if (trialmask == NULL)
return -ENOMEM;
if (!indio_dev->masklength) {
@@ -382,7 +386,7 @@ static ssize_t iio_scan_el_store(struct device *dev,
if (ret < 0)
return ret;
mutex_lock(&indio_dev->mlock);
- if (iio_buffer_is_active(indio_dev->buffer)) {
+ if (iio_buffer_is_active(buffer)) {
ret = -EBUSY;
goto error_ret;
}
@@ -411,7 +415,9 @@ static ssize_t iio_scan_el_ts_show(struct device *dev,
char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- return sprintf(buf, "%d\n", indio_dev->buffer->scan_timestamp);
+ struct iio_buffer *buffer = indio_dev->buffer;
+
+ return sprintf(buf, "%d\n", buffer->scan_timestamp);
}
static ssize_t iio_scan_el_ts_store(struct device *dev,
@@ -421,6 +427,7 @@ static ssize_t iio_scan_el_ts_store(struct device *dev,
{
int ret;
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct iio_buffer *buffer = indio_dev->buffer;
bool state;
ret = strtobool(buf, &state);
@@ -428,11 +435,11 @@ static ssize_t iio_scan_el_ts_store(struct device *dev,
return ret;
mutex_lock(&indio_dev->mlock);
- if (iio_buffer_is_active(indio_dev->buffer)) {
+ if (iio_buffer_is_active(buffer)) {
ret = -EBUSY;
goto error_ret;
}
- indio_dev->buffer->scan_timestamp = state;
+ buffer->scan_timestamp = state;
error_ret:
mutex_unlock(&indio_dev->mlock);
@@ -440,10 +447,10 @@ error_ret:
}
static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev,
+ struct iio_buffer *buffer,
const struct iio_chan_spec *chan)
{
int ret, attrcount = 0;
- struct iio_buffer *buffer = indio_dev->buffer;
ret = __iio_add_chan_devattr("index",
chan,
@@ -519,7 +526,7 @@ static ssize_t iio_buffer_write_length(struct device *dev,
return len;
mutex_lock(&indio_dev->mlock);
- if (iio_buffer_is_active(indio_dev->buffer)) {
+ if (iio_buffer_is_active(buffer)) {
ret = -EBUSY;
} else {
buffer->access->set_length(buffer, val);
@@ -540,7 +547,9 @@ static ssize_t iio_buffer_show_enable(struct device *dev,
char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- return sprintf(buf, "%d\n", iio_buffer_is_active(indio_dev->buffer));
+ struct iio_buffer *buffer = indio_dev->buffer;
+
+ return sprintf(buf, "%d\n", iio_buffer_is_active(buffer));
}
static unsigned int iio_storage_bytes_for_si(struct iio_dev *indio_dev,
@@ -591,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)
@@ -604,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);
}
@@ -680,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;
@@ -687,6 +700,13 @@ static int iio_verify_update(struct iio_dev *indio_dev,
bool scan_timestamp;
unsigned int modes;
+ if (insert_buffer &&
+ bitmap_empty(insert_buffer->scan_mask, indio_dev->masklength)) {
+ dev_dbg(&indio_dev->dev,
+ "At least one scan element must be enabled first\n");
+ return -EINVAL;
+ }
+
memset(config, 0, sizeof(*config));
config->watermark = ~0;
@@ -695,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;
@@ -721,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;
@@ -741,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,
@@ -887,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;
@@ -898,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;
@@ -907,12 +928,14 @@ 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;
indio_dev->active_scan_mask = config->scan_mask;
indio_dev->scan_timestamp = config->scan_timestamp;
indio_dev->scan_bytes = config->scan_bytes;
+ indio_dev->currentmode = config->mode;
iio_update_demux(indio_dev);
@@ -942,34 +965,44 @@ 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;
}
- indio_dev->currentmode = config->mode;
+ 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:
- indio_dev->currentmode = INDIO_DIRECT_MODE;
if (indio_dev->setup_ops->postdisable)
indio_dev->setup_ops->postdisable(indio_dev);
err_undo_config:
+ indio_dev->currentmode = INDIO_DIRECT_MODE;
indio_dev->active_scan_mask = NULL;
return ret;
@@ -977,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;
/*
@@ -998,14 +1032,17 @@ 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;
}
- indio_dev->currentmode = INDIO_DIRECT_MODE;
-
if (indio_dev->setup_ops->postdisable) {
ret2 = indio_dev->setup_ops->postdisable(indio_dev);
if (ret2 && !ret)
@@ -1014,6 +1051,7 @@ static int iio_disable_buffers(struct iio_dev *indio_dev)
iio_free_scan_mask(indio_dev, indio_dev->active_scan_mask);
indio_dev->active_scan_mask = NULL;
+ indio_dev->currentmode = INDIO_DIRECT_MODE;
return ret;
}
@@ -1022,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;
@@ -1046,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);
@@ -1123,6 +1162,7 @@ static ssize_t iio_buffer_store_enable(struct device *dev,
int ret;
bool requested_state;
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct iio_buffer *buffer = indio_dev->buffer;
bool inlist;
ret = strtobool(buf, &requested_state);
@@ -1132,17 +1172,15 @@ static ssize_t iio_buffer_store_enable(struct device *dev,
mutex_lock(&indio_dev->mlock);
/* Find out if it is in the list */
- inlist = iio_buffer_is_active(indio_dev->buffer);
+ inlist = iio_buffer_is_active(buffer);
/* Already in desired state */
if (inlist == requested_state)
goto done;
if (requested_state)
- ret = __iio_update_buffers(indio_dev,
- indio_dev->buffer, NULL);
+ ret = __iio_update_buffers(indio_dev, buffer, NULL);
else
- ret = __iio_update_buffers(indio_dev,
- NULL, indio_dev->buffer);
+ ret = __iio_update_buffers(indio_dev, NULL, buffer);
done:
mutex_unlock(&indio_dev->mlock);
@@ -1184,7 +1222,7 @@ static ssize_t iio_buffer_store_watermark(struct device *dev,
goto out;
}
- if (iio_buffer_is_active(indio_dev->buffer)) {
+ if (iio_buffer_is_active(buffer)) {
ret = -EBUSY;
goto out;
}
@@ -1201,11 +1239,9 @@ static ssize_t iio_dma_show_data_available(struct device *dev,
char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- size_t bytes;
-
- bytes = iio_buffer_data_available(indio_dev->buffer);
+ struct iio_buffer *buffer = indio_dev->buffer;
- return sprintf(buf, "%zu\n", bytes);
+ return sprintf(buf, "%zu\n", iio_buffer_data_available(buffer));
}
static DEVICE_ATTR(length, S_IRUGO | S_IWUSR, iio_buffer_read_length,
@@ -1233,7 +1269,7 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
struct iio_dev_attr *p;
struct attribute **attr;
struct iio_buffer *buffer = indio_dev->buffer;
- int ret, i, attrn, attrcount, attrcount_orig = 0;
+ int ret, i, attrn, attrcount;
const struct iio_chan_spec *channels;
channels = indio_dev->channels;
@@ -1277,12 +1313,7 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
indio_dev->groups[indio_dev->groupcounter++] = &buffer->buffer_group;
- if (buffer->scan_el_attrs != NULL) {
- attr = buffer->scan_el_attrs->attrs;
- while (*attr++ != NULL)
- attrcount_orig++;
- }
- attrcount = attrcount_orig;
+ attrcount = 0;
INIT_LIST_HEAD(&buffer->scan_el_dev_attr_list);
channels = indio_dev->channels;
if (channels) {
@@ -1291,7 +1322,7 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
if (channels[i].scan_index < 0)
continue;
- ret = iio_buffer_add_channel_sysfs(indio_dev,
+ ret = iio_buffer_add_channel_sysfs(indio_dev, buffer,
&channels[i]);
if (ret < 0)
goto error_cleanup_dynamic;
@@ -1319,10 +1350,7 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
ret = -ENOMEM;
goto error_free_scan_mask;
}
- if (buffer->scan_el_attrs)
- memcpy(buffer->scan_el_group.attrs, buffer->scan_el_attrs,
- sizeof(buffer->scan_el_group.attrs[0])*attrcount_orig);
- attrn = attrcount_orig;
+ attrn = 0;
list_for_each_entry(p, &buffer->scan_el_dev_attr_list, l)
buffer->scan_el_group.attrs[attrn++] = &p->dev_attr.attr;
@@ -1334,20 +1362,22 @@ error_free_scan_mask:
bitmap_free(buffer->scan_mask);
error_cleanup_dynamic:
iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list);
- kfree(indio_dev->buffer->buffer_group.attrs);
+ kfree(buffer->buffer_group.attrs);
return ret;
}
void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev)
{
- if (!indio_dev->buffer)
+ struct iio_buffer *buffer = indio_dev->buffer;
+
+ if (!buffer)
return;
- bitmap_free(indio_dev->buffer->scan_mask);
- kfree(indio_dev->buffer->buffer_group.attrs);
- kfree(indio_dev->buffer->scan_el_group.attrs);
- iio_free_chan_devattr_list(&indio_dev->buffer->scan_el_dev_attr_list);
+ bitmap_free(buffer->scan_mask);
+ kfree(buffer->buffer_group.attrs);
+ kfree(buffer->scan_el_group.attrs);
+ iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list);
}
/**
@@ -1404,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;
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 24f7bbff4938..cdcd16f19500 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -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>
@@ -130,6 +131,8 @@ static const char * const iio_modifier_names[] = {
[IIO_MOD_PM2P5] = "pm2p5",
[IIO_MOD_PM4] = "pm4",
[IIO_MOD_PM10] = "pm10",
+ [IIO_MOD_ETHANOL] = "ethanol",
+ [IIO_MOD_H2] = "h2",
};
/* relies on pairs of these shared then separate */
@@ -164,6 +167,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 +213,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 +324,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 +369,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 +396,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
@@ -572,46 +596,46 @@ static ssize_t __iio_format_value(char *buf, size_t len, unsigned int type,
switch (type) {
case IIO_VAL_INT:
- return snprintf(buf, len, "%d", vals[0]);
+ return scnprintf(buf, len, "%d", vals[0]);
case IIO_VAL_INT_PLUS_MICRO_DB:
scale_db = true;
- /* fall through */
+ fallthrough;
case IIO_VAL_INT_PLUS_MICRO:
if (vals[1] < 0)
- return snprintf(buf, len, "-%d.%06u%s", abs(vals[0]),
+ return scnprintf(buf, len, "-%d.%06u%s", abs(vals[0]),
-vals[1], scale_db ? " dB" : "");
else
- return snprintf(buf, len, "%d.%06u%s", vals[0], vals[1],
+ return scnprintf(buf, len, "%d.%06u%s", vals[0], vals[1],
scale_db ? " dB" : "");
case IIO_VAL_INT_PLUS_NANO:
if (vals[1] < 0)
- return snprintf(buf, len, "-%d.%09u", abs(vals[0]),
+ return scnprintf(buf, len, "-%d.%09u", abs(vals[0]),
-vals[1]);
else
- return snprintf(buf, len, "%d.%09u", vals[0], vals[1]);
+ return scnprintf(buf, len, "%d.%09u", vals[0], vals[1]);
case IIO_VAL_FRACTIONAL:
tmp = div_s64((s64)vals[0] * 1000000000LL, vals[1]);
tmp1 = vals[1];
tmp0 = (int)div_s64_rem(tmp, 1000000000, &tmp1);
- return snprintf(buf, len, "%d.%09u", tmp0, abs(tmp1));
+ return scnprintf(buf, len, "%d.%09u", tmp0, abs(tmp1));
case IIO_VAL_FRACTIONAL_LOG2:
tmp = shift_right((s64)vals[0] * 1000000000LL, vals[1]);
tmp0 = (int)div_s64_rem(tmp, 1000000000LL, &tmp1);
- return snprintf(buf, len, "%d.%09u", tmp0, abs(tmp1));
+ return scnprintf(buf, len, "%d.%09u", tmp0, abs(tmp1));
case IIO_VAL_INT_MULTIPLE:
{
int i;
int l = 0;
for (i = 0; i < size; ++i) {
- l += snprintf(&buf[l], len - l, "%d ", vals[i]);
+ l += scnprintf(&buf[l], len - l, "%d ", vals[i]);
if (l >= len)
break;
}
return l;
}
case IIO_VAL_CHAR:
- return snprintf(buf, len, "%c", (char)vals[0]);
+ return scnprintf(buf, len, "%c", (char)vals[0]);
default:
return 0;
}
@@ -682,10 +706,10 @@ static ssize_t iio_format_avail_list(char *buf, const int *vals,
if (len >= PAGE_SIZE)
return -EFBIG;
if (i < length - 1)
- len += snprintf(buf + len, PAGE_SIZE - len,
+ len += scnprintf(buf + len, PAGE_SIZE - len,
" ");
else
- len += snprintf(buf + len, PAGE_SIZE - len,
+ len += scnprintf(buf + len, PAGE_SIZE - len,
"\n");
if (len >= PAGE_SIZE)
return -EFBIG;
@@ -698,10 +722,10 @@ static ssize_t iio_format_avail_list(char *buf, const int *vals,
if (len >= PAGE_SIZE)
return -EFBIG;
if (i < length / 2 - 1)
- len += snprintf(buf + len, PAGE_SIZE - len,
+ len += scnprintf(buf + len, PAGE_SIZE - len,
" ");
else
- len += snprintf(buf + len, PAGE_SIZE - len,
+ len += scnprintf(buf + len, PAGE_SIZE - len,
"\n");
if (len >= PAGE_SIZE)
return -EFBIG;
@@ -725,10 +749,10 @@ static ssize_t iio_format_avail_range(char *buf, const int *vals, int type)
if (len >= PAGE_SIZE)
return -EFBIG;
if (i < 2)
- len += snprintf(buf + len, PAGE_SIZE - len,
+ len += scnprintf(buf + len, PAGE_SIZE - len,
" ");
else
- len += snprintf(buf + len, PAGE_SIZE - len,
+ len += scnprintf(buf + len, PAGE_SIZE - len,
"]\n");
if (len >= PAGE_SIZE)
return -EFBIG;
@@ -741,10 +765,10 @@ static ssize_t iio_format_avail_range(char *buf, const int *vals, int type)
if (len >= PAGE_SIZE)
return -EFBIG;
if (i < 2)
- len += snprintf(buf + len, PAGE_SIZE - len,
+ len += scnprintf(buf + len, PAGE_SIZE - len,
" ");
else
- len += snprintf(buf + len, PAGE_SIZE - len,
+ len += scnprintf(buf + len, PAGE_SIZE - len,
"]\n");
if (len >= PAGE_SIZE)
return -EFBIG;
@@ -894,7 +918,7 @@ static ssize_t iio_write_channel_info(struct device *dev,
break;
case IIO_VAL_INT_PLUS_MICRO_DB:
scale_db = true;
- /* fall through */
+ fallthrough;
case IIO_VAL_INT_PLUS_MICRO:
fract_mult = 100000;
break;
@@ -1116,6 +1140,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 +1153,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 +1169,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 +1189,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 +1204,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 +1280,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 +1415,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 +1445,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 +1455,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 +1513,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,41 +1525,45 @@ 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) {
- dev->dev.groups = dev->groups;
- dev->dev.type = &iio_device_type;
- dev->dev.bus = &iio_bus_type;
- device_initialize(&dev->dev);
- dev_set_drvdata(&dev->dev, (void *)dev);
- mutex_init(&dev->mlock);
- mutex_init(&dev->info_exist_lock);
- INIT_LIST_HEAD(&dev->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);
- return NULL;
- }
- dev_set_name(&dev->dev, "iio:device%d", dev->id);
- INIT_LIST_HEAD(&dev->buffer_list);
+
+ 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.parent = parent;
+ dev->dev.groups = dev->groups;
+ dev->dev.type = &iio_device_type;
+ dev->dev.bus = &iio_bus_type;
+ device_initialize(&dev->dev);
+ dev_set_drvdata(&dev->dev, (void *)dev);
+ mutex_init(&dev->mlock);
+ mutex_init(&dev->info_exist_lock);
+ 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(iio_dev_opaque);
+ return NULL;
}
+ dev_set_name(&dev->dev, "iio:device%d", dev->id);
+ INIT_LIST_HEAD(&iio_dev_opaque->buffer_list);
return dev;
}
@@ -1549,32 +1585,18 @@ static void devm_iio_device_release(struct device *dev, void *res)
iio_device_free(*(struct iio_dev **)res);
}
-int devm_iio_device_match(struct device *dev, void *res, void *data)
-{
- struct iio_dev **r = res;
- if (!r || !*r) {
- WARN_ON(!r || !*r);
- return 0;
- }
- return *r == data;
-}
-EXPORT_SYMBOL_GPL(devm_iio_device_match);
-
/**
* 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
* automatically freed on driver detach.
*
- * If an iio_dev allocated with this function needs to be freed separately,
- * devm_iio_device_free() must be used.
- *
* 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;
@@ -1583,10 +1605,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);
}
@@ -1596,23 +1618,6 @@ struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv)
EXPORT_SYMBOL_GPL(devm_iio_device_alloc);
/**
- * devm_iio_device_free - Resource-managed iio_device_free()
- * @dev: Device this iio_dev belongs to
- * @iio_dev: the iio_dev associated with the device
- *
- * Free iio_dev allocated with devm_iio_device_alloc().
- */
-void devm_iio_device_free(struct device *dev, struct iio_dev *iio_dev)
-{
- int rc;
-
- rc = devres_release(dev, devm_iio_device_release,
- devm_iio_device_match, iio_dev);
- WARN_ON(rc);
-}
-EXPORT_SYMBOL_GPL(devm_iio_device_free);
-
-/**
* iio_chrdev_open() - chrdev file open for buffer access and ioctls
* @inode: Inode structure for identifying the device in the file system
* @filp: File structure for iio device used to keep and later access
@@ -1714,6 +1719,9 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
{
int ret;
+ if (!indio_dev->info)
+ return -EINVAL;
+
indio_dev->driver_module = this_mod;
/* If the calling driver did not initialize of_node, do it here */
if (!indio_dev->dev.of_node && indio_dev->dev.parent)
@@ -1726,9 +1734,6 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
if (ret < 0)
return ret;
- if (!indio_dev->info)
- return -EINVAL;
-
/* configure elements for the chrdev */
indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id);
@@ -1834,23 +1839,6 @@ int __devm_iio_device_register(struct device *dev, struct iio_dev *indio_dev,
EXPORT_SYMBOL_GPL(__devm_iio_device_register);
/**
- * devm_iio_device_unregister - Resource-managed iio_device_unregister()
- * @dev: Device this iio_dev belongs to
- * @indio_dev: the iio_dev associated with the device
- *
- * Unregister iio_dev registered with devm_iio_device_register().
- */
-void devm_iio_device_unregister(struct device *dev, struct iio_dev *indio_dev)
-{
- int rc;
-
- rc = devres_release(dev, devm_iio_device_unreg,
- devm_iio_device_match, indio_dev);
- WARN_ON(rc);
-}
-EXPORT_SYMBOL_GPL(devm_iio_device_unregister);
-
-/**
* iio_device_claim_direct_mode - Keep device in direct mode
* @indio_dev: the iio_dev associated with the device
*
diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c
index 5b17c92d3b50..2ab4d4c44427 100644
--- a/drivers/iio/industrialio-event.c
+++ b/drivers/iio/industrialio-event.c
@@ -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);
}
diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c
index 3908a9a90035..6f16357fd732 100644
--- a/drivers/iio/industrialio-trigger.c
+++ b/drivers/iio/industrialio-trigger.c
@@ -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
@@ -585,18 +585,6 @@ static void devm_iio_trigger_release(struct device *dev, void *res)
iio_trigger_free(*(struct iio_trigger **)res);
}
-static int devm_iio_trigger_match(struct device *dev, void *res, void *data)
-{
- struct iio_trigger **r = res;
-
- if (!r || !*r) {
- WARN_ON(!r || !*r);
- return 0;
- }
-
- return *r == data;
-}
-
/**
* devm_iio_trigger_alloc - Resource-managed iio_trigger_alloc()
* @dev: Device to allocate iio_trigger for
@@ -608,9 +596,6 @@ static int devm_iio_trigger_match(struct device *dev, void *res, void *data)
* Managed iio_trigger_alloc. iio_trigger allocated with this function is
* automatically freed on driver detach.
*
- * If an iio_trigger allocated with this function needs to be freed separately,
- * devm_iio_trigger_free() must be used.
- *
* RETURNS:
* Pointer to allocated iio_trigger on success, NULL on failure.
*/
@@ -640,23 +625,6 @@ struct iio_trigger *devm_iio_trigger_alloc(struct device *dev,
}
EXPORT_SYMBOL_GPL(devm_iio_trigger_alloc);
-/**
- * devm_iio_trigger_free - Resource-managed iio_trigger_free()
- * @dev: Device this iio_dev belongs to
- * @iio_trig: the iio_trigger associated with the device
- *
- * Free iio_trigger allocated with devm_iio_trigger_alloc().
- */
-void devm_iio_trigger_free(struct device *dev, struct iio_trigger *iio_trig)
-{
- int rc;
-
- rc = devres_release(dev, devm_iio_trigger_release,
- devm_iio_trigger_match, iio_trig);
- WARN_ON(rc);
-}
-EXPORT_SYMBOL_GPL(devm_iio_trigger_free);
-
static void devm_iio_trigger_unreg(struct device *dev, void *res)
{
iio_trigger_unregister(*(struct iio_trigger **)res);
@@ -673,9 +641,6 @@ static void devm_iio_trigger_unreg(struct device *dev, void *res)
* calls iio_trigger_register() internally. Refer to that function for more
* information.
*
- * If an iio_trigger registered with this function needs to be unregistered
- * separately, devm_iio_trigger_unregister() must be used.
- *
* RETURNS:
* 0 on success, negative error number on failure.
*/
@@ -701,24 +666,6 @@ int __devm_iio_trigger_register(struct device *dev,
}
EXPORT_SYMBOL_GPL(__devm_iio_trigger_register);
-/**
- * devm_iio_trigger_unregister - Resource-managed iio_trigger_unregister()
- * @dev: device this iio_trigger belongs to
- * @trig_info: the trigger associated with the device
- *
- * Unregister trigger registered with devm_iio_trigger_register().
- */
-void devm_iio_trigger_unregister(struct device *dev,
- struct iio_trigger *trig_info)
-{
- int rc;
-
- rc = devres_release(dev, devm_iio_trigger_unreg, devm_iio_trigger_match,
- trig_info);
- WARN_ON(rc);
-}
-EXPORT_SYMBOL_GPL(devm_iio_trigger_unregister);
-
bool iio_trigger_using_own(struct iio_dev *indio_dev)
{
return indio_dev->trig->attached_own_device;
@@ -758,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);
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index 5a8351c9a426..ede99e0d5371 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -360,18 +360,6 @@ static void devm_iio_channel_free(struct device *dev, void *res)
iio_channel_release(channel);
}
-static int devm_iio_channel_match(struct device *dev, void *res, void *data)
-{
- struct iio_channel **r = res;
-
- if (!r || !*r) {
- WARN_ON(!r || !*r);
- return 0;
- }
-
- return *r == data;
-}
-
struct iio_channel *devm_iio_channel_get(struct device *dev,
const char *channel_name)
{
@@ -394,13 +382,6 @@ struct iio_channel *devm_iio_channel_get(struct device *dev,
}
EXPORT_SYMBOL_GPL(devm_iio_channel_get);
-void devm_iio_channel_release(struct device *dev, struct iio_channel *channel)
-{
- WARN_ON(devres_release(dev, devm_iio_channel_free,
- devm_iio_channel_match, channel));
-}
-EXPORT_SYMBOL_GPL(devm_iio_channel_release);
-
struct iio_channel *iio_channel_get_all(struct device *dev)
{
const char *name;
@@ -514,14 +495,6 @@ struct iio_channel *devm_iio_channel_get_all(struct device *dev)
}
EXPORT_SYMBOL_GPL(devm_iio_channel_get_all);
-void devm_iio_channel_release_all(struct device *dev,
- struct iio_channel *channels)
-{
- WARN_ON(devres_release(dev, devm_iio_channel_free_all,
- devm_iio_channel_match, channels));
-}
-EXPORT_SYMBOL_GPL(devm_iio_channel_release_all);
-
static int iio_channel_read(struct iio_channel *chan, int *val, int *val2,
enum iio_chan_info_enum info)
{
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index b27719cefcf9..182bd18c4bb2 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -516,6 +516,8 @@ config US5182D
config VCNL4000
tristate "VCNL4000/4010/4020/4200 combined ALS and proximity sensor"
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
depends on I2C
help
Say Y here if you want to build a driver for the Vishay VCNL4000,
diff --git a/drivers/iio/light/acpi-als.c b/drivers/iio/light/acpi-als.c
index 1eafd0b24e18..2be7180e2cbf 100644
--- a/drivers/iio/light/acpi-als.c
+++ b/drivers/iio/light/acpi-als.c
@@ -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;
diff --git a/drivers/iio/light/adjd_s311.c b/drivers/iio/light/adjd_s311.c
index d3269cd44fb5..17dac8d0e11d 100644
--- a/drivers/iio/light/adjd_s311.c
+++ b/drivers/iio/light/adjd_s311.c
@@ -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;
diff --git a/drivers/iio/light/adux1020.c b/drivers/iio/light/adux1020.c
index b07797ac10d7..9aa28695e6f1 100644
--- a/drivers/iio/light/adux1020.c
+++ b/drivers/iio/light/adux1020.c
@@ -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;
diff --git a/drivers/iio/light/al3010.c b/drivers/iio/light/al3010.c
index b1ed7658cc46..b4e9924094cd 100644
--- a/drivers/iio/light/al3010.c
+++ b/drivers/iio/light/al3010.c
@@ -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;
diff --git a/drivers/iio/light/al3320a.c b/drivers/iio/light/al3320a.c
index 20ed0a73c390..cc1407ccc10a 100644
--- a/drivers/iio/light/al3320a.c
+++ b/drivers/iio/light/al3320a.c
@@ -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;
diff --git a/drivers/iio/light/apds9300.c b/drivers/iio/light/apds9300.c
index 856b6c468dea..baaf202dce05 100644
--- a/drivers/iio/light/apds9300.c
+++ b/drivers/iio/light/apds9300.c
@@ -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;
diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c
index 52f86bc777dd..9afb3fcc74e6 100644
--- a/drivers/iio/light/apds9960.c
+++ b/drivers/iio/light/apds9960.c
@@ -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;
diff --git a/drivers/iio/light/bh1750.c b/drivers/iio/light/bh1750.c
index adb5ab9e3439..48484b9401b9 100644
--- a/drivers/iio/light/bh1750.c
+++ b/drivers/iio/light/bh1750.c
@@ -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;
diff --git a/drivers/iio/light/bh1780.c b/drivers/iio/light/bh1780.c
index a8361006dcd9..abbf2e662e7d 100644
--- a/drivers/iio/light/bh1780.c
+++ b/drivers/iio/light/bh1780.c
@@ -13,7 +13,7 @@
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/module.h>
-#include <linux/of.h>
+#include <linux/mod_devicetable.h>
#include <linux/pm_runtime.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -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;
@@ -273,13 +272,11 @@ static const struct i2c_device_id bh1780_id[] = {
MODULE_DEVICE_TABLE(i2c, bh1780_id);
-#ifdef CONFIG_OF
static const struct of_device_id of_bh1780_match[] = {
{ .compatible = "rohm,bh1780gli", },
{},
};
MODULE_DEVICE_TABLE(of, of_bh1780_match);
-#endif
static struct i2c_driver bh1780_driver = {
.probe = bh1780_probe,
@@ -288,7 +285,7 @@ static struct i2c_driver bh1780_driver = {
.driver = {
.name = "bh1780",
.pm = &bh1780_dev_pm_ops,
- .of_match_table = of_match_ptr(of_bh1780_match),
+ .of_match_table = of_bh1780_match,
},
};
diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c
index 5f4fb5674fa0..97649944f1df 100644
--- a/drivers/iio/light/cm32181.c
+++ b/drivers/iio/light/cm32181.c
@@ -4,11 +4,13 @@
* Author: Kevin Tsai <ktsai@capellamicro.com>
*/
+#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/module.h>
+#include <linux/mod_devicetable.h>
#include <linux/interrupt.h>
#include <linux/regulator/consumer.h>
#include <linux/iio/iio.h>
@@ -18,17 +20,24 @@
/* Registers Address */
#define CM32181_REG_ADDR_CMD 0x00
+#define CM32181_REG_ADDR_WH 0x01
+#define CM32181_REG_ADDR_WL 0x02
+#define CM32181_REG_ADDR_TEST 0x03
#define CM32181_REG_ADDR_ALS 0x04
#define CM32181_REG_ADDR_STATUS 0x06
#define CM32181_REG_ADDR_ID 0x07
/* Number of Configurable Registers */
-#define CM32181_CONF_REG_NUM 0x01
+#define CM32181_CONF_REG_NUM 4
/* CMD register */
-#define CM32181_CMD_ALS_ENABLE 0x00
-#define CM32181_CMD_ALS_DISABLE 0x01
-#define CM32181_CMD_ALS_INT_EN 0x02
+#define CM32181_CMD_ALS_DISABLE BIT(0)
+#define CM32181_CMD_ALS_INT_EN BIT(1)
+#define CM32181_CMD_ALS_THRES_WINDOW BIT(2)
+
+#define CM32181_CMD_ALS_PERS_SHIFT 4
+#define CM32181_CMD_ALS_PERS_MASK (0x03 << CM32181_CMD_ALS_PERS_SHIFT)
+#define CM32181_CMD_ALS_PERS_DEFAULT (0x01 << CM32181_CMD_ALS_PERS_SHIFT)
#define CM32181_CMD_ALS_IT_SHIFT 6
#define CM32181_CMD_ALS_IT_MASK (0x0F << CM32181_CMD_ALS_IT_SHIFT)
@@ -38,27 +47,133 @@
#define CM32181_CMD_ALS_SM_MASK (0x03 << CM32181_CMD_ALS_SM_SHIFT)
#define CM32181_CMD_ALS_SM_DEFAULT (0x01 << CM32181_CMD_ALS_SM_SHIFT)
-#define CM32181_MLUX_PER_BIT 5 /* ALS_SM=01 IT=800ms */
-#define CM32181_MLUX_PER_BIT_BASE_IT 800000 /* Based on IT=800ms */
-#define CM32181_CALIBSCALE_DEFAULT 1000
-#define CM32181_CALIBSCALE_RESOLUTION 1000
-#define MLUX_PER_LUX 1000
+#define CM32181_LUX_PER_BIT 500 /* ALS_SM=01 IT=800ms */
+#define CM32181_LUX_PER_BIT_RESOLUTION 100000
+#define CM32181_LUX_PER_BIT_BASE_IT 800000 /* Based on IT=800ms */
+#define CM32181_CALIBSCALE_DEFAULT 100000
+#define CM32181_CALIBSCALE_RESOLUTION 100000
-static const u8 cm32181_reg[CM32181_CONF_REG_NUM] = {
- CM32181_REG_ADDR_CMD,
-};
+#define SMBUS_ALERT_RESPONSE_ADDRESS 0x0c
+
+/* CPM0 Index 0: device-id (3218 or 32181), 1: Unknown, 2: init_regs_bitmap */
+#define CPM0_REGS_BITMAP 2
+#define CPM0_HEADER_SIZE 3
-static const int als_it_bits[] = {12, 8, 0, 1, 2, 3};
-static const int als_it_value[] = {25000, 50000, 100000, 200000, 400000,
- 800000};
+/* CPM1 Index 0: lux_per_bit, 1: calibscale, 2: resolution (100000) */
+#define CPM1_LUX_PER_BIT 0
+#define CPM1_CALIBSCALE 1
+#define CPM1_SIZE 3
+
+/* CM3218 Family */
+static const int cm3218_als_it_bits[] = { 0, 1, 2, 3 };
+static const int cm3218_als_it_values[] = { 100000, 200000, 400000, 800000 };
+
+/* CM32181 Family */
+static const int cm32181_als_it_bits[] = { 12, 8, 0, 1, 2, 3 };
+static const int cm32181_als_it_values[] = {
+ 25000, 50000, 100000, 200000, 400000, 800000
+};
struct cm32181_chip {
struct i2c_client *client;
+ struct device *dev;
struct mutex lock;
u16 conf_regs[CM32181_CONF_REG_NUM];
+ unsigned long init_regs_bitmap;
int calibscale;
+ int lux_per_bit;
+ int lux_per_bit_base_it;
+ int num_als_it;
+ const int *als_it_bits;
+ const int *als_it_values;
};
+static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val2);
+
+#ifdef CONFIG_ACPI
+/**
+ * cm32181_acpi_get_cpm() - Get CPM object from ACPI
+ * @dev: pointer of struct device.
+ * @obj_name: pointer of ACPI object name.
+ * @values: pointer of array for return elements.
+ * @count: maximum size of return array.
+ *
+ * Convert ACPI CPM table to array.
+ *
+ * Return: -ENODEV for fail. Otherwise is number of elements.
+ */
+static int cm32181_acpi_get_cpm(struct device *dev, char *obj_name,
+ u64 *values, int count)
+{
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *cpm, *elem;
+ acpi_handle handle;
+ acpi_status status;
+ int i;
+
+ handle = ACPI_HANDLE(dev);
+ if (!handle)
+ return -ENODEV;
+
+ status = acpi_evaluate_object(handle, obj_name, NULL, &buffer);
+ if (ACPI_FAILURE(status)) {
+ dev_err(dev, "object %s not found\n", obj_name);
+ return -ENODEV;
+ }
+
+ cpm = buffer.pointer;
+ if (cpm->package.count > count)
+ dev_warn(dev, "%s table contains %u values, only using first %d values\n",
+ obj_name, cpm->package.count, count);
+
+ count = min_t(int, cpm->package.count, count);
+ for (i = 0; i < count; i++) {
+ elem = &(cpm->package.elements[i]);
+ values[i] = elem->integer.value;
+ }
+
+ kfree(buffer.pointer);
+
+ return count;
+}
+
+static void cm32181_acpi_parse_cpm_tables(struct cm32181_chip *cm32181)
+{
+ u64 vals[CPM0_HEADER_SIZE + CM32181_CONF_REG_NUM];
+ struct device *dev = cm32181->dev;
+ int i, count;
+
+ count = cm32181_acpi_get_cpm(dev, "CPM0", vals, ARRAY_SIZE(vals));
+ if (count <= CPM0_HEADER_SIZE)
+ return;
+
+ count -= CPM0_HEADER_SIZE;
+
+ cm32181->init_regs_bitmap = vals[CPM0_REGS_BITMAP];
+ cm32181->init_regs_bitmap &= GENMASK(count - 1, 0);
+ for_each_set_bit(i, &cm32181->init_regs_bitmap, count)
+ cm32181->conf_regs[i] = vals[CPM0_HEADER_SIZE + i];
+
+ count = cm32181_acpi_get_cpm(dev, "CPM1", vals, ARRAY_SIZE(vals));
+ if (count != CPM1_SIZE)
+ return;
+
+ cm32181->lux_per_bit = vals[CPM1_LUX_PER_BIT];
+
+ /* Check for uncalibrated devices */
+ if (vals[CPM1_CALIBSCALE] == CM32181_CALIBSCALE_DEFAULT)
+ return;
+
+ cm32181->calibscale = vals[CPM1_CALIBSCALE];
+ /* CPM1 lux_per_bit is for the current it value */
+ cm32181_read_als_it(cm32181, &cm32181->lux_per_bit_base_it);
+}
+#else
+static void cm32181_acpi_parse_cpm_tables(struct cm32181_chip *cm32181)
+{
+}
+#endif /* CONFIG_ACPI */
+
/**
* cm32181_reg_init() - Initialize CM32181 registers
* @cm32181: pointer of struct cm32181.
@@ -78,18 +193,37 @@ static int cm32181_reg_init(struct cm32181_chip *cm32181)
return ret;
/* check device ID */
- if ((ret & 0xFF) != 0x81)
+ switch (ret & 0xFF) {
+ case 0x18: /* CM3218 */
+ cm32181->num_als_it = ARRAY_SIZE(cm3218_als_it_bits);
+ cm32181->als_it_bits = cm3218_als_it_bits;
+ cm32181->als_it_values = cm3218_als_it_values;
+ break;
+ case 0x81: /* CM32181 */
+ case 0x82: /* CM32182, fully compat. with CM32181 */
+ cm32181->num_als_it = ARRAY_SIZE(cm32181_als_it_bits);
+ cm32181->als_it_bits = cm32181_als_it_bits;
+ cm32181->als_it_values = cm32181_als_it_values;
+ break;
+ default:
return -ENODEV;
+ }
/* Default Values */
- cm32181->conf_regs[CM32181_REG_ADDR_CMD] = CM32181_CMD_ALS_ENABLE |
+ cm32181->conf_regs[CM32181_REG_ADDR_CMD] =
CM32181_CMD_ALS_IT_DEFAULT | CM32181_CMD_ALS_SM_DEFAULT;
+ cm32181->init_regs_bitmap = BIT(CM32181_REG_ADDR_CMD);
cm32181->calibscale = CM32181_CALIBSCALE_DEFAULT;
+ cm32181->lux_per_bit = CM32181_LUX_PER_BIT;
+ cm32181->lux_per_bit_base_it = CM32181_LUX_PER_BIT_BASE_IT;
+
+ if (ACPI_HANDLE(cm32181->dev))
+ cm32181_acpi_parse_cpm_tables(cm32181);
/* Initialize registers*/
- for (i = 0; i < CM32181_CONF_REG_NUM; i++) {
- ret = i2c_smbus_write_word_data(client, cm32181_reg[i],
- cm32181->conf_regs[i]);
+ for_each_set_bit(i, &cm32181->init_regs_bitmap, CM32181_CONF_REG_NUM) {
+ ret = i2c_smbus_write_word_data(client, i,
+ cm32181->conf_regs[i]);
if (ret < 0)
return ret;
}
@@ -102,7 +236,7 @@ static int cm32181_reg_init(struct cm32181_chip *cm32181)
* @cm32181: pointer of struct cm32181
* @val2: pointer of int to load the als_it value.
*
- * Report the current integartion time by millisecond.
+ * Report the current integration time in milliseconds.
*
* Return: IIO_VAL_INT_PLUS_MICRO for success, otherwise -EINVAL.
*/
@@ -114,9 +248,9 @@ static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val2)
als_it = cm32181->conf_regs[CM32181_REG_ADDR_CMD];
als_it &= CM32181_CMD_ALS_IT_MASK;
als_it >>= CM32181_CMD_ALS_IT_SHIFT;
- for (i = 0; i < ARRAY_SIZE(als_it_bits); i++) {
- if (als_it == als_it_bits[i]) {
- *val2 = als_it_value[i];
+ for (i = 0; i < cm32181->num_als_it; i++) {
+ if (als_it == cm32181->als_it_bits[i]) {
+ *val2 = cm32181->als_it_values[i];
return IIO_VAL_INT_PLUS_MICRO;
}
}
@@ -139,14 +273,14 @@ static int cm32181_write_als_it(struct cm32181_chip *cm32181, int val)
u16 als_it;
int ret, i, n;
- n = ARRAY_SIZE(als_it_value);
+ n = cm32181->num_als_it;
for (i = 0; i < n; i++)
- if (val <= als_it_value[i])
+ if (val <= cm32181->als_it_values[i])
break;
if (i >= n)
i = n - 1;
- als_it = als_it_bits[i];
+ als_it = cm32181->als_it_bits[i];
als_it <<= CM32181_CMD_ALS_IT_SHIFT;
mutex_lock(&cm32181->lock);
@@ -175,15 +309,15 @@ static int cm32181_get_lux(struct cm32181_chip *cm32181)
struct i2c_client *client = cm32181->client;
int ret;
int als_it;
- unsigned long lux;
+ u64 lux;
ret = cm32181_read_als_it(cm32181, &als_it);
if (ret < 0)
return -EINVAL;
- lux = CM32181_MLUX_PER_BIT;
- lux *= CM32181_MLUX_PER_BIT_BASE_IT;
- lux /= als_it;
+ lux = cm32181->lux_per_bit;
+ lux *= cm32181->lux_per_bit_base_it;
+ lux = div_u64(lux, als_it);
ret = i2c_smbus_read_word_data(client, CM32181_REG_ADDR_ALS);
if (ret < 0)
@@ -191,8 +325,8 @@ static int cm32181_get_lux(struct cm32181_chip *cm32181)
lux *= ret;
lux *= cm32181->calibscale;
- lux /= CM32181_CALIBSCALE_RESOLUTION;
- lux /= MLUX_PER_LUX;
+ lux = div_u64(lux, CM32181_CALIBSCALE_RESOLUTION);
+ lux = div_u64(lux, CM32181_LUX_PER_BIT_RESOLUTION);
if (lux > 0xFFFF)
lux = 0xFFFF;
@@ -258,11 +392,12 @@ static int cm32181_write_raw(struct iio_dev *indio_dev,
static ssize_t cm32181_get_it_available(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct cm32181_chip *cm32181 = iio_priv(dev_to_iio_dev(dev));
int i, n, len;
- n = ARRAY_SIZE(als_it_value);
+ n = cm32181->num_als_it;
for (i = 0, len = 0; i < n; i++)
- len += sprintf(buf + len, "0.%06u ", als_it_value[i]);
+ len += sprintf(buf + len, "0.%06u ", cm32181->als_it_values[i]);
return len + sprintf(buf + len, "\n");
}
@@ -294,70 +429,85 @@ static const struct iio_info cm32181_info = {
.attrs = &cm32181_attribute_group,
};
-static int cm32181_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int cm32181_probe(struct i2c_client *client)
{
+ struct device *dev = &client->dev;
struct cm32181_chip *cm32181;
struct iio_dev *indio_dev;
int ret;
- indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*cm32181));
- if (!indio_dev) {
- dev_err(&client->dev, "devm_iio_device_alloc failed\n");
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*cm32181));
+ if (!indio_dev)
return -ENOMEM;
+
+ /*
+ * Some ACPI systems list 2 I2C resources for the CM3218 sensor, the
+ * SMBus Alert Response Address (ARA, 0x0c) and the actual I2C address.
+ * Detect this and take the following step to deal with it:
+ * 1. When a SMBus Alert capable sensor has an Alert asserted, it will
+ * not respond on its actual I2C address. Read a byte from the ARA
+ * to clear any pending Alerts.
+ * 2. Create a "dummy" client for the actual I2C address and
+ * use that client to communicate with the sensor.
+ */
+ if (ACPI_HANDLE(dev) && client->addr == SMBUS_ALERT_RESPONSE_ADDRESS) {
+ struct i2c_board_info board_info = { .type = "dummy" };
+
+ i2c_smbus_read_byte(client);
+
+ client = i2c_acpi_new_device(dev, 1, &board_info);
+ if (IS_ERR(client))
+ return PTR_ERR(client);
}
cm32181 = iio_priv(indio_dev);
- i2c_set_clientdata(client, indio_dev);
cm32181->client = client;
+ cm32181->dev = dev;
mutex_init(&cm32181->lock);
- indio_dev->dev.parent = &client->dev;
indio_dev->channels = cm32181_channels;
indio_dev->num_channels = ARRAY_SIZE(cm32181_channels);
indio_dev->info = &cm32181_info;
- indio_dev->name = id->name;
+ indio_dev->name = dev_name(dev);
indio_dev->modes = INDIO_DIRECT_MODE;
ret = cm32181_reg_init(cm32181);
if (ret) {
- dev_err(&client->dev,
- "%s: register init failed\n",
- __func__);
+ dev_err(dev, "%s: register init failed\n", __func__);
return ret;
}
- ret = devm_iio_device_register(&client->dev, indio_dev);
+ ret = devm_iio_device_register(dev, indio_dev);
if (ret) {
- dev_err(&client->dev,
- "%s: regist device failed\n",
- __func__);
+ dev_err(dev, "%s: regist device failed\n", __func__);
return ret;
}
return 0;
}
-static const struct i2c_device_id cm32181_id[] = {
- { "cm32181", 0 },
- { }
-};
-
-MODULE_DEVICE_TABLE(i2c, cm32181_id);
-
static const struct of_device_id cm32181_of_match[] = {
+ { .compatible = "capella,cm3218" },
{ .compatible = "capella,cm32181" },
{ }
};
MODULE_DEVICE_TABLE(of, cm32181_of_match);
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id cm32181_acpi_match[] = {
+ { "CPLM3218", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, cm32181_acpi_match);
+#endif
+
static struct i2c_driver cm32181_driver = {
.driver = {
.name = "cm32181",
- .of_match_table = of_match_ptr(cm32181_of_match),
+ .acpi_match_table = ACPI_PTR(cm32181_acpi_match),
+ .of_match_table = cm32181_of_match,
},
- .id_table = cm32181_id,
- .probe = cm32181_probe,
+ .probe_new = cm32181_probe,
};
module_i2c_driver(cm32181_driver);
diff --git a/drivers/iio/light/cm3232.c b/drivers/iio/light/cm3232.c
index cd3cfb7d02bd..18a410340dc5 100644
--- a/drivers/iio/light/cm3232.c
+++ b/drivers/iio/light/cm3232.c
@@ -10,6 +10,7 @@
#include <linux/i2c.h>
#include <linux/module.h>
+#include <linux/mod_devicetable.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/init.h>
@@ -339,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;
@@ -418,7 +418,7 @@ MODULE_DEVICE_TABLE(of, cm3232_of_match);
static struct i2c_driver cm3232_driver = {
.driver = {
.name = "cm3232",
- .of_match_table = of_match_ptr(cm3232_of_match),
+ .of_match_table = cm3232_of_match,
#ifdef CONFIG_PM_SLEEP
.pm = &cm3232_pm_ops,
#endif
diff --git a/drivers/iio/light/cm3323.c b/drivers/iio/light/cm3323.c
index 0443861ba1ec..6d1b0ffd144b 100644
--- a/drivers/iio/light/cm3323.c
+++ b/drivers/iio/light/cm3323.c
@@ -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;
diff --git a/drivers/iio/light/cm3605.c b/drivers/iio/light/cm3605.c
index 964ede49f662..4c83953672be 100644
--- a/drivers/iio/light/cm3605.c
+++ b/drivers/iio/light/cm3605.c
@@ -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;
diff --git a/drivers/iio/light/cm36651.c b/drivers/iio/light/cm36651.c
index 90e38fcc974b..fd83a19929bc 100644
--- a/drivers/iio/light/cm36651.c
+++ b/drivers/iio/light/cm36651.c
@@ -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;
diff --git a/drivers/iio/light/cros_ec_light_prox.c b/drivers/iio/light/cros_ec_light_prox.c
index 2198b50909ed..fed79ba27fda 100644
--- a/drivers/iio/light/cros_ec_light_prox.c
+++ b/drivers/iio/light/cros_ec_light_prox.c
@@ -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,
diff --git a/drivers/iio/light/gp2ap002.c b/drivers/iio/light/gp2ap002.c
index b7ef16b28280..d5e1cd27eb46 100644
--- a/drivers/iio/light/gp2ap002.c
+++ b/drivers/iio/light/gp2ap002.c
@@ -158,6 +158,9 @@ static irqreturn_t gp2ap002_prox_irq(int irq, void *d)
int val;
int ret;
+ if (!gp2ap002->enabled)
+ goto err_retrig;
+
ret = regmap_read(gp2ap002->map, GP2AP002_PROX, &val);
if (ret) {
dev_err(gp2ap002->dev, "error reading proximity\n");
@@ -247,6 +250,8 @@ static int gp2ap002_read_raw(struct iio_dev *indio_dev,
struct gp2ap002 *gp2ap002 = iio_priv(indio_dev);
int ret;
+ pm_runtime_get_sync(gp2ap002->dev);
+
switch (mask) {
case IIO_CHAN_INFO_RAW:
switch (chan->type) {
@@ -255,13 +260,21 @@ static int gp2ap002_read_raw(struct iio_dev *indio_dev,
if (ret < 0)
return ret;
*val = ret;
- return IIO_VAL_INT;
+ ret = IIO_VAL_INT;
+ goto out;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
default:
- return -EINVAL;
+ ret = -EINVAL;
}
+
+out:
+ pm_runtime_mark_last_busy(gp2ap002->dev);
+ pm_runtime_put_autosuspend(gp2ap002->dev);
+
+ return ret;
}
static int gp2ap002_init(struct gp2ap002 *gp2ap002)
@@ -583,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;
diff --git a/drivers/iio/light/gp2ap020a00f.c b/drivers/iio/light/gp2ap020a00f.c
index 7fbbce0d4bc7..e2850c1a7353 100644
--- a/drivers/iio/light/gp2ap020a00f.c
+++ b/drivers/iio/light/gp2ap020a00f.c
@@ -38,8 +38,8 @@
#include <linux/irq.h>
#include <linux/irq_work.h>
#include <linux/module.h>
+#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
-#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
@@ -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;
@@ -1617,18 +1606,16 @@ static const struct i2c_device_id gp2ap020a00f_id[] = {
MODULE_DEVICE_TABLE(i2c, gp2ap020a00f_id);
-#ifdef CONFIG_OF
static const struct of_device_id gp2ap020a00f_of_match[] = {
{ .compatible = "sharp,gp2ap020a00f" },
{ }
};
MODULE_DEVICE_TABLE(of, gp2ap020a00f_of_match);
-#endif
static struct i2c_driver gp2ap020a00f_driver = {
.driver = {
.name = GP2A_I2C_NAME,
- .of_match_table = of_match_ptr(gp2ap020a00f_of_match),
+ .of_match_table = gp2ap020a00f_of_match,
},
.probe = gp2ap020a00f_probe,
.remove = gp2ap020a00f_remove,
diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
index b6cd299517d1..a21c827e4953 100644
--- a/drivers/iio/light/hid-sensor-als.c
+++ b/drivers/iio/light/hid-sensor-als.c
@@ -14,8 +14,6 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
-#include <linux/iio/trigger_consumer.h>
-#include <linux/iio/triggered_buffer.h>
#include "../common/hid-sensors/hid-sensor-trigger.h"
enum {
@@ -303,23 +301,17 @@ 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;
- ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
- NULL, NULL);
- if (ret) {
- dev_err(&pdev->dev, "failed to initialize trigger buffer\n");
- goto error_free_dev_mem;
- }
atomic_set(&als_state->common_attributes.data_ready, 0);
+
ret = hid_sensor_setup_trigger(indio_dev, name,
&als_state->common_attributes);
if (ret < 0) {
dev_err(&pdev->dev, "trigger setup failed\n");
- goto error_unreg_buffer_funcs;
+ goto error_free_dev_mem;
}
ret = iio_device_register(indio_dev);
@@ -343,9 +335,7 @@ static int hid_als_probe(struct platform_device *pdev)
error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
- hid_sensor_remove_trigger(&als_state->common_attributes);
-error_unreg_buffer_funcs:
- iio_triggered_buffer_cleanup(indio_dev);
+ hid_sensor_remove_trigger(indio_dev, &als_state->common_attributes);
error_free_dev_mem:
kfree(indio_dev->channels);
return ret;
@@ -360,8 +350,7 @@ static int hid_als_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_ALS);
iio_device_unregister(indio_dev);
- hid_sensor_remove_trigger(&als_state->common_attributes);
- iio_triggered_buffer_cleanup(indio_dev);
+ hid_sensor_remove_trigger(indio_dev, &als_state->common_attributes);
kfree(indio_dev->channels);
return 0;
diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c
index 7e1030af9ba3..330cf359e0b8 100644
--- a/drivers/iio/light/hid-sensor-prox.c
+++ b/drivers/iio/light/hid-sensor-prox.c
@@ -14,8 +14,6 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
-#include <linux/iio/trigger_consumer.h>
-#include <linux/iio/triggered_buffer.h>
#include "../common/hid-sensors/hid-sensor-trigger.h"
#define CHANNEL_SCAN_INDEX_PRESENCE 0
@@ -281,23 +279,17 @@ 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;
- ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
- NULL, NULL);
- if (ret) {
- dev_err(&pdev->dev, "failed to initialize trigger buffer\n");
- goto error_free_dev_mem;
- }
atomic_set(&prox_state->common_attributes.data_ready, 0);
+
ret = hid_sensor_setup_trigger(indio_dev, name,
&prox_state->common_attributes);
if (ret) {
dev_err(&pdev->dev, "trigger setup failed\n");
- goto error_unreg_buffer_funcs;
+ goto error_free_dev_mem;
}
ret = iio_device_register(indio_dev);
@@ -321,9 +313,7 @@ static int hid_prox_probe(struct platform_device *pdev)
error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
- hid_sensor_remove_trigger(&prox_state->common_attributes);
-error_unreg_buffer_funcs:
- iio_triggered_buffer_cleanup(indio_dev);
+ hid_sensor_remove_trigger(indio_dev, &prox_state->common_attributes);
error_free_dev_mem:
kfree(indio_dev->channels);
return ret;
@@ -338,8 +328,7 @@ static int hid_prox_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_PROX);
iio_device_unregister(indio_dev);
- hid_sensor_remove_trigger(&prox_state->common_attributes);
- iio_triggered_buffer_cleanup(indio_dev);
+ hid_sensor_remove_trigger(indio_dev, &prox_state->common_attributes);
kfree(indio_dev->channels);
return 0;
diff --git a/drivers/iio/light/iqs621-als.c b/drivers/iio/light/iqs621-als.c
index b2988a782bd0..004ea890a4b2 100644
--- a/drivers/iio/light/iqs621-als.c
+++ b/drivers/iio/light/iqs621-als.c
@@ -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;
diff --git a/drivers/iio/light/isl29018.c b/drivers/iio/light/isl29018.c
index 805a74f08ad1..ac8ad0f32689 100644
--- a/drivers/iio/light/isl29018.c
+++ b/drivers/iio/light/isl29018.c
@@ -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);
diff --git a/drivers/iio/light/isl29028.c b/drivers/iio/light/isl29028.c
index 4d220c835c75..2f8b494f3e08 100644
--- a/drivers/iio/light/isl29028.c
+++ b/drivers/iio/light/isl29028.c
@@ -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);
diff --git a/drivers/iio/light/isl29125.c b/drivers/iio/light/isl29125.c
index e37894f0ae0b..b93b85dbc3a6 100644
--- a/drivers/iio/light/isl29125.c
+++ b/drivers/iio/light/isl29125.c
@@ -213,7 +213,7 @@ static const struct iio_info isl29125_info = {
.attrs = &isl29125_attribute_group,
};
-static int isl29125_buffer_preenable(struct iio_dev *indio_dev)
+static int isl29125_buffer_postenable(struct iio_dev *indio_dev)
{
struct isl29125_data *data = iio_priv(indio_dev);
@@ -225,11 +225,6 @@ static int isl29125_buffer_preenable(struct iio_dev *indio_dev)
static int isl29125_buffer_predisable(struct iio_dev *indio_dev)
{
struct isl29125_data *data = iio_priv(indio_dev);
- int ret;
-
- ret = iio_triggered_buffer_predisable(indio_dev);
- if (ret < 0)
- return ret;
data->conf1 &= ~ISL29125_MODE_MASK;
data->conf1 |= ISL29125_MODE_PD;
@@ -238,8 +233,7 @@ static int isl29125_buffer_predisable(struct iio_dev *indio_dev)
}
static const struct iio_buffer_setup_ops isl29125_buffer_setup_ops = {
- .preenable = isl29125_buffer_preenable,
- .postenable = &iio_triggered_buffer_postenable,
+ .postenable = isl29125_buffer_postenable,
.predisable = isl29125_buffer_predisable,
};
@@ -258,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;
diff --git a/drivers/iio/light/jsa1212.c b/drivers/iio/light/jsa1212.c
index 13deeebe37eb..724a0ec9f35c 100644
--- a/drivers/iio/light/jsa1212.c
+++ b/drivers/iio/light/jsa1212.c
@@ -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;
diff --git a/drivers/iio/light/lm3533-als.c b/drivers/iio/light/lm3533-als.c
index bc196c212881..8a621244dd01 100644
--- a/drivers/iio/light/lm3533-als.c
+++ b/drivers/iio/light/lm3533-als.c
@@ -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);
diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
index 71f99d2a22c1..b4323d2db0b1 100644
--- a/drivers/iio/light/ltr501.c
+++ b/drivers/iio/light/ltr501.c
@@ -101,12 +101,12 @@ struct ltr501_gain {
int uscale;
};
-static struct ltr501_gain ltr501_als_gain_tbl[] = {
+static const struct ltr501_gain ltr501_als_gain_tbl[] = {
{1, 0},
{0, 5000},
};
-static struct ltr501_gain ltr559_als_gain_tbl[] = {
+static const struct ltr501_gain ltr559_als_gain_tbl[] = {
{1, 0},
{0, 500000},
{0, 250000},
@@ -117,14 +117,14 @@ static struct ltr501_gain ltr559_als_gain_tbl[] = {
{0, 10000},
};
-static struct ltr501_gain ltr501_ps_gain_tbl[] = {
+static const struct ltr501_gain ltr501_ps_gain_tbl[] = {
{1, 0},
{0, 250000},
{0, 125000},
{0, 62500},
};
-static struct ltr501_gain ltr559_ps_gain_tbl[] = {
+static const struct ltr501_gain ltr559_ps_gain_tbl[] = {
{0, 62500}, /* x16 gain */
{0, 31250}, /* x32 gain */
{0, 15625}, /* bits X1 are for x64 gain */
@@ -133,9 +133,9 @@ static struct ltr501_gain ltr559_ps_gain_tbl[] = {
struct ltr501_chip_info {
u8 partid;
- struct ltr501_gain *als_gain;
+ const struct ltr501_gain *als_gain;
int als_gain_tbl_size;
- struct ltr501_gain *ps_gain;
+ const struct ltr501_gain *ps_gain;
int ps_gain_tbl_size;
u8 als_mode_active;
u8 als_gain_mask;
@@ -192,7 +192,7 @@ static int ltr501_match_samp_freq(const struct ltr501_samp_table *tab,
return -EINVAL;
}
-static int ltr501_als_read_samp_freq(struct ltr501_data *data,
+static int ltr501_als_read_samp_freq(const struct ltr501_data *data,
int *val, int *val2)
{
int ret, i;
@@ -210,7 +210,7 @@ static int ltr501_als_read_samp_freq(struct ltr501_data *data,
return IIO_VAL_INT_PLUS_MICRO;
}
-static int ltr501_ps_read_samp_freq(struct ltr501_data *data,
+static int ltr501_ps_read_samp_freq(const struct ltr501_data *data,
int *val, int *val2)
{
int ret, i;
@@ -266,7 +266,7 @@ static int ltr501_ps_write_samp_freq(struct ltr501_data *data,
return ret;
}
-static int ltr501_als_read_samp_period(struct ltr501_data *data, int *val)
+static int ltr501_als_read_samp_period(const struct ltr501_data *data, int *val)
{
int ret, i;
@@ -282,7 +282,7 @@ static int ltr501_als_read_samp_period(struct ltr501_data *data, int *val)
return IIO_VAL_INT;
}
-static int ltr501_ps_read_samp_period(struct ltr501_data *data, int *val)
+static int ltr501_ps_read_samp_period(const struct ltr501_data *data, int *val)
{
int ret, i;
@@ -321,7 +321,7 @@ static unsigned long ltr501_calculate_lux(u16 vis_data, u16 ir_data)
return lux / 1000;
}
-static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask)
+static int ltr501_drdy(const struct ltr501_data *data, u8 drdy_mask)
{
int tries = 100;
int ret, status;
@@ -373,7 +373,8 @@ static int ltr501_set_it_time(struct ltr501_data *data, int it)
}
/* read int time in micro seconds */
-static int ltr501_read_it_time(struct ltr501_data *data, int *val, int *val2)
+static int ltr501_read_it_time(const struct ltr501_data *data,
+ int *val, int *val2)
{
int ret, index;
@@ -391,7 +392,7 @@ static int ltr501_read_it_time(struct ltr501_data *data, int *val, int *val2)
return IIO_VAL_INT_PLUS_MICRO;
}
-static int ltr501_read_als(struct ltr501_data *data, __le16 buf[2])
+static int ltr501_read_als(const struct ltr501_data *data, __le16 buf[2])
{
int ret;
@@ -403,7 +404,7 @@ static int ltr501_read_als(struct ltr501_data *data, __le16 buf[2])
buf, 2 * sizeof(__le16));
}
-static int ltr501_read_ps(struct ltr501_data *data)
+static int ltr501_read_ps(const struct ltr501_data *data)
{
int ret, status;
@@ -419,7 +420,7 @@ static int ltr501_read_ps(struct ltr501_data *data)
return status;
}
-static int ltr501_read_intr_prst(struct ltr501_data *data,
+static int ltr501_read_intr_prst(const struct ltr501_data *data,
enum iio_chan_type type,
int *val2)
{
@@ -716,7 +717,7 @@ static int ltr501_read_raw(struct iio_dev *indio_dev,
return -EINVAL;
}
-static int ltr501_get_gain_index(struct ltr501_gain *gain, int size,
+static int ltr501_get_gain_index(const struct ltr501_gain *gain, int size,
int val, int val2)
{
int i;
@@ -848,14 +849,14 @@ static int ltr501_write_raw(struct iio_dev *indio_dev,
return ret;
}
-static int ltr501_read_thresh(struct iio_dev *indio_dev,
+static int ltr501_read_thresh(const struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
enum iio_event_info info,
int *val, int *val2)
{
- struct ltr501_data *data = iio_priv(indio_dev);
+ const struct ltr501_data *data = iio_priv(indio_dev);
int ret, thresh_data;
switch (chan->type) {
@@ -1242,13 +1243,16 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct ltr501_data *data = iio_priv(indio_dev);
- u16 buf[8];
+ struct {
+ u16 channels[3];
+ s64 ts __aligned(8);
+ } scan;
__le16 als_buf[2];
u8 mask = 0;
int j = 0;
int ret, psdata;
- memset(buf, 0, sizeof(buf));
+ memset(&scan, 0, sizeof(scan));
/* figure out which data needs to be ready */
if (test_bit(0, indio_dev->active_scan_mask) ||
@@ -1263,13 +1267,13 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p)
if (mask & LTR501_STATUS_ALS_RDY) {
ret = regmap_bulk_read(data->regmap, LTR501_ALS_DATA1,
- (u8 *)als_buf, sizeof(als_buf));
+ als_buf, sizeof(als_buf));
if (ret < 0)
return ret;
if (test_bit(0, indio_dev->active_scan_mask))
- buf[j++] = le16_to_cpu(als_buf[1]);
+ scan.channels[j++] = le16_to_cpu(als_buf[1]);
if (test_bit(1, indio_dev->active_scan_mask))
- buf[j++] = le16_to_cpu(als_buf[0]);
+ scan.channels[j++] = le16_to_cpu(als_buf[0]);
}
if (mask & LTR501_STATUS_PS_RDY) {
@@ -1277,10 +1281,10 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p)
&psdata, 2);
if (ret < 0)
goto done;
- buf[j++] = psdata & LTR501_PS_DATA_MASK;
+ scan.channels[j++] = psdata & LTR501_PS_DATA_MASK;
}
- iio_push_to_buffers_with_timestamp(indio_dev, buf,
+ iio_push_to_buffers_with_timestamp(indio_dev, &scan,
iio_get_time_ns(indio_dev));
done:
@@ -1359,7 +1363,7 @@ static bool ltr501_is_volatile_reg(struct device *dev, unsigned int reg)
}
}
-static struct regmap_config ltr501_regmap_config = {
+static const struct regmap_config ltr501_regmap_config = {
.name = LTR501_REGMAP_NAME,
.reg_bits = 8,
.val_bits = 8,
@@ -1479,7 +1483,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;
diff --git a/drivers/iio/light/lv0104cs.c b/drivers/iio/light/lv0104cs.c
index 55b8e2855647..c2aef88f4e63 100644
--- a/drivers/iio/light/lv0104cs.c
+++ b/drivers/iio/light/lv0104cs.c
@@ -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;
diff --git a/drivers/iio/light/max44000.c b/drivers/iio/light/max44000.c
index d6d8007ba430..b8e721bced5b 100644
--- a/drivers/iio/light/max44000.c
+++ b/drivers/iio/light/max44000.c
@@ -75,6 +75,11 @@
struct max44000_data {
struct mutex lock;
struct regmap *regmap;
+ /* Ensure naturally aligned timestamp */
+ struct {
+ u16 channels[2];
+ s64 ts __aligned(8);
+ } scan;
};
/* Default scale is set to the minimum of 0.03125 or 1 / (1 << 5) lux */
@@ -488,7 +493,6 @@ static irqreturn_t max44000_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct max44000_data *data = iio_priv(indio_dev);
- u16 buf[8]; /* 2x u16 + padding + 8 bytes timestamp */
int index = 0;
unsigned int regval;
int ret;
@@ -498,17 +502,17 @@ static irqreturn_t max44000_trigger_handler(int irq, void *p)
ret = max44000_read_alsval(data);
if (ret < 0)
goto out_unlock;
- buf[index++] = ret;
+ data->scan.channels[index++] = ret;
}
if (test_bit(MAX44000_SCAN_INDEX_PRX, indio_dev->active_scan_mask)) {
ret = regmap_read(data->regmap, MAX44000_REG_PRX_DATA, &regval);
if (ret < 0)
goto out_unlock;
- buf[index] = regval;
+ data->scan.channels[index] = regval;
}
mutex_unlock(&data->lock);
- iio_push_to_buffers_with_timestamp(indio_dev, buf,
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
iio_get_time_ns(indio_dev));
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
@@ -538,7 +542,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;
diff --git a/drivers/iio/light/max44009.c b/drivers/iio/light/max44009.c
index 00ba15499638..801e5a0ad496 100644
--- a/drivers/iio/light/max44009.c
+++ b/drivers/iio/light/max44009.c
@@ -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;
diff --git a/drivers/iio/light/noa1305.c b/drivers/iio/light/noa1305.c
index 5ebfbc52f541..a308fbc2fc7b 100644
--- a/drivers/iio/light/noa1305.c
+++ b/drivers/iio/light/noa1305.c
@@ -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);
diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c
index 92004a2563ea..2d48d61909a4 100644
--- a/drivers/iio/light/opt3001.c
+++ b/drivers/iio/light/opt3001.c
@@ -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>
@@ -16,6 +16,7 @@
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/types.h>
@@ -767,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;
@@ -844,7 +844,7 @@ static struct i2c_driver opt3001_driver = {
.driver = {
.name = "opt3001",
- .of_match_table = of_match_ptr(opt3001_of_match),
+ .of_match_table = opt3001_of_match,
},
};
diff --git a/drivers/iio/light/pa12203001.c b/drivers/iio/light/pa12203001.c
index 0295783f036a..bfade6577a38 100644
--- a/drivers/iio/light/pa12203001.c
+++ b/drivers/iio/light/pa12203001.c
@@ -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;
diff --git a/drivers/iio/light/rpr0521.c b/drivers/iio/light/rpr0521.c
index a0a7aeae5a82..aa2972b04833 100644
--- a/drivers/iio/light/rpr0521.c
+++ b/drivers/iio/light/rpr0521.c
@@ -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;
diff --git a/drivers/iio/light/si1133.c b/drivers/iio/light/si1133.c
index 9174ab928880..c280b4195003 100644
--- a/drivers/iio/light/si1133.c
+++ b/drivers/iio/light/si1133.c
@@ -17,6 +17,8 @@
#include <linux/util_macros.h>
+#include <asm/unaligned.h>
+
#define SI1133_REG_PART_ID 0x00
#define SI1133_REG_REV_ID 0x01
#define SI1133_REG_MFR_ID 0x02
@@ -104,8 +106,6 @@
#define SI1133_LUX_BUFFER_SIZE 9
#define SI1133_MEASURE_BUFFER_SIZE 3
-#define SI1133_SIGN_BIT_INDEX 23
-
static const int si1133_scale_available[] = {
1, 2, 4, 8, 16, 32, 64, 128};
@@ -633,8 +633,7 @@ static int si1133_measure(struct si1133_data *data,
if (err)
return err;
- *val = sign_extend32((buffer[0] << 16) | (buffer[1] << 8) | buffer[2],
- SI1133_SIGN_BIT_INDEX);
+ *val = sign_extend32(get_unaligned_be24(&buffer[0]), 23);
return err;
}
@@ -723,16 +722,11 @@ static int si1133_get_lux(struct si1133_data *data, int *val)
if (err)
return err;
- high_vis =
- sign_extend32((buffer[0] << 16) | (buffer[1] << 8) | buffer[2],
- SI1133_SIGN_BIT_INDEX);
+ high_vis = sign_extend32(get_unaligned_be24(&buffer[0]), 23);
- low_vis =
- sign_extend32((buffer[3] << 16) | (buffer[4] << 8) | buffer[5],
- SI1133_SIGN_BIT_INDEX);
+ low_vis = sign_extend32(get_unaligned_be24(&buffer[3]), 23);
- ir = sign_extend32((buffer[6] << 16) | (buffer[7] << 8) | buffer[8],
- SI1133_SIGN_BIT_INDEX);
+ ir = sign_extend32(get_unaligned_be24(&buffer[6]), 23);
if (high_vis > SI1133_ADC_THRESHOLD || ir > SI1133_ADC_THRESHOLD)
lux = si1133_calc_polynomial(high_vis, ir,
@@ -1021,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);
diff --git a/drivers/iio/light/si1145.c b/drivers/iio/light/si1145.c
index 0476c2bc8138..8f5f857c2e7d 100644
--- a/drivers/iio/light/si1145.c
+++ b/drivers/iio/light/si1145.c
@@ -181,7 +181,7 @@ struct si1145_data {
int meas_rate;
};
-/**
+/*
* __si1145_command_reset() - Send CMD_NOP and wait for response 0
*
* Does not modify data->rsp_seq
@@ -215,7 +215,7 @@ static int __si1145_command_reset(struct si1145_data *data)
}
}
-/**
+/*
* si1145_command() - Execute a command and poll the response register
*
* All conversion overflows are reported as -EOVERFLOW
@@ -1042,7 +1042,7 @@ static int si1145_initialize(struct si1145_data *data)
SI1145_LED_CURRENT_45mA);
if (ret < 0)
return ret;
- /* fallthrough */
+ fallthrough;
case 2:
ret = i2c_smbus_write_byte_data(client,
SI1145_REG_PS_LED21,
@@ -1171,12 +1171,10 @@ 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,
};
-/**
+/*
* si1145_trigger_set_state() - Set trigger state
*
* When not using triggers interrupts are disabled and measurement rate is
@@ -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;
diff --git a/drivers/iio/light/st_uvis25_core.c b/drivers/iio/light/st_uvis25_core.c
index d262c254b895..a18a82e6bbf5 100644
--- a/drivers/iio/light/st_uvis25_core.c
+++ b/drivers/iio/light/st_uvis25_core.c
@@ -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;
diff --git a/drivers/iio/light/st_uvis25_i2c.c b/drivers/iio/light/st_uvis25_i2c.c
index 4889bbeb0c73..98cd49eefe45 100644
--- a/drivers/iio/light/st_uvis25_i2c.c
+++ b/drivers/iio/light/st_uvis25_i2c.c
@@ -9,6 +9,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/mod_devicetable.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/regmap.h>
@@ -31,8 +32,8 @@ static int st_uvis25_i2c_probe(struct i2c_client *client,
regmap = devm_regmap_init_i2c(client, &st_uvis25_i2c_regmap_config);
if (IS_ERR(regmap)) {
- dev_err(&client->dev, "Failed to register i2c regmap %d\n",
- (int)PTR_ERR(regmap));
+ dev_err(&client->dev, "Failed to register i2c regmap %ld\n",
+ PTR_ERR(regmap));
return PTR_ERR(regmap);
}
@@ -55,7 +56,7 @@ static struct i2c_driver st_uvis25_driver = {
.driver = {
.name = "st_uvis25_i2c",
.pm = &st_uvis25_pm_ops,
- .of_match_table = of_match_ptr(st_uvis25_i2c_of_match),
+ .of_match_table = st_uvis25_i2c_of_match,
},
.probe = st_uvis25_i2c_probe,
.id_table = st_uvis25_i2c_id_table,
diff --git a/drivers/iio/light/st_uvis25_spi.c b/drivers/iio/light/st_uvis25_spi.c
index a9ceae4f58b3..af9d94d12787 100644
--- a/drivers/iio/light/st_uvis25_spi.c
+++ b/drivers/iio/light/st_uvis25_spi.c
@@ -9,6 +9,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/mod_devicetable.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/regmap.h>
@@ -31,8 +32,8 @@ static int st_uvis25_spi_probe(struct spi_device *spi)
regmap = devm_regmap_init_spi(spi, &st_uvis25_spi_regmap_config);
if (IS_ERR(regmap)) {
- dev_err(&spi->dev, "Failed to register spi regmap %d\n",
- (int)PTR_ERR(regmap));
+ dev_err(&spi->dev, "Failed to register spi regmap %ld\n",
+ PTR_ERR(regmap));
return PTR_ERR(regmap);
}
@@ -55,7 +56,7 @@ static struct spi_driver st_uvis25_driver = {
.driver = {
.name = "st_uvis25_spi",
.pm = &st_uvis25_pm_ops,
- .of_match_table = of_match_ptr(st_uvis25_spi_of_match),
+ .of_match_table = st_uvis25_spi_of_match,
},
.probe = st_uvis25_spi_probe,
.id_table = st_uvis25_spi_id_table,
diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c
index 185c24a75ae6..a2827d03ab0f 100644
--- a/drivers/iio/light/stk3310.c
+++ b/drivers/iio/light/stk3310.c
@@ -37,6 +37,7 @@
#define STK3310_CHIP_ID_VAL 0x13
#define STK3311_CHIP_ID_VAL 0x1D
+#define STK3311X_CHIP_ID_VAL 0x12
#define STK3335_CHIP_ID_VAL 0x51
#define STK3310_PSINT_EN 0x01
#define STK3310_PS_MAX_VAL 0xFFFF
@@ -453,6 +454,7 @@ static int stk3310_init(struct iio_dev *indio_dev)
if (chipid != STK3310_CHIP_ID_VAL &&
chipid != STK3311_CHIP_ID_VAL &&
+ chipid != STK3311X_CHIP_ID_VAL &&
chipid != STK3335_CHIP_ID_VAL) {
dev_err(&client->dev, "invalid chip id: 0x%x\n", chipid);
return -ENODEV;
@@ -487,7 +489,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 +587,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;
diff --git a/drivers/iio/light/tcs3414.c b/drivers/iio/light/tcs3414.c
index b542e5619ead..6fe5d46f80d4 100644
--- a/drivers/iio/light/tcs3414.c
+++ b/drivers/iio/light/tcs3414.c
@@ -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;
diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c
index 12ad34441010..a0dc447aeb68 100644
--- a/drivers/iio/light/tcs3472.c
+++ b/drivers/iio/light/tcs3472.c
@@ -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;
diff --git a/drivers/iio/light/tsl2563.c b/drivers/iio/light/tsl2563.c
index d8c40a83097d..abc8d7db8dc1 100644
--- a/drivers/iio/light/tsl2563.c
+++ b/drivers/iio/light/tsl2563.c
@@ -69,7 +69,7 @@
#define TSL2563_TIMING_GAIN16 0x10
#define TSL2563_TIMING_GAIN1 0x00
-#define TSL2563_INT_DISBLED 0x00
+#define TSL2563_INT_DISABLED 0x00
#define TSL2563_INT_LEVEL 0x10
#define TSL2563_INT_PERSIST(n) ((n) & 0x0F)
@@ -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);
diff --git a/drivers/iio/light/tsl2583.c b/drivers/iio/light/tsl2583.c
index a760d14e146a..9e5490b7473b 100644
--- a/drivers/iio/light/tsl2583.c
+++ b/drivers/iio/light/tsl2583.c
@@ -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;
diff --git a/drivers/iio/light/tsl2772.c b/drivers/iio/light/tsl2772.c
index be37fcbd4654..735399405417 100644
--- a/drivers/iio/light/tsl2772.c
+++ b/drivers/iio/light/tsl2772.c
@@ -932,7 +932,7 @@ static ssize_t in_illuminance0_target_input_show(struct device *dev,
{
struct tsl2772_chip *chip = iio_priv(dev_to_iio_dev(dev));
- return snprintf(buf, PAGE_SIZE, "%d\n", chip->settings.als_cal_target);
+ return scnprintf(buf, PAGE_SIZE, "%d\n", chip->settings.als_cal_target);
}
static ssize_t in_illuminance0_target_input_store(struct device *dev,
@@ -986,7 +986,7 @@ static ssize_t in_illuminance0_lux_table_show(struct device *dev,
int offset = 0;
while (i < TSL2772_MAX_LUX_TABLE_SIZE) {
- offset += snprintf(buf + offset, PAGE_SIZE, "%u,%u,",
+ offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%u,%u,",
chip->tsl2772_device_lux[i].ch0,
chip->tsl2772_device_lux[i].ch1);
if (chip->tsl2772_device_lux[i].ch0 == 0) {
@@ -1000,7 +1000,7 @@ static ssize_t in_illuminance0_lux_table_show(struct device *dev,
i++;
}
- offset += snprintf(buf + offset, PAGE_SIZE, "\n");
+ offset += scnprintf(buf + offset, PAGE_SIZE - offset, "\n");
return offset;
}
@@ -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;
diff --git a/drivers/iio/light/tsl4531.c b/drivers/iio/light/tsl4531.c
index 0dfc664205c7..70505ba6d858 100644
--- a/drivers/iio/light/tsl4531.c
+++ b/drivers/iio/light/tsl4531.c
@@ -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);
diff --git a/drivers/iio/light/us5182d.c b/drivers/iio/light/us5182d.c
index b995f21a3347..393f27b75c75 100644
--- a/drivers/iio/light/us5182d.c
+++ b/drivers/iio/light/us5182d.c
@@ -446,8 +446,8 @@ static int us5182d_read_raw(struct iio_dev *indio_dev,
/**
* us5182d_update_dark_th - update Darh_Th registers
- * @data us5182d_data structure
- * @index index in us5182d_dark_ths array to use for the updated value
+ * @data: us5182d_data structure
+ * @index: index in us5182d_dark_ths array to use for the updated value
*
* Function needs to be called with a lock held because it needs two i2c write
* byte operations as these registers (0x27 0x28) don't work in word mode
@@ -469,8 +469,8 @@ static int us5182d_update_dark_th(struct us5182d_data *data, int index)
/**
* us5182d_apply_scale - update the ALS scale
- * @data us5182d_data structure
- * @index index in us5182d_scales array to use for the updated value
+ * @data: us5182d_data structure
+ * @index: index in us5182d_scales array to use for the updated value
*
* Function needs to be called with a lock held as we're having more than one
* i2c operation.
@@ -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;
diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
index ec803c1e81df..fff4b36b8b58 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -5,6 +5,7 @@
*
* Copyright 2012 Peter Meerwald <pmeerw@pmeerw.net>
* Copyright 2019 Pursim SPC
+ * Copyright 2020 Mathieu Othacehe <m.othacehe@gmail.com>
*
* IIO driver for:
* VCNL4000/10/20 (7-bit I2C slave address 0x13)
@@ -13,9 +14,7 @@
*
* TODO:
* allow to adjust IR current
- * proximity threshold and event handling
- * periodic ALS/proximity measurement (VCNL4010/20)
- * interrupts (VCNL4010/20/40, VCNL4200)
+ * interrupts (VCNL4040, VCNL4200)
*/
#include <linux/module.h>
@@ -23,9 +22,15 @@
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/pm_runtime.h>
+#include <linux/interrupt.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/events.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>
#define VCNL4000_DRV_NAME "vcnl4000"
#define VCNL4000_PROD_ID 0x01
@@ -35,14 +40,22 @@
#define VCNL4000_COMMAND 0x80 /* Command register */
#define VCNL4000_PROD_REV 0x81 /* Product ID and Revision ID */
+#define VCNL4010_PROX_RATE 0x82 /* Proximity rate */
#define VCNL4000_LED_CURRENT 0x83 /* IR LED current for proximity mode */
#define VCNL4000_AL_PARAM 0x84 /* Ambient light parameter register */
+#define VCNL4010_ALS_PARAM 0x84 /* ALS rate */
#define VCNL4000_AL_RESULT_HI 0x85 /* Ambient light result register, MSB */
#define VCNL4000_AL_RESULT_LO 0x86 /* Ambient light result register, LSB */
#define VCNL4000_PS_RESULT_HI 0x87 /* Proximity result register, MSB */
#define VCNL4000_PS_RESULT_LO 0x88 /* Proximity result register, LSB */
#define VCNL4000_PS_MEAS_FREQ 0x89 /* Proximity test signal frequency */
+#define VCNL4010_INT_CTRL 0x89 /* Interrupt control */
#define VCNL4000_PS_MOD_ADJ 0x8a /* Proximity modulator timing adjustment */
+#define VCNL4010_LOW_THR_HI 0x8a /* Low threshold, MSB */
+#define VCNL4010_LOW_THR_LO 0x8b /* Low threshold, LSB */
+#define VCNL4010_HIGH_THR_HI 0x8c /* High threshold, MSB */
+#define VCNL4010_HIGH_THR_LO 0x8d /* High threshold, LSB */
+#define VCNL4010_ISR 0x8e /* Interrupt status */
#define VCNL4200_AL_CONF 0x00 /* Ambient light configuration */
#define VCNL4200_PS_CONF1 0x03 /* Proximity configuration */
@@ -57,6 +70,36 @@
#define VCNL4000_PS_RDY BIT(5) /* proximity data ready? */
#define VCNL4000_AL_OD BIT(4) /* start on-demand ALS measurement */
#define VCNL4000_PS_OD BIT(3) /* start on-demand proximity measurement */
+#define VCNL4000_ALS_EN BIT(2) /* start ALS measurement */
+#define VCNL4000_PROX_EN BIT(1) /* start proximity measurement */
+#define VCNL4000_SELF_TIMED_EN BIT(0) /* start self-timed measurement */
+
+/* Bit masks for interrupt registers. */
+#define VCNL4010_INT_THR_SEL BIT(0) /* Select threshold interrupt source */
+#define VCNL4010_INT_THR_EN BIT(1) /* Threshold interrupt type */
+#define VCNL4010_INT_ALS_EN BIT(2) /* Enable on ALS data ready */
+#define VCNL4010_INT_PROX_EN BIT(3) /* Enable on proximity data ready */
+
+#define VCNL4010_INT_THR_HIGH 0 /* High threshold exceeded */
+#define VCNL4010_INT_THR_LOW 1 /* Low threshold exceeded */
+#define VCNL4010_INT_ALS 2 /* ALS data ready */
+#define VCNL4010_INT_PROXIMITY 3 /* Proximity data ready */
+
+#define VCNL4010_INT_THR \
+ (BIT(VCNL4010_INT_THR_LOW) | BIT(VCNL4010_INT_THR_HIGH))
+#define VCNL4010_INT_DRDY \
+ (BIT(VCNL4010_INT_PROXIMITY) | BIT(VCNL4010_INT_ALS))
+
+static const int vcnl4010_prox_sampling_frequency[][2] = {
+ {1, 950000},
+ {3, 906250},
+ {7, 812500},
+ {16, 625000},
+ {31, 250000},
+ {62, 500000},
+ {125, 0},
+ {250, 0},
+};
#define VCNL4000_SLEEP_DELAY_MS 2000 /* before we enter pm_runtime_suspend */
@@ -83,10 +126,15 @@ struct vcnl4000_data {
struct mutex vcnl4000_lock;
struct vcnl4200_channel vcnl4200_al;
struct vcnl4200_channel vcnl4200_ps;
+ uint32_t near_level;
};
struct vcnl4000_chip_spec {
const char *prod;
+ struct iio_chan_spec const *channels;
+ const int num_channels;
+ const struct iio_info *info;
+ bool irq_support;
int (*init)(struct vcnl4000_data *data);
int (*measure_light)(struct vcnl4000_data *data, int *val);
int (*measure_proximity)(struct vcnl4000_data *data, int *val);
@@ -215,11 +263,31 @@ static int vcnl4200_init(struct vcnl4000_data *data)
return 0;
};
+static int vcnl4000_read_data(struct vcnl4000_data *data, u8 data_reg, int *val)
+{
+ s32 ret;
+
+ ret = i2c_smbus_read_word_swapped(data->client, data_reg);
+ if (ret < 0)
+ return ret;
+
+ *val = ret;
+ return 0;
+}
+
+static int vcnl4000_write_data(struct vcnl4000_data *data, u8 data_reg, int val)
+{
+ if (val > U16_MAX)
+ return -ERANGE;
+
+ return i2c_smbus_write_word_swapped(data->client, data_reg, val);
+}
+
+
static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask,
u8 rdy_mask, u8 data_reg, int *val)
{
int tries = 20;
- __be16 buf;
int ret;
mutex_lock(&data->vcnl4000_lock);
@@ -246,13 +314,11 @@ static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask,
goto fail;
}
- ret = i2c_smbus_read_i2c_block_data(data->client,
- data_reg, sizeof(buf), (u8 *) &buf);
+ ret = vcnl4000_read_data(data, data_reg, val);
if (ret < 0)
goto fail;
mutex_unlock(&data->vcnl4000_lock);
- *val = be16_to_cpu(buf);
return 0;
@@ -312,47 +378,34 @@ static int vcnl4200_measure_proximity(struct vcnl4000_data *data, int *val)
return vcnl4200_measure(data, &data->vcnl4200_ps, val);
}
-static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = {
- [VCNL4000] = {
- .prod = "VCNL4000",
- .init = vcnl4000_init,
- .measure_light = vcnl4000_measure_light,
- .measure_proximity = vcnl4000_measure_proximity,
- .set_power_state = vcnl4000_set_power_state,
- },
- [VCNL4010] = {
- .prod = "VCNL4010/4020",
- .init = vcnl4000_init,
- .measure_light = vcnl4000_measure_light,
- .measure_proximity = vcnl4000_measure_proximity,
- .set_power_state = vcnl4000_set_power_state,
- },
- [VCNL4040] = {
- .prod = "VCNL4040",
- .init = vcnl4200_init,
- .measure_light = vcnl4200_measure_light,
- .measure_proximity = vcnl4200_measure_proximity,
- .set_power_state = vcnl4200_set_power_state,
- },
- [VCNL4200] = {
- .prod = "VCNL4200",
- .init = vcnl4200_init,
- .measure_light = vcnl4200_measure_light,
- .measure_proximity = vcnl4200_measure_proximity,
- .set_power_state = vcnl4200_set_power_state,
- },
-};
+static int vcnl4010_read_proxy_samp_freq(struct vcnl4000_data *data, int *val,
+ int *val2)
+{
+ int ret;
-static const struct iio_chan_spec vcnl4000_channels[] = {
- {
- .type = IIO_LIGHT,
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
- BIT(IIO_CHAN_INFO_SCALE),
- }, {
- .type = IIO_PROXIMITY,
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
- }
-};
+ ret = i2c_smbus_read_byte_data(data->client, VCNL4010_PROX_RATE);
+ if (ret < 0)
+ return ret;
+
+ if (ret >= ARRAY_SIZE(vcnl4010_prox_sampling_frequency))
+ return -EINVAL;
+
+ *val = vcnl4010_prox_sampling_frequency[ret][0];
+ *val2 = vcnl4010_prox_sampling_frequency[ret][1];
+
+ return 0;
+}
+
+static bool vcnl4010_is_in_periodic_mode(struct vcnl4000_data *data)
+{
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND);
+ if (ret < 0)
+ return false;
+
+ return !!(ret & VCNL4000_SELF_TIMED_EN);
+}
static int vcnl4000_set_pm_runtime_state(struct vcnl4000_data *data, bool on)
{
@@ -412,10 +465,550 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev,
}
}
+static int vcnl4010_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ int ret;
+ struct vcnl4000_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ case IIO_CHAN_INFO_SCALE:
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
+ /* Protect against event capture. */
+ if (vcnl4010_is_in_periodic_mode(data)) {
+ ret = -EBUSY;
+ } else {
+ ret = vcnl4000_read_raw(indio_dev, chan, val, val2,
+ mask);
+ }
+
+ iio_device_release_direct_mode(indio_dev);
+ return ret;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ switch (chan->type) {
+ case IIO_PROXIMITY:
+ ret = vcnl4010_read_proxy_samp_freq(data, val, val2);
+ if (ret < 0)
+ return ret;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static int vcnl4010_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:
+ *vals = (int *)vcnl4010_prox_sampling_frequency;
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ *length = 2 * ARRAY_SIZE(vcnl4010_prox_sampling_frequency);
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int vcnl4010_write_proxy_samp_freq(struct vcnl4000_data *data, int val,
+ int val2)
+{
+ unsigned int i;
+ int index = -1;
+
+ for (i = 0; i < ARRAY_SIZE(vcnl4010_prox_sampling_frequency); i++) {
+ if (val == vcnl4010_prox_sampling_frequency[i][0] &&
+ val2 == vcnl4010_prox_sampling_frequency[i][1]) {
+ index = i;
+ break;
+ }
+ }
+
+ if (index < 0)
+ return -EINVAL;
+
+ return i2c_smbus_write_byte_data(data->client, VCNL4010_PROX_RATE,
+ index);
+}
+
+static int vcnl4010_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ int ret;
+ struct vcnl4000_data *data = iio_priv(indio_dev);
+
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
+ /* Protect against event capture. */
+ if (vcnl4010_is_in_periodic_mode(data)) {
+ ret = -EBUSY;
+ goto end;
+ }
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ switch (chan->type) {
+ case IIO_PROXIMITY:
+ ret = vcnl4010_write_proxy_samp_freq(data, val, val2);
+ goto end;
+ default:
+ ret = -EINVAL;
+ goto end;
+ }
+ default:
+ ret = -EINVAL;
+ goto end;
+ }
+
+end:
+ iio_device_release_direct_mode(indio_dev);
+ return ret;
+}
+
+static int vcnl4010_read_event(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int *val, int *val2)
+{
+ int ret;
+ struct vcnl4000_data *data = iio_priv(indio_dev);
+
+ switch (info) {
+ case IIO_EV_INFO_VALUE:
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ ret = vcnl4000_read_data(data, VCNL4010_HIGH_THR_HI,
+ val);
+ if (ret < 0)
+ return ret;
+ return IIO_VAL_INT;
+ case IIO_EV_DIR_FALLING:
+ ret = vcnl4000_read_data(data, VCNL4010_LOW_THR_HI,
+ val);
+ if (ret < 0)
+ return ret;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static int vcnl4010_write_event(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int val, int val2)
+{
+ int ret;
+ struct vcnl4000_data *data = iio_priv(indio_dev);
+
+ switch (info) {
+ case IIO_EV_INFO_VALUE:
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ ret = vcnl4000_write_data(data, VCNL4010_HIGH_THR_HI,
+ val);
+ if (ret < 0)
+ return ret;
+ return IIO_VAL_INT;
+ case IIO_EV_DIR_FALLING:
+ ret = vcnl4000_write_data(data, VCNL4010_LOW_THR_HI,
+ val);
+ if (ret < 0)
+ return ret;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static bool vcnl4010_is_thr_enabled(struct vcnl4000_data *data)
+{
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(data->client, VCNL4010_INT_CTRL);
+ if (ret < 0)
+ return false;
+
+ return !!(ret & VCNL4010_INT_THR_EN);
+}
+
+static int vcnl4010_read_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir)
+{
+ struct vcnl4000_data *data = iio_priv(indio_dev);
+
+ switch (chan->type) {
+ case IIO_PROXIMITY:
+ return vcnl4010_is_thr_enabled(data);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int vcnl4010_config_threshold(struct iio_dev *indio_dev, bool state)
+{
+ struct vcnl4000_data *data = iio_priv(indio_dev);
+ int ret;
+ int icr;
+ int command;
+
+ if (state) {
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
+ /* Enable periodic measurement of proximity data. */
+ command = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN;
+
+ /*
+ * Enable interrupts on threshold, for proximity data by
+ * default.
+ */
+ icr = VCNL4010_INT_THR_EN;
+ } else {
+ if (!vcnl4010_is_thr_enabled(data))
+ return 0;
+
+ command = 0;
+ icr = 0;
+ }
+
+ ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND,
+ command);
+ if (ret < 0)
+ goto end;
+
+ ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, icr);
+
+end:
+ if (state)
+ iio_device_release_direct_mode(indio_dev);
+
+ return ret;
+}
+
+static int vcnl4010_write_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ int state)
+{
+ switch (chan->type) {
+ case IIO_PROXIMITY:
+ return vcnl4010_config_threshold(indio_dev, state);
+ default:
+ return -EINVAL;
+ }
+}
+
+static ssize_t vcnl4000_read_near_level(struct iio_dev *indio_dev,
+ uintptr_t priv,
+ const struct iio_chan_spec *chan,
+ char *buf)
+{
+ struct vcnl4000_data *data = iio_priv(indio_dev);
+
+ return sprintf(buf, "%u\n", data->near_level);
+}
+
+static const struct iio_chan_spec_ext_info vcnl4000_ext_info[] = {
+ {
+ .name = "nearlevel",
+ .shared = IIO_SEPARATE,
+ .read = vcnl4000_read_near_level,
+ },
+ { /* sentinel */ }
+};
+
+static const struct iio_event_spec vcnl4000_event_spec[] = {
+ {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_RISING,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE),
+ }, {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_FALLING,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE),
+ }, {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_EITHER,
+ .mask_separate = BIT(IIO_EV_INFO_ENABLE),
+ }
+};
+
+static const struct iio_chan_spec vcnl4000_channels[] = {
+ {
+ .type = IIO_LIGHT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ }, {
+ .type = IIO_PROXIMITY,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .ext_info = vcnl4000_ext_info,
+ }
+};
+
+static const struct iio_chan_spec vcnl4010_channels[] = {
+ {
+ .type = IIO_LIGHT,
+ .scan_index = -1,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ }, {
+ .type = IIO_PROXIMITY,
+ .scan_index = 0,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .event_spec = vcnl4000_event_spec,
+ .num_event_specs = ARRAY_SIZE(vcnl4000_event_spec),
+ .ext_info = vcnl4000_ext_info,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_CPU,
+ },
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(1),
+};
+
static const struct iio_info vcnl4000_info = {
.read_raw = vcnl4000_read_raw,
};
+static const struct iio_info vcnl4010_info = {
+ .read_raw = vcnl4010_read_raw,
+ .read_avail = vcnl4010_read_avail,
+ .write_raw = vcnl4010_write_raw,
+ .read_event_value = vcnl4010_read_event,
+ .write_event_value = vcnl4010_write_event,
+ .read_event_config = vcnl4010_read_event_config,
+ .write_event_config = vcnl4010_write_event_config,
+};
+
+static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = {
+ [VCNL4000] = {
+ .prod = "VCNL4000",
+ .init = vcnl4000_init,
+ .measure_light = vcnl4000_measure_light,
+ .measure_proximity = vcnl4000_measure_proximity,
+ .set_power_state = vcnl4000_set_power_state,
+ .channels = vcnl4000_channels,
+ .num_channels = ARRAY_SIZE(vcnl4000_channels),
+ .info = &vcnl4000_info,
+ .irq_support = false,
+ },
+ [VCNL4010] = {
+ .prod = "VCNL4010/4020",
+ .init = vcnl4000_init,
+ .measure_light = vcnl4000_measure_light,
+ .measure_proximity = vcnl4000_measure_proximity,
+ .set_power_state = vcnl4000_set_power_state,
+ .channels = vcnl4010_channels,
+ .num_channels = ARRAY_SIZE(vcnl4010_channels),
+ .info = &vcnl4010_info,
+ .irq_support = true,
+ },
+ [VCNL4040] = {
+ .prod = "VCNL4040",
+ .init = vcnl4200_init,
+ .measure_light = vcnl4200_measure_light,
+ .measure_proximity = vcnl4200_measure_proximity,
+ .set_power_state = vcnl4200_set_power_state,
+ .channels = vcnl4000_channels,
+ .num_channels = ARRAY_SIZE(vcnl4000_channels),
+ .info = &vcnl4000_info,
+ .irq_support = false,
+ },
+ [VCNL4200] = {
+ .prod = "VCNL4200",
+ .init = vcnl4200_init,
+ .measure_light = vcnl4200_measure_light,
+ .measure_proximity = vcnl4200_measure_proximity,
+ .set_power_state = vcnl4200_set_power_state,
+ .channels = vcnl4000_channels,
+ .num_channels = ARRAY_SIZE(vcnl4000_channels),
+ .info = &vcnl4000_info,
+ .irq_support = false,
+ },
+};
+
+static irqreturn_t vcnl4010_irq_thread(int irq, void *p)
+{
+ struct iio_dev *indio_dev = p;
+ struct vcnl4000_data *data = iio_priv(indio_dev);
+ unsigned long isr;
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR);
+ if (ret < 0)
+ goto end;
+
+ isr = ret;
+
+ if (isr & VCNL4010_INT_THR) {
+ if (test_bit(VCNL4010_INT_THR_LOW, &isr)) {
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(
+ IIO_PROXIMITY,
+ 1,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
+ iio_get_time_ns(indio_dev));
+ }
+
+ if (test_bit(VCNL4010_INT_THR_HIGH, &isr)) {
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(
+ IIO_PROXIMITY,
+ 1,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
+ iio_get_time_ns(indio_dev));
+ }
+
+ i2c_smbus_write_byte_data(data->client, VCNL4010_ISR,
+ isr & VCNL4010_INT_THR);
+ }
+
+ if (isr & VCNL4010_INT_DRDY && iio_buffer_enabled(indio_dev))
+ iio_trigger_poll_chained(indio_dev->trig);
+
+end:
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t vcnl4010_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct vcnl4000_data *data = iio_priv(indio_dev);
+ const unsigned long *active_scan_mask = indio_dev->active_scan_mask;
+ u16 buffer[8] = {0}; /* 1x16-bit + ts */
+ bool data_read = false;
+ unsigned long isr;
+ int val = 0;
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR);
+ if (ret < 0)
+ goto end;
+
+ isr = ret;
+
+ if (test_bit(0, active_scan_mask)) {
+ if (test_bit(VCNL4010_INT_PROXIMITY, &isr)) {
+ ret = vcnl4000_read_data(data,
+ VCNL4000_PS_RESULT_HI,
+ &val);
+ if (ret < 0)
+ goto end;
+
+ buffer[0] = val;
+ data_read = true;
+ }
+ }
+
+ ret = i2c_smbus_write_byte_data(data->client, VCNL4010_ISR,
+ isr & VCNL4010_INT_DRDY);
+ if (ret < 0)
+ goto end;
+
+ if (!data_read)
+ goto end;
+
+ iio_push_to_buffers_with_timestamp(indio_dev, buffer,
+ iio_get_time_ns(indio_dev));
+
+end:
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
+static int vcnl4010_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct vcnl4000_data *data = iio_priv(indio_dev);
+ int ret;
+ int cmd;
+
+ /* Do not enable the buffer if we are already capturing events. */
+ 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)
+ return ret;
+
+ cmd = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN;
+ 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 = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, 0);
+ if (ret < 0)
+ return ret;
+
+ return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 0);
+}
+
+static const struct iio_buffer_setup_ops vcnl4010_buffer_ops = {
+ .postenable = &vcnl4010_buffer_postenable,
+ .predisable = &vcnl4010_buffer_predisable,
+};
+
+static const struct iio_trigger_ops vcnl4010_trigger_ops = {
+ .validate_device = iio_trigger_validate_own_device,
+};
+
+static int vcnl4010_probe_trigger(struct iio_dev *indio_dev)
+{
+ struct vcnl4000_data *data = iio_priv(indio_dev);
+ struct i2c_client *client = data->client;
+ struct iio_trigger *trigger;
+
+ trigger = devm_iio_trigger_alloc(&client->dev, "%s-dev%d",
+ indio_dev->name, indio_dev->id);
+ if (!trigger)
+ return -ENOMEM;
+
+ trigger->dev.parent = &client->dev;
+ trigger->ops = &vcnl4010_trigger_ops;
+ iio_trigger_set_drvdata(trigger, indio_dev);
+
+ return devm_iio_trigger_register(&client->dev, trigger);
+}
+
static int vcnl4000_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -440,13 +1033,43 @@ static int vcnl4000_probe(struct i2c_client *client,
dev_dbg(&client->dev, "%s Ambient light/proximity sensor, Rev: %02x\n",
data->chip_spec->prod, data->rev);
- indio_dev->dev.parent = &client->dev;
- indio_dev->info = &vcnl4000_info;
- indio_dev->channels = vcnl4000_channels;
- indio_dev->num_channels = ARRAY_SIZE(vcnl4000_channels);
+ if (device_property_read_u32(&client->dev, "proximity-near-level",
+ &data->near_level))
+ data->near_level = 0;
+
+ indio_dev->info = data->chip_spec->info;
+ indio_dev->channels = data->chip_spec->channels;
+ indio_dev->num_channels = data->chip_spec->num_channels;
indio_dev->name = VCNL4000_DRV_NAME;
indio_dev->modes = INDIO_DIRECT_MODE;
+ if (client->irq && data->chip_spec->irq_support) {
+ ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,
+ NULL,
+ vcnl4010_trigger_handler,
+ &vcnl4010_buffer_ops);
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "unable to setup iio triggered buffer\n");
+ return ret;
+ }
+
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, vcnl4010_irq_thread,
+ IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT,
+ "vcnl4010_irq",
+ indio_dev);
+ if (ret < 0) {
+ dev_err(&client->dev, "irq request failed\n");
+ return ret;
+ }
+
+ ret = vcnl4010_probe_trigger(indio_dev);
+ if (ret < 0)
+ return ret;
+ }
+
ret = pm_runtime_set_active(&client->dev);
if (ret < 0)
goto fail_poweroff;
@@ -540,5 +1163,6 @@ static struct i2c_driver vcnl4000_driver = {
module_i2c_driver(vcnl4000_driver);
MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
+MODULE_AUTHOR("Mathieu Othacehe <m.othacehe@gmail.com>");
MODULE_DESCRIPTION("Vishay VCNL4000 proximity/ambient light sensor driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/iio/light/vcnl4035.c b/drivers/iio/light/vcnl4035.c
index cca4db312bd3..765c44adac57 100644
--- a/drivers/iio/light/vcnl4035.c
+++ b/drivers/iio/light/vcnl4035.c
@@ -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;
diff --git a/drivers/iio/light/veml6030.c b/drivers/iio/light/veml6030.c
index aa25b87fca8f..de85c9b30be1 100644
--- a/drivers/iio/light/veml6030.c
+++ b/drivers/iio/light/veml6030.c
@@ -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);
diff --git a/drivers/iio/light/veml6070.c b/drivers/iio/light/veml6070.c
index 0be553ad5989..1e55e09a8d16 100644
--- a/drivers/iio/light/veml6070.c
+++ b/drivers/iio/light/veml6070.c
@@ -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);
diff --git a/drivers/iio/light/vl6180.c b/drivers/iio/light/vl6180.c
index d9533a76b8f6..4775bd785e50 100644
--- a/drivers/iio/light/vl6180.c
+++ b/drivers/iio/light/vl6180.c
@@ -16,6 +16,7 @@
*/
#include <linux/module.h>
+#include <linux/mod_devicetable.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/err.h>
@@ -508,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);
@@ -537,7 +537,7 @@ MODULE_DEVICE_TABLE(i2c, vl6180_id);
static struct i2c_driver vl6180_driver = {
.driver = {
.name = VL6180_DRV_NAME,
- .of_match_table = of_match_ptr(vl6180_of_match),
+ .of_match_table = vl6180_of_match,
},
.probe = vl6180_probe,
.id_table = vl6180_id,
diff --git a/drivers/iio/light/zopt2201.c b/drivers/iio/light/zopt2201.c
index 5f54f39e7a4c..e0bc9df9c88b 100644
--- a/drivers/iio/light/zopt2201.c
+++ b/drivers/iio/light/zopt2201.c
@@ -19,6 +19,8 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <asm/unaligned.h>
+
#define ZOPT2201_DRV_NAME "zopt2201"
/* Registers */
@@ -219,7 +221,7 @@ static int zopt2201_read(struct zopt2201_data *data, u8 reg)
goto fail;
mutex_unlock(&data->lock);
- return (buf[2] << 16) | (buf[1] << 8) | buf[0];
+ return get_unaligned_le24(&buf[0]);
fail:
mutex_unlock(&data->lock);
@@ -525,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);
diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c
index d32996702110..cbb44e401c0a 100644
--- a/drivers/iio/magnetometer/ak8974.c
+++ b/drivers/iio/magnetometer/ak8974.c
@@ -49,6 +49,7 @@
#define AK8974_WHOAMI_VALUE_AMI306 0x46
#define AK8974_WHOAMI_VALUE_AMI305 0x47
#define AK8974_WHOAMI_VALUE_AK8974 0x48
+#define AK8974_WHOAMI_VALUE_HSCDTD008A 0x49
#define AK8974_DATA_X 0x10
#define AK8974_DATA_Y 0x12
@@ -140,6 +141,12 @@
#define AK8974_INT_CTRL_PULSE BIT(1) /* 0 = latched; 1 = pulse (50 usec) */
#define AK8974_INT_CTRL_RESDEF (AK8974_INT_CTRL_XYZEN | AK8974_INT_CTRL_POL)
+/* HSCDTD008A-specific control register */
+#define HSCDTD008A_CTRL4 0x1E
+#define HSCDTD008A_CTRL4_MMD BIT(7) /* must be set to 1 */
+#define HSCDTD008A_CTRL4_RANGE BIT(4) /* 0 = 14-bit output; 1 = 15-bit output */
+#define HSCDTD008A_CTRL4_RESDEF (HSCDTD008A_CTRL4_MMD | HSCDTD008A_CTRL4_RANGE)
+
/* The AMI305 has elaborate FW version and serial number registers */
#define AMI305_VER 0xE8
#define AMI305_SN 0xEA
@@ -173,6 +180,7 @@
* @drdy_irq: uses the DRDY IRQ line
* @drdy_complete: completion for DRDY
* @drdy_active_low: the DRDY IRQ is active low
+ * @scan: timestamps
*/
struct ak8974 {
struct i2c_client *i2c;
@@ -185,6 +193,11 @@ struct ak8974 {
bool drdy_irq;
struct completion drdy_complete;
bool drdy_active_low;
+ /* Ensure timestamp is naturally aligned */
+ struct {
+ __le16 channels[3];
+ s64 ts __aligned(8);
+ } scan;
};
static const char ak8974_reg_avdd[] = "avdd";
@@ -241,10 +254,17 @@ static int ak8974_reset(struct ak8974 *ak8974)
ret = regmap_write(ak8974->map, AK8974_CTRL3, AK8974_CTRL3_RESDEF);
if (ret)
return ret;
- ret = regmap_write(ak8974->map, AK8974_INT_CTRL,
- AK8974_INT_CTRL_RESDEF);
- if (ret)
- return ret;
+ if (ak8974->variant != AK8974_WHOAMI_VALUE_HSCDTD008A) {
+ ret = regmap_write(ak8974->map, AK8974_INT_CTRL,
+ AK8974_INT_CTRL_RESDEF);
+ if (ret)
+ return ret;
+ } else {
+ ret = regmap_write(ak8974->map, HSCDTD008A_CTRL4,
+ HSCDTD008A_CTRL4_RESDEF);
+ if (ret)
+ return ret;
+ }
/* After reset, power off is default state */
return ak8974_set_power(ak8974, AK8974_PWR_OFF);
@@ -267,6 +287,8 @@ static int ak8974_configure(struct ak8974 *ak8974)
if (ret)
return ret;
}
+ if (ak8974->variant == AK8974_WHOAMI_VALUE_HSCDTD008A)
+ return 0;
ret = regmap_write(ak8974->map, AK8974_INT_CTRL, AK8974_INT_CTRL_POL);
if (ret)
return ret;
@@ -477,7 +499,7 @@ static int ak8974_detect(struct ak8974 *ak8974)
switch (whoami) {
case AK8974_WHOAMI_VALUE_AMI306:
name = "ami306";
- /* fall-through */
+ fallthrough;
case AK8974_WHOAMI_VALUE_AMI305:
ret = regmap_read(ak8974->map, AMI305_VER, &fw);
if (ret)
@@ -495,6 +517,10 @@ static int ak8974_detect(struct ak8974 *ak8974)
name = "ak8974";
dev_info(&ak8974->i2c->dev, "detected AK8974\n");
break;
+ case AK8974_WHOAMI_VALUE_HSCDTD008A:
+ name = "hscdtd008a";
+ dev_info(&ak8974->i2c->dev, "detected hscdtd008a\n");
+ break;
default:
dev_err(&ak8974->i2c->dev, "unsupported device (%02x) ",
whoami);
@@ -534,54 +560,109 @@ static int ak8974_detect(struct ak8974 *ak8974)
return 0;
}
+static int ak8974_measure_channel(struct ak8974 *ak8974, unsigned long address,
+ int *val)
+{
+ __le16 hw_values[3];
+ int ret;
+
+ pm_runtime_get_sync(&ak8974->i2c->dev);
+ mutex_lock(&ak8974->lock);
+
+ /*
+ * We read all axes and discard all but one, for optimized
+ * reading, use the triggered buffer.
+ */
+ ret = ak8974_trigmeas(ak8974);
+ if (ret)
+ goto out_unlock;
+ ret = ak8974_getresult(ak8974, hw_values);
+ if (ret)
+ goto out_unlock;
+ /*
+ * This explicit cast to (s16) is necessary as the measurement
+ * is done in 2's complement with positive and negative values.
+ * The follwing assignment to *val will then convert the signed
+ * s16 value to a signed int value.
+ */
+ *val = (s16)le16_to_cpu(hw_values[address]);
+out_unlock:
+ mutex_unlock(&ak8974->lock);
+ pm_runtime_mark_last_busy(&ak8974->i2c->dev);
+ pm_runtime_put_autosuspend(&ak8974->i2c->dev);
+
+ return ret;
+}
+
static int ak8974_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2,
long mask)
{
struct ak8974 *ak8974 = iio_priv(indio_dev);
- __le16 hw_values[3];
- int ret = -EINVAL;
-
- pm_runtime_get_sync(&ak8974->i2c->dev);
- mutex_lock(&ak8974->lock);
+ int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
if (chan->address > 2) {
dev_err(&ak8974->i2c->dev, "faulty channel address\n");
- ret = -EIO;
- goto out_unlock;
+ return -EIO;
}
- ret = ak8974_trigmeas(ak8974);
+ ret = ak8974_measure_channel(ak8974, chan->address, val);
if (ret)
- goto out_unlock;
- ret = ak8974_getresult(ak8974, hw_values);
- if (ret)
- goto out_unlock;
-
- /*
- * We read all axes and discard all but one, for optimized
- * reading, use the triggered buffer.
- */
- *val = (s16)le16_to_cpu(hw_values[chan->address]);
-
- ret = IIO_VAL_INT;
+ return ret;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ switch (ak8974->variant) {
+ case AK8974_WHOAMI_VALUE_AMI306:
+ case AK8974_WHOAMI_VALUE_AMI305:
+ /*
+ * The datasheet for AMI305 and AMI306, page 6
+ * specifies the range of the sensor to be
+ * +/- 12 Gauss.
+ */
+ *val = 12;
+ /*
+ * 12 bits are used, +/- 2^11
+ * [ -2048 .. 2047 ] (manual page 20)
+ * [ 0xf800 .. 0x07ff ]
+ */
+ *val2 = 11;
+ return IIO_VAL_FRACTIONAL_LOG2;
+ case AK8974_WHOAMI_VALUE_HSCDTD008A:
+ /*
+ * The datasheet for HSCDTF008A, page 3 specifies the
+ * range of the sensor as +/- 2.4 mT per axis, which
+ * corresponds to +/- 2400 uT = +/- 24 Gauss.
+ */
+ *val = 24;
+ /*
+ * 15 bits are used (set up in CTRL4), +/- 2^14
+ * [ -16384 .. 16383 ] (manual page 24)
+ * [ 0xc000 .. 0x3fff ]
+ */
+ *val2 = 14;
+ return IIO_VAL_FRACTIONAL_LOG2;
+ default:
+ /* GUESSING +/- 12 Gauss */
+ *val = 12;
+ /* GUESSING 12 bits ADC +/- 2^11 */
+ *val2 = 11;
+ return IIO_VAL_FRACTIONAL_LOG2;
+ }
+ break;
+ default:
+ /* Unknown request */
+ break;
}
- out_unlock:
- mutex_unlock(&ak8974->lock);
- pm_runtime_mark_last_busy(&ak8974->i2c->dev);
- pm_runtime_put_autosuspend(&ak8974->i2c->dev);
-
- return ret;
+ return -EINVAL;
}
static void ak8974_fill_buffer(struct iio_dev *indio_dev)
{
struct ak8974 *ak8974 = iio_priv(indio_dev);
int ret;
- __le16 hw_values[8]; /* Three axes + 64bit padding */
pm_runtime_get_sync(&ak8974->i2c->dev);
mutex_lock(&ak8974->lock);
@@ -591,13 +672,13 @@ static void ak8974_fill_buffer(struct iio_dev *indio_dev)
dev_err(&ak8974->i2c->dev, "error triggering measure\n");
goto out_unlock;
}
- ret = ak8974_getresult(ak8974, hw_values);
+ ret = ak8974_getresult(ak8974, ak8974->scan.channels);
if (ret) {
dev_err(&ak8974->i2c->dev, "error getting measures\n");
goto out_unlock;
}
- iio_push_to_buffers_with_timestamp(indio_dev, hw_values,
+ iio_push_to_buffers_with_timestamp(indio_dev, &ak8974->scan,
iio_get_time_ns(indio_dev));
out_unlock:
@@ -631,27 +712,44 @@ static const struct iio_chan_spec_ext_info ak8974_ext_info[] = {
{ },
};
-#define AK8974_AXIS_CHANNEL(axis, index) \
+#define AK8974_AXIS_CHANNEL(axis, index, bits) \
{ \
.type = IIO_MAGN, \
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
.ext_info = ak8974_ext_info, \
.address = index, \
.scan_index = index, \
.scan_type = { \
.sign = 's', \
- .realbits = 16, \
+ .realbits = bits, \
.storagebits = 16, \
.endianness = IIO_LE \
}, \
}
-static const struct iio_chan_spec ak8974_channels[] = {
- AK8974_AXIS_CHANNEL(X, 0),
- AK8974_AXIS_CHANNEL(Y, 1),
- AK8974_AXIS_CHANNEL(Z, 2),
+/*
+ * We have no datasheet for the AK8974 but we guess that its
+ * ADC is 12 bits. The AMI305 and AMI306 certainly has 12bit
+ * ADC.
+ */
+static const struct iio_chan_spec ak8974_12_bits_channels[] = {
+ AK8974_AXIS_CHANNEL(X, 0, 12),
+ AK8974_AXIS_CHANNEL(Y, 1, 12),
+ AK8974_AXIS_CHANNEL(Z, 2, 12),
+ IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+/*
+ * The HSCDTD008A has 15 bits resolution the way we set it up
+ * in CTRL4.
+ */
+static const struct iio_chan_spec ak8974_15_bits_channels[] = {
+ AK8974_AXIS_CHANNEL(X, 0, 15),
+ AK8974_AXIS_CHANNEL(Y, 1, 15),
+ AK8974_AXIS_CHANNEL(Z, 2, 15),
IIO_CHAN_SOFT_TIMESTAMP(3),
};
@@ -674,18 +772,18 @@ static bool ak8974_writeable_reg(struct device *dev, unsigned int reg)
case AK8974_INT_CTRL:
case AK8974_INT_THRES:
case AK8974_INT_THRES + 1:
+ return true;
case AK8974_PRESET:
case AK8974_PRESET + 1:
- return true;
+ return ak8974->variant != AK8974_WHOAMI_VALUE_HSCDTD008A;
case AK8974_OFFSET_X:
case AK8974_OFFSET_X + 1:
case AK8974_OFFSET_Y:
case AK8974_OFFSET_Y + 1:
case AK8974_OFFSET_Z:
case AK8974_OFFSET_Z + 1:
- if (ak8974->variant == AK8974_WHOAMI_VALUE_AK8974)
- return true;
- return false;
+ return ak8974->variant == AK8974_WHOAMI_VALUE_AK8974 ||
+ ak8974->variant == AK8974_WHOAMI_VALUE_HSCDTD008A;
case AMI305_OFFSET_X:
case AMI305_OFFSET_X + 1:
case AMI305_OFFSET_Y:
@@ -746,7 +844,12 @@ static int ak8974_probe(struct i2c_client *i2c,
ARRAY_SIZE(ak8974->regs),
ak8974->regs);
if (ret < 0) {
- dev_err(&i2c->dev, "cannot get regulators\n");
+ if (ret != -EPROBE_DEFER)
+ dev_err(&i2c->dev, "cannot get regulators: %d\n", ret);
+ else
+ dev_dbg(&i2c->dev,
+ "regulators unavailable, deferring probe\n");
+
return ret;
}
@@ -764,19 +867,21 @@ static int ak8974_probe(struct i2c_client *i2c,
ak8974->map = devm_regmap_init_i2c(i2c, &ak8974_regmap_config);
if (IS_ERR(ak8974->map)) {
dev_err(&i2c->dev, "failed to allocate register map\n");
+ pm_runtime_put_noidle(&i2c->dev);
+ pm_runtime_disable(&i2c->dev);
return PTR_ERR(ak8974->map);
}
ret = ak8974_set_power(ak8974, AK8974_PWR_ON);
if (ret) {
dev_err(&i2c->dev, "could not power on\n");
- goto power_off;
+ goto disable_pm;
}
ret = ak8974_detect(ak8974);
if (ret) {
dev_err(&i2c->dev, "neither AK8974 nor AMI30x found\n");
- goto power_off;
+ goto disable_pm;
}
ret = ak8974_selftest(ak8974);
@@ -786,17 +891,24 @@ static int ak8974_probe(struct i2c_client *i2c,
ret = ak8974_reset(ak8974);
if (ret) {
dev_err(&i2c->dev, "AK8974 reset failed\n");
- goto power_off;
+ goto disable_pm;
}
- pm_runtime_set_autosuspend_delay(&i2c->dev,
- AK8974_AUTOSUSPEND_DELAY);
- pm_runtime_use_autosuspend(&i2c->dev);
- pm_runtime_put(&i2c->dev);
-
- indio_dev->dev.parent = &i2c->dev;
- indio_dev->channels = ak8974_channels;
- indio_dev->num_channels = ARRAY_SIZE(ak8974_channels);
+ switch (ak8974->variant) {
+ case AK8974_WHOAMI_VALUE_AMI306:
+ case AK8974_WHOAMI_VALUE_AMI305:
+ indio_dev->channels = ak8974_12_bits_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ak8974_12_bits_channels);
+ break;
+ case AK8974_WHOAMI_VALUE_HSCDTD008A:
+ indio_dev->channels = ak8974_15_bits_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ak8974_15_bits_channels);
+ break;
+ default:
+ indio_dev->channels = ak8974_12_bits_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ak8974_12_bits_channels);
+ break;
+ }
indio_dev->info = &ak8974_info;
indio_dev->available_scan_masks = ak8974_scan_masks;
indio_dev->modes = INDIO_DIRECT_MODE;
@@ -846,6 +958,11 @@ no_irq:
goto cleanup_buffer;
}
+ pm_runtime_set_autosuspend_delay(&i2c->dev,
+ AK8974_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(&i2c->dev);
+ pm_runtime_put(&i2c->dev);
+
return 0;
cleanup_buffer:
@@ -854,7 +971,6 @@ disable_pm:
pm_runtime_put_noidle(&i2c->dev);
pm_runtime_disable(&i2c->dev);
ak8974_set_power(ak8974, AK8974_PWR_OFF);
-power_off:
regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs);
return ret;
@@ -926,12 +1042,14 @@ static const struct i2c_device_id ak8974_id[] = {
{"ami305", 0 },
{"ami306", 0 },
{"ak8974", 0 },
+ {"hscdtd008a", 0 },
{}
};
MODULE_DEVICE_TABLE(i2c, ak8974_id);
static const struct of_device_id ak8974_of_match[] = {
{ .compatible = "asahi-kasei,ak8974", },
+ { .compatible = "alps,hscdtd008a", },
{}
};
MODULE_DEVICE_TABLE(of, ak8974_of_match);
diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c
index 3c881541ae72..623766ff800b 100644
--- a/drivers/iio/magnetometer/ak8975.c
+++ b/drivers/iio/magnetometer/ak8975.c
@@ -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;
@@ -365,6 +366,12 @@ struct ak8975_data {
struct iio_mount_matrix orientation;
struct regulator *vdd;
struct regulator *vid;
+
+ /* Ensure natural alignment of timestamp */
+ struct {
+ s16 channels[3];
+ s64 ts __aligned(8);
+ } scan;
};
/* Enable attached power regulator if any. */
@@ -384,10 +391,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 +406,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);
}
@@ -787,7 +799,6 @@ static void ak8975_fill_buffer(struct iio_dev *indio_dev)
const struct i2c_client *client = data->client;
const struct ak_def *def = data->def;
int ret;
- s16 buff[8]; /* 3 x 16 bits axis values + 1 aligned 64 bits timestamp */
__le16 fval[3];
mutex_lock(&data->lock);
@@ -810,12 +821,13 @@ static void ak8975_fill_buffer(struct iio_dev *indio_dev)
mutex_unlock(&data->lock);
/* Clamp to valid range. */
- buff[0] = clamp_t(s16, le16_to_cpu(fval[0]), -def->range, def->range);
- buff[1] = clamp_t(s16, le16_to_cpu(fval[1]), -def->range, def->range);
- buff[2] = clamp_t(s16, le16_to_cpu(fval[2]), -def->range, def->range);
+ data->scan.channels[0] = clamp_t(s16, le16_to_cpu(fval[0]), -def->range, def->range);
+ data->scan.channels[1] = clamp_t(s16, le16_to_cpu(fval[1]), -def->range, def->range);
+ data->scan.channels[2] = clamp_t(s16, le16_to_cpu(fval[2]), -def->range, def->range);
- iio_push_to_buffers_with_timestamp(indio_dev, buff,
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
iio_get_time_ns(indio_dev));
+
return;
unlock:
@@ -839,6 +851,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 +869,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 +889,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 +946,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;
diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c
index d4de16750b10..fc6840f9c1fa 100644
--- a/drivers/iio/magnetometer/bmc150_magn.c
+++ b/drivers/iio/magnetometer/bmc150_magn.c
@@ -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;
diff --git a/drivers/iio/magnetometer/bmc150_magn_i2c.c b/drivers/iio/magnetometer/bmc150_magn_i2c.c
index fb45b63c56e4..876e96005e33 100644
--- a/drivers/iio/magnetometer/bmc150_magn_i2c.c
+++ b/drivers/iio/magnetometer/bmc150_magn_i2c.c
@@ -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);
diff --git a/drivers/iio/magnetometer/bmc150_magn_spi.c b/drivers/iio/magnetometer/bmc150_magn_spi.c
index ed9be0490d77..c6ed3ea8460a 100644
--- a/drivers/iio/magnetometer/bmc150_magn_spi.c
+++ b/drivers/iio/magnetometer/bmc150_magn_spi.c
@@ -22,8 +22,8 @@ static int bmc150_magn_spi_probe(struct spi_device *spi)
regmap = devm_regmap_init_spi(spi, &bmc150_magn_regmap_config);
if (IS_ERR(regmap)) {
- dev_err(&spi->dev, "Failed to register spi regmap %d\n",
- (int)PTR_ERR(regmap));
+ dev_err(&spi->dev, "Failed to register spi regmap: %pe\n",
+ regmap);
return PTR_ERR(regmap);
}
return bmc150_magn_probe(&spi->dev, regmap, spi->irq, id->name);
diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
index 25e60b233e08..97642ebd9168 100644
--- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
+++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
@@ -14,8 +14,6 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
-#include <linux/iio/trigger_consumer.h>
-#include <linux/iio/triggered_buffer.h>
#include "../common/hid-sensors/hid-sensor-trigger.h"
enum magn_3d_channel {
@@ -514,23 +512,17 @@ 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;
- ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
- NULL, NULL);
- if (ret) {
- dev_err(&pdev->dev, "failed to initialize trigger buffer\n");
- return ret;
- }
atomic_set(&magn_state->magn_flux_attributes.data_ready, 0);
+
ret = hid_sensor_setup_trigger(indio_dev, name,
&magn_state->magn_flux_attributes);
if (ret < 0) {
dev_err(&pdev->dev, "trigger setup failed\n");
- goto error_unreg_buffer_funcs;
+ return ret;
}
ret = iio_device_register(indio_dev);
@@ -554,9 +546,7 @@ static int hid_magn_3d_probe(struct platform_device *pdev)
error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
- hid_sensor_remove_trigger(&magn_state->magn_flux_attributes);
-error_unreg_buffer_funcs:
- iio_triggered_buffer_cleanup(indio_dev);
+ hid_sensor_remove_trigger(indio_dev, &magn_state->magn_flux_attributes);
return ret;
}
@@ -569,8 +559,7 @@ static int hid_magn_3d_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_COMPASS_3D);
iio_device_unregister(indio_dev);
- hid_sensor_remove_trigger(&magn_state->magn_flux_attributes);
- iio_triggered_buffer_cleanup(indio_dev);
+ hid_sensor_remove_trigger(indio_dev, &magn_state->magn_flux_attributes);
return 0;
}
diff --git a/drivers/iio/magnetometer/hmc5843.h b/drivers/iio/magnetometer/hmc5843.h
index b0dee87a8b20..3f6c0b662941 100644
--- a/drivers/iio/magnetometer/hmc5843.h
+++ b/drivers/iio/magnetometer/hmc5843.h
@@ -52,9 +52,9 @@ int hmc5843_common_suspend(struct device *dev);
int hmc5843_common_resume(struct device *dev);
#ifdef CONFIG_PM_SLEEP
-static SIMPLE_DEV_PM_OPS(hmc5843_pm_ops,
- hmc5843_common_suspend,
- hmc5843_common_resume);
+static __maybe_unused SIMPLE_DEV_PM_OPS(hmc5843_pm_ops,
+ hmc5843_common_suspend,
+ hmc5843_common_resume);
#define HMC5843_PM_OPS (&hmc5843_pm_ops)
#else
#define HMC5843_PM_OPS NULL
diff --git a/drivers/iio/magnetometer/hmc5843_core.c b/drivers/iio/magnetometer/hmc5843_core.c
index c44a4292da92..1474ba63babe 100644
--- a/drivers/iio/magnetometer/hmc5843_core.c
+++ b/drivers/iio/magnetometer/hmc5843_core.c
@@ -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;
diff --git a/drivers/iio/magnetometer/mag3110.c b/drivers/iio/magnetometer/mag3110.c
index fb16cfdd6fa6..4d305a21c379 100644
--- a/drivers/iio/magnetometer/mag3110.c
+++ b/drivers/iio/magnetometer/mag3110.c
@@ -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);
diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c
index 425cdd07b4e5..65f3d1ed0d59 100644
--- a/drivers/iio/magnetometer/mmc35240.c
+++ b/drivers/iio/magnetometer/mmc35240.c
@@ -239,7 +239,7 @@ static int mmc35240_init(struct mmc35240_data *data)
return ret;
ret = regmap_bulk_read(data->regmap, MMC35240_OTP_START_ADDR,
- (u8 *)otp_data, sizeof(otp_data));
+ otp_data, sizeof(otp_data));
if (ret < 0)
return ret;
@@ -295,13 +295,13 @@ static int mmc35240_read_measurement(struct mmc35240_data *data, __le16 buf[3])
if (ret < 0)
return ret;
- return regmap_bulk_read(data->regmap, MMC35240_REG_XOUT_L, (u8 *)buf,
+ return regmap_bulk_read(data->regmap, MMC35240_REG_XOUT_L, buf,
3 * sizeof(__le16));
}
/**
* mmc35240_raw_to_mgauss - convert raw readings to milli gauss. Also apply
- compensation for output value.
+ * compensation for output value.
*
* @data: device private data
* @index: axis index for which we want the conversion
@@ -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;
diff --git a/drivers/iio/magnetometer/rm3100-core.c b/drivers/iio/magnetometer/rm3100-core.c
index 7c20918d8108..7242897a05e9 100644
--- a/drivers/iio/magnetometer/rm3100-core.c
+++ b/drivers/iio/magnetometer/rm3100-core.c
@@ -22,6 +22,8 @@
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.h>
+#include <asm/unaligned.h>
+
#include "rm3100.h"
/* Cycle Count Registers. */
@@ -223,8 +225,7 @@ static int rm3100_read_mag(struct rm3100_data *data, int idx, int *val)
goto unlock_return;
mutex_unlock(&data->lock);
- *val = sign_extend32((buffer[0] << 16) | (buffer[1] << 8) | buffer[2],
- 23);
+ *val = sign_extend32(get_unaligned_be24(&buffer[0]), 23);
return IIO_VAL_INT;
@@ -462,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,
};
@@ -548,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;
diff --git a/drivers/iio/magnetometer/st_magn_buffer.c b/drivers/iio/magnetometer/st_magn_buffer.c
index bb425c167a96..4917721fa2e5 100644
--- a/drivers/iio/magnetometer/st_magn_buffer.c
+++ b/drivers/iio/magnetometer/st_magn_buffer.c
@@ -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 = {
diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c
index e68184a93a6d..79de721e6015 100644
--- a/drivers/iio/magnetometer/st_magn_core.c
+++ b/drivers/iio/magnetometer/st_magn_core.c
@@ -506,8 +506,7 @@ int st_magn_common_probe(struct iio_dev *indio_dev)
indio_dev->channels = mdata->sensor_settings->ch;
indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
- mdata->current_fullscale = (struct st_sensor_fullscale_avl *)
- &mdata->sensor_settings->fs.fs_avl[0];
+ mdata->current_fullscale = &mdata->sensor_settings->fs.fs_avl[0];
mdata->odr = mdata->sensor_settings->odr.odr_avl[0].hz;
err = st_sensors_init_sensor(indio_dev, NULL);
diff --git a/drivers/iio/multiplexer/iio-mux.c b/drivers/iio/multiplexer/iio-mux.c
index 0422ef57914c..6910218fdb00 100644
--- a/drivers/iio/multiplexer/iio-mux.c
+++ b/drivers/iio/multiplexer/iio-mux.c
@@ -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;
diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c
index 00af68764cda..ae132a93bcae 100644
--- a/drivers/iio/orientation/hid-sensor-incl-3d.c
+++ b/drivers/iio/orientation/hid-sensor-incl-3d.c
@@ -15,8 +15,6 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
-#include <linux/iio/trigger_consumer.h>
-#include <linux/iio/triggered_buffer.h>
#include "../common/hid-sensors/hid-sensor-trigger.h"
enum incl_3d_channel {
@@ -341,23 +339,17 @@ 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;
- ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
- NULL, NULL);
- if (ret) {
- dev_err(&pdev->dev, "failed to initialize trigger buffer\n");
- goto error_free_dev_mem;
- }
atomic_set(&incl_state->common_attributes.data_ready, 0);
+
ret = hid_sensor_setup_trigger(indio_dev, name,
&incl_state->common_attributes);
if (ret) {
dev_err(&pdev->dev, "trigger setup failed\n");
- goto error_unreg_buffer_funcs;
+ goto error_free_dev_mem;
}
ret = iio_device_register(indio_dev);
@@ -382,9 +374,7 @@ static int hid_incl_3d_probe(struct platform_device *pdev)
error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
- hid_sensor_remove_trigger(&incl_state->common_attributes);
-error_unreg_buffer_funcs:
- iio_triggered_buffer_cleanup(indio_dev);
+ hid_sensor_remove_trigger(indio_dev, &incl_state->common_attributes);
error_free_dev_mem:
kfree(indio_dev->channels);
return ret;
@@ -399,8 +389,7 @@ static int hid_incl_3d_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_INCLINOMETER_3D);
iio_device_unregister(indio_dev);
- hid_sensor_remove_trigger(&incl_state->common_attributes);
- iio_triggered_buffer_cleanup(indio_dev);
+ hid_sensor_remove_trigger(indio_dev, &incl_state->common_attributes);
kfree(indio_dev->channels);
return 0;
diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c
index 64ae7d04a200..23bc61a7f018 100644
--- a/drivers/iio/orientation/hid-sensor-rotation.c
+++ b/drivers/iio/orientation/hid-sensor-rotation.c
@@ -14,8 +14,6 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
-#include <linux/iio/trigger_consumer.h>
-#include <linux/iio/triggered_buffer.h>
#include "../common/hid-sensors/hid-sensor-trigger.h"
struct dev_rot_state {
@@ -283,23 +281,17 @@ 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;
- ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
- NULL, NULL);
- if (ret) {
- dev_err(&pdev->dev, "failed to initialize trigger buffer\n");
- return ret;
- }
atomic_set(&rot_state->common_attributes.data_ready, 0);
+
ret = hid_sensor_setup_trigger(indio_dev, name,
&rot_state->common_attributes);
if (ret) {
dev_err(&pdev->dev, "trigger setup failed\n");
- goto error_unreg_buffer_funcs;
+ return ret;
}
ret = iio_device_register(indio_dev);
@@ -323,9 +315,7 @@ static int hid_dev_rot_probe(struct platform_device *pdev)
error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
- hid_sensor_remove_trigger(&rot_state->common_attributes);
-error_unreg_buffer_funcs:
- iio_triggered_buffer_cleanup(indio_dev);
+ hid_sensor_remove_trigger(indio_dev, &rot_state->common_attributes);
return ret;
}
@@ -338,8 +328,7 @@ static int hid_dev_rot_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, hsdev->usage);
iio_device_unregister(indio_dev);
- hid_sensor_remove_trigger(&rot_state->common_attributes);
- iio_triggered_buffer_cleanup(indio_dev);
+ hid_sensor_remove_trigger(indio_dev, &rot_state->common_attributes);
return 0;
}
diff --git a/drivers/iio/position/iqs624-pos.c b/drivers/iio/position/iqs624-pos.c
index 77096c31c2ba..4d7452314209 100644
--- a/drivers/iio/position/iqs624-pos.c
+++ b/drivers/iio/position/iqs624-pos.c
@@ -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;
diff --git a/drivers/iio/potentiometer/ad5272.c b/drivers/iio/potentiometer/ad5272.c
index 154f9a5da8bc..933afcf7e925 100644
--- a/drivers/iio/potentiometer/ad5272.c
+++ b/drivers/iio/potentiometer/ad5272.c
@@ -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;
diff --git a/drivers/iio/potentiometer/ds1803.c b/drivers/iio/potentiometer/ds1803.c
index d0de78232a93..5c061ab8f46c 100644
--- a/drivers/iio/potentiometer/ds1803.c
+++ b/drivers/iio/potentiometer/ds1803.c
@@ -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);
diff --git a/drivers/iio/potentiometer/max5432.c b/drivers/iio/potentiometer/max5432.c
index 641b1821fdf6..280de9c54471 100644
--- a/drivers/iio/potentiometer/max5432.c
+++ b/drivers/iio/potentiometer/max5432.c
@@ -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);
diff --git a/drivers/iio/potentiometer/max5481.c b/drivers/iio/potentiometer/max5481.c
index 732375b6d131..5f5988189796 100644
--- a/drivers/iio/potentiometer/max5481.c
+++ b/drivers/iio/potentiometer/max5481.c
@@ -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 */
diff --git a/drivers/iio/potentiometer/max5487.c b/drivers/iio/potentiometer/max5487.c
index 68ff806d4668..7ec51976ec99 100644
--- a/drivers/iio/potentiometer/max5487.c
+++ b/drivers/iio/potentiometer/max5487.c
@@ -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);
diff --git a/drivers/iio/potentiometer/mcp4018.c b/drivers/iio/potentiometer/mcp4018.c
index 62151b2a2b12..fd0579ad3c83 100644
--- a/drivers/iio/potentiometer/mcp4018.c
+++ b/drivers/iio/potentiometer/mcp4018.c
@@ -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;
diff --git a/drivers/iio/potentiometer/mcp41010.c b/drivers/iio/potentiometer/mcp41010.c
index 2368b39debf5..79ccac6d4be0 100644
--- a/drivers/iio/potentiometer/mcp41010.c
+++ b/drivers/iio/potentiometer/mcp41010.c
@@ -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;
diff --git a/drivers/iio/potentiometer/mcp4131.c b/drivers/iio/potentiometer/mcp4131.c
index 98df91e97f2f..2923ce250fc3 100644
--- a/drivers/iio/potentiometer/mcp4131.c
+++ b/drivers/iio/potentiometer/mcp4131.c
@@ -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;
diff --git a/drivers/iio/potentiometer/mcp4531.c b/drivers/iio/potentiometer/mcp4531.c
index d71a22d71a30..95efc4b40514 100644
--- a/drivers/iio/potentiometer/mcp4531.c
+++ b/drivers/iio/potentiometer/mcp4531.c
@@ -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;
diff --git a/drivers/iio/potentiometer/tpl0102.c b/drivers/iio/potentiometer/tpl0102.c
index a0a07e47f13f..d996dc367fb7 100644
--- a/drivers/iio/potentiometer/tpl0102.c
+++ b/drivers/iio/potentiometer/tpl0102.c
@@ -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;
diff --git a/drivers/iio/potentiostat/lmp91000.c b/drivers/iio/potentiostat/lmp91000.c
index 2cb11da18e0f..67ae635a05f3 100644
--- a/drivers/iio/potentiostat/lmp91000.c
+++ b/drivers/iio/potentiostat/lmp91000.c
@@ -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);
diff --git a/drivers/iio/pressure/abp060mg.c b/drivers/iio/pressure/abp060mg.c
index 267aad8af0a6..e1c3bdb371ee 100644
--- a/drivers/iio/pressure/abp060mg.c
+++ b/drivers/iio/pressure/abp060mg.c
@@ -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;
diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
index 29c209cc1108..6b7da40f99c8 100644
--- a/drivers/iio/pressure/bmp280-core.c
+++ b/drivers/iio/pressure/bmp280-core.c
@@ -271,6 +271,8 @@ static u32 bmp280_compensate_humidity(struct bmp280_data *data,
+ (s32)2097152) * calib->H2 + 8192) >> 14);
var -= ((((var >> 15) * (var >> 15)) >> 7) * (s32)calib->H1) >> 4;
+ var = clamp_val(var, 0, 419430400);
+
return var >> 12;
};
@@ -337,8 +339,7 @@ static int bmp280_read_temp(struct bmp280_data *data,
__be32 tmp = 0;
s32 adc_temp, comp_temp;
- ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB,
- (u8 *) &tmp, 3);
+ ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB, &tmp, 3);
if (ret < 0) {
dev_err(data->dev, "failed to read temperature\n");
return ret;
@@ -377,8 +378,7 @@ static int bmp280_read_press(struct bmp280_data *data,
if (ret < 0)
return ret;
- ret = regmap_bulk_read(data->regmap, BMP280_REG_PRESS_MSB,
- (u8 *) &tmp, 3);
+ ret = regmap_bulk_read(data->regmap, BMP280_REG_PRESS_MSB, &tmp, 3);
if (ret < 0) {
dev_err(data->dev, "failed to read pressure\n");
return ret;
@@ -400,8 +400,8 @@ static int bmp280_read_press(struct bmp280_data *data,
static int bmp280_read_humid(struct bmp280_data *data, int *val, int *val2)
{
+ __be16 tmp;
int ret;
- __be16 tmp = 0;
s32 adc_humidity;
u32 comp_humidity;
@@ -410,8 +410,7 @@ static int bmp280_read_humid(struct bmp280_data *data, int *val, int *val2)
if (ret < 0)
return ret;
- ret = regmap_bulk_read(data->regmap, BMP280_REG_HUMIDITY_MSB,
- (u8 *) &tmp, 2);
+ ret = regmap_bulk_read(data->regmap, BMP280_REG_HUMIDITY_MSB, &tmp, 2);
if (ret < 0) {
dev_err(data->dev, "failed to read humidity\n");
return ret;
@@ -575,57 +574,38 @@ static int bmp280_write_raw(struct iio_dev *indio_dev,
return ret;
}
-static ssize_t bmp280_show_avail(char *buf, const int *vals, const int n)
+static int bmp280_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long mask)
{
- size_t len = 0;
- int i;
-
- for (i = 0; i < n; i++)
- len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", vals[i]);
-
- buf[len - 1] = '\n';
-
- return len;
-}
-
-static ssize_t bmp280_show_temp_oversampling_avail(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct bmp280_data *data = iio_priv(dev_to_iio_dev(dev));
-
- return bmp280_show_avail(buf, data->chip_info->oversampling_temp_avail,
- data->chip_info->num_oversampling_temp_avail);
-}
-
-static ssize_t bmp280_show_press_oversampling_avail(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct bmp280_data *data = iio_priv(dev_to_iio_dev(dev));
+ struct bmp280_data *data = iio_priv(indio_dev);
- return bmp280_show_avail(buf, data->chip_info->oversampling_press_avail,
- data->chip_info->num_oversampling_press_avail);
+ switch (mask) {
+ case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+ switch (chan->type) {
+ case IIO_PRESSURE:
+ *vals = data->chip_info->oversampling_press_avail;
+ *length = data->chip_info->num_oversampling_press_avail;
+ break;
+ case IIO_TEMP:
+ *vals = data->chip_info->oversampling_temp_avail;
+ *length = data->chip_info->num_oversampling_temp_avail;
+ break;
+ default:
+ return -EINVAL;
+ }
+ *type = IIO_VAL_INT;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
}
-static IIO_DEVICE_ATTR(in_temp_oversampling_ratio_available,
- S_IRUGO, bmp280_show_temp_oversampling_avail, NULL, 0);
-
-static IIO_DEVICE_ATTR(in_pressure_oversampling_ratio_available,
- S_IRUGO, bmp280_show_press_oversampling_avail, NULL, 0);
-
-static struct attribute *bmp280_attributes[] = {
- &iio_dev_attr_in_temp_oversampling_ratio_available.dev_attr.attr,
- &iio_dev_attr_in_pressure_oversampling_ratio_available.dev_attr.attr,
- NULL,
-};
-
-static const struct attribute_group bmp280_attrs_group = {
- .attrs = bmp280_attributes,
-};
-
static const struct iio_info bmp280_info = {
.read_raw = &bmp280_read_raw,
+ .read_avail = &bmp280_read_avail,
.write_raw = &bmp280_write_raw,
- .attrs = &bmp280_attrs_group,
};
static int bmp280_chip_config(struct bmp280_data *data)
@@ -713,7 +693,7 @@ static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas)
unsigned int ctrl;
if (data->use_eoc)
- init_completion(&data->done);
+ reinit_completion(&data->done);
ret = regmap_write(data->regmap, BMP280_REG_CTRL_MEAS, ctrl_meas);
if (ret)
@@ -752,14 +732,14 @@ static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas)
static int bmp180_read_adc_temp(struct bmp280_data *data, int *val)
{
+ __be16 tmp;
int ret;
- __be16 tmp = 0;
ret = bmp180_measure(data, BMP180_MEAS_TEMP);
if (ret)
return ret;
- ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB, (u8 *)&tmp, 2);
+ ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB, &tmp, 2);
if (ret)
return ret;
@@ -856,7 +836,7 @@ static int bmp180_read_adc_press(struct bmp280_data *data, int *val)
if (ret)
return ret;
- ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB, (u8 *)&tmp, 3);
+ ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB, &tmp, 3);
if (ret)
return ret;
@@ -965,10 +945,12 @@ static int bmp085_fetch_eoc_irq(struct device *dev,
irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq));
if (irq_trig != IRQF_TRIGGER_RISING) {
- dev_err(dev, "non-rising trigger given for EOC interrupt, "
- "trying to enforce it\n");
+ dev_err(dev, "non-rising trigger given for EOC interrupt, trying to enforce it\n");
irq_trig = IRQF_TRIGGER_RISING;
}
+
+ init_completion(&data->done);
+
ret = devm_request_threaded_irq(dev,
irq,
bmp085_eoc_irq,
@@ -1022,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;
@@ -1082,9 +1063,9 @@ int bmp280_common_probe(struct device *dev,
usleep_range(data->start_up_time, data->start_up_time + 100);
/* Bring chip out of reset if there is an assigned GPIO line */
- gpiod = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ gpiod = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
/* Deassert the signal */
- if (!IS_ERR(gpiod)) {
+ if (gpiod) {
dev_info(dev, "release reset\n");
gpiod_set_value(gpiod, 0);
}
diff --git a/drivers/iio/pressure/cros_ec_baro.c b/drivers/iio/pressure/cros_ec_baro.c
index c079b8960082..f0938b6fbba0 100644
--- a/drivers/iio/pressure/cros_ec_baro.c
+++ b/drivers/iio/pressure/cros_ec_baro.c
@@ -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,
diff --git a/drivers/iio/pressure/dlhl60d.c b/drivers/iio/pressure/dlhl60d.c
index b8c99e7bd6cf..ade73267d5eb 100644
--- a/drivers/iio/pressure/dlhl60d.c
+++ b/drivers/iio/pressure/dlhl60d.c
@@ -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;
diff --git a/drivers/iio/pressure/dps310.c b/drivers/iio/pressure/dps310.c
index 2c1943bbc433..0730380ceb69 100644
--- a/drivers/iio/pressure/dps310.c
+++ b/drivers/iio/pressure/dps310.c
@@ -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);
diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c
index 953235052155..5c458788f346 100644
--- a/drivers/iio/pressure/hid-sensor-press.c
+++ b/drivers/iio/pressure/hid-sensor-press.c
@@ -14,8 +14,6 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
-#include <linux/iio/trigger_consumer.h>
-#include <linux/iio/triggered_buffer.h>
#include "../common/hid-sensors/hid-sensor-trigger.h"
#define CHANNEL_SCAN_INDEX_PRESSURE 0
@@ -285,23 +283,17 @@ 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;
- ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
- NULL, NULL);
- if (ret) {
- dev_err(&pdev->dev, "failed to initialize trigger buffer\n");
- goto error_free_dev_mem;
- }
atomic_set(&press_state->common_attributes.data_ready, 0);
+
ret = hid_sensor_setup_trigger(indio_dev, name,
&press_state->common_attributes);
if (ret) {
dev_err(&pdev->dev, "trigger setup failed\n");
- goto error_unreg_buffer_funcs;
+ goto error_free_dev_mem;
}
ret = iio_device_register(indio_dev);
@@ -325,9 +317,7 @@ static int hid_press_probe(struct platform_device *pdev)
error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
- hid_sensor_remove_trigger(&press_state->common_attributes);
-error_unreg_buffer_funcs:
- iio_triggered_buffer_cleanup(indio_dev);
+ hid_sensor_remove_trigger(indio_dev, &press_state->common_attributes);
error_free_dev_mem:
kfree(indio_dev->channels);
return ret;
@@ -342,8 +332,7 @@ static int hid_press_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_PRESSURE);
iio_device_unregister(indio_dev);
- hid_sensor_remove_trigger(&press_state->common_attributes);
- iio_triggered_buffer_cleanup(indio_dev);
+ hid_sensor_remove_trigger(indio_dev, &press_state->common_attributes);
kfree(indio_dev->channels);
return 0;
diff --git a/drivers/iio/pressure/hp03.c b/drivers/iio/pressure/hp03.c
index 026ba15ef68f..e40b1d7dc129 100644
--- a/drivers/iio/pressure/hp03.c
+++ b/drivers/iio/pressure/hp03.c
@@ -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);
diff --git a/drivers/iio/pressure/hp206c.c b/drivers/iio/pressure/hp206c.c
index 3ac3632e7242..986b7a59712e 100644
--- a/drivers/iio/pressure/hp206c.c
+++ b/drivers/iio/pressure/hp206c.c
@@ -18,6 +18,8 @@
#include <linux/util_macros.h>
#include <linux/acpi.h>
+#include <asm/unaligned.h>
+
/* I2C commands: */
#define HP206C_CMD_SOFT_RST 0x06
@@ -93,12 +95,12 @@ static int hp206c_read_20bit(struct i2c_client *client, u8 cmd)
int ret;
u8 values[3];
- ret = i2c_smbus_read_i2c_block_data(client, cmd, 3, values);
+ ret = i2c_smbus_read_i2c_block_data(client, cmd, sizeof(values), values);
if (ret < 0)
return ret;
- if (ret != 3)
+ if (ret != sizeof(values))
return -EIO;
- return ((values[0] & 0xF) << 16) | (values[1] << 8) | (values[2]);
+ return get_unaligned_be24(&values[0]) & GENMASK(19, 0);
}
/* Spin for max 160ms until DEV_RDY is 1, or return error. */
@@ -376,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);
diff --git a/drivers/iio/pressure/icp10100.c b/drivers/iio/pressure/icp10100.c
index 06cb5b63a189..90c0df068bbb 100644
--- a/drivers/iio/pressure/icp10100.c
+++ b/drivers/iio/pressure/icp10100.c
@@ -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;
diff --git a/drivers/iio/pressure/mpl115.c b/drivers/iio/pressure/mpl115.c
index ca81a3dc5646..81f288312a28 100644
--- a/drivers/iio/pressure/mpl115.c
+++ b/drivers/iio/pressure/mpl115.c
@@ -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);
diff --git a/drivers/iio/pressure/mpl3115.c b/drivers/iio/pressure/mpl3115.c
index d066f3c5a8a6..ccdb0b70e48c 100644
--- a/drivers/iio/pressure/mpl3115.c
+++ b/drivers/iio/pressure/mpl3115.c
@@ -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);
diff --git a/drivers/iio/pressure/ms5611_core.c b/drivers/iio/pressure/ms5611_core.c
index 2f598ad91621..214b0d25f598 100644
--- a/drivers/iio/pressure/ms5611_core.c
+++ b/drivers/iio/pressure/ms5611_core.c
@@ -212,16 +212,21 @@ static irqreturn_t ms5611_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct ms5611_state *st = iio_priv(indio_dev);
- s32 buf[4]; /* s32 (pressure) + s32 (temp) + 2 * s32 (timestamp) */
+ /* Ensure buffer elements are naturally aligned */
+ struct {
+ s32 channels[2];
+ s64 ts __aligned(8);
+ } scan;
int ret;
mutex_lock(&st->lock);
- ret = ms5611_read_temp_and_pressure(indio_dev, &buf[1], &buf[0]);
+ ret = ms5611_read_temp_and_pressure(indio_dev, &scan.channels[1],
+ &scan.channels[0]);
mutex_unlock(&st->lock);
if (ret < 0)
goto err;
- iio_push_to_buffers_with_timestamp(indio_dev, buf,
+ iio_push_to_buffers_with_timestamp(indio_dev, &scan,
iio_get_time_ns(indio_dev));
err:
@@ -435,7 +440,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;
diff --git a/drivers/iio/pressure/ms5611_i2c.c b/drivers/iio/pressure/ms5611_i2c.c
index 8089c59adce5..072c106dd66d 100644
--- a/drivers/iio/pressure/ms5611_i2c.c
+++ b/drivers/iio/pressure/ms5611_i2c.c
@@ -16,6 +16,8 @@
#include <linux/module.h>
#include <linux/of_device.h>
+#include <asm/unaligned.h>
+
#include "ms5611.h"
static int ms5611_i2c_reset(struct device *dev)
@@ -50,7 +52,7 @@ static int ms5611_i2c_read_adc(struct ms5611_state *st, s32 *val)
if (ret < 0)
return ret;
- *val = (buf[0] << 16) | (buf[1] << 8) | buf[2];
+ *val = get_unaligned_be24(&buf[0]);
return 0;
}
diff --git a/drivers/iio/pressure/ms5611_spi.c b/drivers/iio/pressure/ms5611_spi.c
index b463eaa799ab..4799aa57135e 100644
--- a/drivers/iio/pressure/ms5611_spi.c
+++ b/drivers/iio/pressure/ms5611_spi.c
@@ -11,6 +11,8 @@
#include <linux/spi/spi.h>
#include <linux/of_device.h>
+#include <asm/unaligned.h>
+
#include "ms5611.h"
static int ms5611_spi_reset(struct device *dev)
@@ -45,7 +47,7 @@ static int ms5611_spi_read_adc(struct device *dev, s32 *val)
if (ret < 0)
return ret;
- *val = (buf[0] << 16) | (buf[1] << 8) | buf[2];
+ *val = get_unaligned_be24(&buf[0]);
return 0;
}
diff --git a/drivers/iio/pressure/ms5637.c b/drivers/iio/pressure/ms5637.c
index f49c7003c72a..05e0ef7260d5 100644
--- a/drivers/iio/pressure/ms5637.c
+++ b/drivers/iio/pressure/ms5637.c
@@ -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);
diff --git a/drivers/iio/pressure/st_pressure_buffer.c b/drivers/iio/pressure/st_pressure_buffer.c
index 418dbf9e6e1e..7cf6f06797e1 100644
--- a/drivers/iio/pressure/st_pressure_buffer.c
+++ b/drivers/iio/pressure/st_pressure_buffer.c
@@ -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 = {
diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c
index bd972cec4830..789a2928504a 100644
--- a/drivers/iio/pressure/st_pressure_core.c
+++ b/drivers/iio/pressure/st_pressure_core.c
@@ -683,8 +683,7 @@ EXPORT_SYMBOL(st_press_get_settings);
int st_press_common_probe(struct iio_dev *indio_dev)
{
struct st_sensor_data *press_data = iio_priv(indio_dev);
- struct st_sensors_platform_data *pdata =
- (struct st_sensors_platform_data *)press_data->dev->platform_data;
+ struct st_sensors_platform_data *pdata = dev_get_platdata(press_data->dev);
int err;
indio_dev->modes = INDIO_DIRECT_MODE;
@@ -708,9 +707,7 @@ int st_press_common_probe(struct iio_dev *indio_dev)
indio_dev->channels = press_data->sensor_settings->ch;
indio_dev->num_channels = press_data->sensor_settings->num_ch;
- press_data->current_fullscale =
- (struct st_sensor_fullscale_avl *)
- &press_data->sensor_settings->fs.fs_avl[0];
+ press_data->current_fullscale = &press_data->sensor_settings->fs.fs_avl[0];
press_data->odr = press_data->sensor_settings->odr.odr_avl[0].hz;
diff --git a/drivers/iio/pressure/t5403.c b/drivers/iio/pressure/t5403.c
index 22abd28071b7..685fcf65334f 100644
--- a/drivers/iio/pressure/t5403.c
+++ b/drivers/iio/pressure/t5403.c
@@ -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);
diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c
index 99dfe33ee402..2cecbe0adb3f 100644
--- a/drivers/iio/pressure/zpa2326.c
+++ b/drivers/iio/pressure/zpa2326.c
@@ -64,6 +64,7 @@
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
+#include <asm/unaligned.h>
#include "zpa2326.h"
/* 200 ms should be enough for the longest conversion time in one-shot mode. */
@@ -664,8 +665,10 @@ static int zpa2326_resume(const struct iio_dev *indio_dev)
int err;
err = pm_runtime_get_sync(indio_dev->dev.parent);
- if (err < 0)
+ if (err < 0) {
+ pm_runtime_put(indio_dev->dev.parent);
return err;
+ }
if (err > 0) {
/*
@@ -1005,22 +1008,20 @@ static int zpa2326_fetch_raw_sample(const struct iio_dev *indio_dev,
struct regmap *regs = ((struct zpa2326_private *)
iio_priv(indio_dev))->regmap;
int err;
+ u8 v[3];
switch (type) {
case IIO_PRESSURE:
zpa2326_dbg(indio_dev, "fetching raw pressure sample");
- err = regmap_bulk_read(regs, ZPA2326_PRESS_OUT_XL_REG, value,
- 3);
+ err = regmap_bulk_read(regs, ZPA2326_PRESS_OUT_XL_REG, v, sizeof(v));
if (err) {
zpa2326_warn(indio_dev, "failed to fetch pressure (%d)",
err);
return err;
}
- /* Pressure is a 24 bits wide little-endian unsigned int. */
- *value = (((u8 *)value)[2] << 16) | (((u8 *)value)[1] << 8) |
- ((u8 *)value)[0];
+ *value = get_unaligned_le24(&v[0]);
return IIO_VAL_INT;
@@ -1243,19 +1244,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) {
@@ -1264,18 +1263,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)
@@ -1288,7 +1283,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
};
@@ -1602,7 +1596,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;
diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig
index 37606d400805..12672a0e89ed 100644
--- a/drivers/iio/proximity/Kconfig
+++ b/drivers/iio/proximity/Kconfig
@@ -101,6 +101,19 @@ config SRF04
To compile this driver as a module, choose M here: the
module will be called srf04.
+config SX9310
+ tristate "SX9310/SX9311 Semtech proximity sensor"
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ select REGMAP_I2C
+ depends on I2C
+ help
+ Say Y here to build a driver for Semtech's SX9310/SX9311 capacitive
+ proximity/button sensor.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sx9310.
+
config SX9500
tristate "SX9500 Semtech proximity sensor"
select IIO_BUFFER
@@ -127,6 +140,17 @@ config SRF08
To compile this driver as a module, choose M here: the
module will be called srf08.
+config VCNL3020
+ tristate "VCNL3020 proximity sensor"
+ select REGMAP_I2C
+ depends on I2C
+ help
+ Say Y here if you want to build a driver for the Vishay VCNL3020
+ proximity sensor.
+
+ To compile this driver as a module, choose M here: the
+ module will be called vcnl3020.
+
config VL53L0X_I2C
tristate "STMicroelectronics VL53L0X ToF ranger sensor (I2C)"
depends on I2C
diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile
index c591b019304e..9c1aca1a8b79 100644
--- a/drivers/iio/proximity/Makefile
+++ b/drivers/iio/proximity/Makefile
@@ -12,6 +12,8 @@ obj-$(CONFIG_PING) += ping.o
obj-$(CONFIG_RFD77402) += rfd77402.o
obj-$(CONFIG_SRF04) += srf04.o
obj-$(CONFIG_SRF08) += srf08.o
+obj-$(CONFIG_SX9310) += sx9310.o
obj-$(CONFIG_SX9500) += sx9500.o
+obj-$(CONFIG_VCNL3020) += vcnl3020.o
obj-$(CONFIG_VL53L0X_I2C) += vl53l0x-i2c.o
diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c
index bac9a433dd19..c339e7339ec8 100644
--- a/drivers/iio/proximity/as3935.c
+++ b/drivers/iio/proximity/as3935.c
@@ -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);
diff --git a/drivers/iio/proximity/isl29501.c b/drivers/iio/proximity/isl29501.c
index 5ae549075b27..90e76451c972 100644
--- a/drivers/iio/proximity/isl29501.c
+++ b/drivers/iio/proximity/isl29501.c
@@ -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;
diff --git a/drivers/iio/proximity/mb1232.c b/drivers/iio/proximity/mb1232.c
index 166b3e6d7db8..ad4b1fb2607a 100644
--- a/drivers/iio/proximity/mb1232.c
+++ b/drivers/iio/proximity/mb1232.c
@@ -40,6 +40,11 @@ struct mb1232_data {
*/
struct completion ranging;
int irqnr;
+ /* Ensure correct alignment of data to push to IIO buffer */
+ struct {
+ s16 distance;
+ s64 ts __aligned(8);
+ } scan;
};
static irqreturn_t mb1232_handle_irq(int irq, void *dev_id)
@@ -113,17 +118,13 @@ static irqreturn_t mb1232_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct mb1232_data *data = iio_priv(indio_dev);
- /*
- * triggered buffer
- * 16-bit channel + 48-bit padding + 64-bit timestamp
- */
- s16 buffer[8] = { 0 };
- buffer[0] = mb1232_read_distance(data);
- if (buffer[0] < 0)
+ data->scan.distance = mb1232_read_distance(data);
+ if (data->scan.distance < 0)
goto err;
- iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp);
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
+ pf->timestamp);
err:
iio_trigger_notify_done(indio_dev->trig);
@@ -200,7 +201,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);
diff --git a/drivers/iio/proximity/ping.c b/drivers/iio/proximity/ping.c
index 12b893c5b0ee..1283ac1c2e03 100644
--- a/drivers/iio/proximity/ping.c
+++ b/drivers/iio/proximity/ping.c
@@ -89,14 +89,14 @@ static irqreturn_t ping_handle_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int ping_read(struct ping_data *data)
+static int ping_read(struct iio_dev *indio_dev)
{
+ struct ping_data *data = iio_priv(indio_dev);
int ret;
ktime_t ktime_dt;
s64 dt_ns;
u32 time_ns, distance_mm;
struct platform_device *pdev = to_platform_device(data->dev);
- struct iio_dev *indio_dev = iio_priv_to_dev(data);
/*
* just one read-echo-cycle can take place at a time
@@ -228,7 +228,6 @@ static int ping_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *channel, int *val,
int *val2, long info)
{
- struct ping_data *data = iio_priv(indio_dev);
int ret;
if (channel->type != IIO_DISTANCE)
@@ -236,7 +235,7 @@ static int ping_read_raw(struct iio_dev *indio_dev,
switch (info) {
case IIO_CHAN_INFO_RAW:
- ret = ping_read(data);
+ ret = ping_read(indio_dev);
if (ret < 0)
return ret;
*val = ret;
@@ -310,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;
diff --git a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
index 5b369645ef49..a8e716dbd24e 100644
--- a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
+++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
@@ -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);
diff --git a/drivers/iio/proximity/rfd77402.c b/drivers/iio/proximity/rfd77402.c
index 36480c0100a7..7a0472323f17 100644
--- a/drivers/iio/proximity/rfd77402.c
+++ b/drivers/iio/proximity/rfd77402.c
@@ -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);
diff --git a/drivers/iio/proximity/srf04.c b/drivers/iio/proximity/srf04.c
index 568b76e06385..420c37c72de4 100644
--- a/drivers/iio/proximity/srf04.c
+++ b/drivers/iio/proximity/srf04.c
@@ -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;
diff --git a/drivers/iio/proximity/srf08.c b/drivers/iio/proximity/srf08.c
index b23ce446b7be..70beac5c9c1d 100644
--- a/drivers/iio/proximity/srf08.c
+++ b/drivers/iio/proximity/srf08.c
@@ -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);
diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c
new file mode 100644
index 000000000000..dc2e11b43431
--- /dev/null
+++ b/drivers/iio/proximity/sx9310.c
@@ -0,0 +1,1066 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 Google LLC.
+ *
+ * Driver for Semtech's SX9310/SX9311 capacitive proximity/button solution.
+ * Based on SX9500 driver and Semtech driver using the input framework
+ * <https://my.syncplicity.com/share/teouwsim8niiaud/
+ * linux-driver-SX9310_NoSmartHSensing>.
+ * Reworked April 2019 by Evan Green <evgreen@chromium.org>
+ * and January 2020 by Daniel Campello <campello@chromium.org>
+ */
+
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pm.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include <linux/iio/buffer.h>
+#include <linux/iio/events.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
+
+/* Register definitions. */
+#define SX9310_REG_IRQ_SRC 0x00
+#define SX9310_REG_STAT0 0x01
+#define SX9310_REG_STAT1 0x02
+#define SX9310_REG_IRQ_MSK 0x03
+#define SX9310_CONVDONE_IRQ BIT(3)
+#define SX9310_FAR_IRQ BIT(5)
+#define SX9310_CLOSE_IRQ BIT(6)
+#define SX9310_EVENT_IRQ (SX9310_FAR_IRQ | \
+ SX9310_CLOSE_IRQ)
+#define SX9310_REG_IRQ_FUNC 0x04
+
+#define SX9310_REG_PROX_CTRL0 0x10
+#define SX9310_REG_PROX_CTRL0_PROXSTAT2 0x10
+#define SX9310_REG_PROX_CTRL0_EN_MASK 0x0F
+#define SX9310_REG_PROX_CTRL1 0x11
+#define SX9310_REG_PROX_CTRL2 0x12
+#define SX9310_REG_PROX_CTRL2_COMBMODE_ALL 0x80
+#define SX9310_REG_PROX_CTRL2_SHIELDEN_DYNAMIC 0x04
+#define SX9310_REG_PROX_CTRL3 0x13
+#define SX9310_REG_PROX_CTRL3_GAIN0_X8 0x0c
+#define SX9310_REG_PROX_CTRL3_GAIN12_X4 0x02
+#define SX9310_REG_PROX_CTRL4 0x14
+#define SX9310_REG_PROX_CTRL4_RESOLUTION_FINEST 0x07
+#define SX9310_REG_PROX_CTRL5 0x15
+#define SX9310_REG_PROX_CTRL5_RANGE_SMALL 0xc0
+#define SX9310_REG_PROX_CTRL5_STARTUPSENS_CS1 0x04
+#define SX9310_REG_PROX_CTRL5_RAWFILT_1P25 0x02
+#define SX9310_REG_PROX_CTRL6 0x16
+#define SX9310_REG_PROX_CTRL6_COMP_COMMON 0x20
+#define SX9310_REG_PROX_CTRL7 0x17
+#define SX9310_REG_PROX_CTRL7_AVGNEGFILT_2 0x08
+#define SX9310_REG_PROX_CTRL7_AVGPOSFILT_512 0x05
+#define SX9310_REG_PROX_CTRL8 0x18
+#define SX9310_REG_PROX_CTRL9 0x19
+#define SX9310_REG_PROX_CTRL8_9_PTHRESH12_28 0x40
+#define SX9310_REG_PROX_CTRL8_9_PTHRESH_96 0x88
+#define SX9310_REG_PROX_CTRL8_9_BODYTHRESH_900 0x03
+#define SX9310_REG_PROX_CTRL8_9_BODYTHRESH_1500 0x05
+#define SX9310_REG_PROX_CTRL10 0x1a
+#define SX9310_REG_PROX_CTRL10_HYST_6PCT 0x10
+#define SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_8 0x12
+#define SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_8 0x03
+#define SX9310_REG_PROX_CTRL11 0x1b
+#define SX9310_REG_PROX_CTRL12 0x1c
+#define SX9310_REG_PROX_CTRL13 0x1d
+#define SX9310_REG_PROX_CTRL14 0x1e
+#define SX9310_REG_PROX_CTRL15 0x1f
+#define SX9310_REG_PROX_CTRL16 0x20
+#define SX9310_REG_PROX_CTRL17 0x21
+#define SX9310_REG_PROX_CTRL18 0x22
+#define SX9310_REG_PROX_CTRL19 0x23
+#define SX9310_REG_SAR_CTRL0 0x2a
+#define SX9310_REG_SAR_CTRL0_SARDEB_4_SAMPLES 0x40
+#define SX9310_REG_SAR_CTRL0_SARHYST_8 0x10
+#define SX9310_REG_SAR_CTRL1 0x2b
+/* Each increment of the slope register is 0.0078125. */
+#define SX9310_REG_SAR_CTRL1_SLOPE(_hnslope) (_hnslope / 78125)
+#define SX9310_REG_SAR_CTRL2 0x2c
+#define SX9310_REG_SAR_CTRL2_SAROFFSET_DEFAULT 0x3c
+
+#define SX9310_REG_SENSOR_SEL 0x30
+
+#define SX9310_REG_USE_MSB 0x31
+#define SX9310_REG_USE_LSB 0x32
+
+#define SX9310_REG_AVG_MSB 0x33
+#define SX9310_REG_AVG_LSB 0x34
+
+#define SX9310_REG_DIFF_MSB 0x35
+#define SX9310_REG_DIFF_LSB 0x36
+
+#define SX9310_REG_OFFSET_MSB 0x37
+#define SX9310_REG_OFFSET_LSB 0x38
+
+#define SX9310_REG_SAR_MSB 0x39
+#define SX9310_REG_SAR_LSB 0x3a
+
+#define SX9310_REG_I2CADDR 0x40
+#define SX9310_REG_PAUSE 0x41
+#define SX9310_REG_WHOAMI 0x42
+#define SX9310_WHOAMI_VALUE 0x01
+#define SX9311_WHOAMI_VALUE 0x02
+
+#define SX9310_REG_RESET 0x7f
+#define SX9310_SOFT_RESET 0xde
+
+#define SX9310_SCAN_PERIOD_MASK GENMASK(7, 4)
+#define SX9310_SCAN_PERIOD_SHIFT 4
+
+#define SX9310_COMPSTAT_MASK GENMASK(3, 0)
+
+/* 4 hardware channels, as defined in STAT0: COMB, CS2, CS1 and CS0. */
+#define SX9310_NUM_CHANNELS 4
+#define SX9310_CHAN_ENABLED_MASK GENMASK(3, 0)
+
+struct sx9310_data {
+ /* Serialize access to registers and channel configuration */
+ struct mutex mutex;
+ struct i2c_client *client;
+ struct iio_trigger *trig;
+ struct regmap *regmap;
+ /*
+ * Last reading of the proximity status for each channel.
+ * We only send an event to user space when this changes.
+ */
+ bool prox_stat[SX9310_NUM_CHANNELS];
+ bool trigger_enabled;
+ __be16 buffer[SX9310_NUM_CHANNELS +
+ 4]; /* 64-bit data + 64-bit timestamp */
+ /* Remember enabled channels and sample rate during suspend. */
+ unsigned int suspend_ctrl0;
+ struct completion completion;
+ unsigned int chan_read, chan_event;
+ int channel_users[SX9310_NUM_CHANNELS];
+ int whoami;
+};
+
+static const struct iio_event_spec sx9310_events[] = {
+ {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_EITHER,
+ .mask_separate = BIT(IIO_EV_INFO_ENABLE),
+ },
+};
+
+#define SX9310_NAMED_CHANNEL(idx, name) \
+ { \
+ .type = IIO_PROXIMITY, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .indexed = 1, \
+ .channel = idx, \
+ .extend_name = name, \
+ .address = SX9310_REG_DIFF_MSB, \
+ .event_spec = sx9310_events, \
+ .num_event_specs = ARRAY_SIZE(sx9310_events), \
+ .scan_index = idx, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 12, \
+ .storagebits = 16, \
+ .endianness = IIO_BE, \
+ }, \
+ }
+#define SX9310_CHANNEL(idx) SX9310_NAMED_CHANNEL(idx, NULL)
+
+static const struct iio_chan_spec sx9310_channels[] = {
+ SX9310_CHANNEL(0), /* CS0 */
+ SX9310_CHANNEL(1), /* CS1 */
+ SX9310_CHANNEL(2), /* CS2 */
+ SX9310_NAMED_CHANNEL(3, "comb"), /* COMB */
+
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+};
+
+/*
+ * Each entry contains the integer part (val) and the fractional part, in micro
+ * seconds. It conforms to the IIO output IIO_VAL_INT_PLUS_MICRO.
+ */
+static const struct {
+ int val;
+ int val2;
+} sx9310_samp_freq_table[] = {
+ { 500, 0 }, /* 0000: Min (no idle time) */
+ { 66, 666666 }, /* 0001: 15 ms */
+ { 33, 333333 }, /* 0010: 30 ms (Typ.) */
+ { 22, 222222 }, /* 0011: 45 ms */
+ { 16, 666666 }, /* 0100: 60 ms */
+ { 11, 111111 }, /* 0101: 90 ms */
+ { 8, 333333 }, /* 0110: 120 ms */
+ { 5, 0 }, /* 0111: 200 ms */
+ { 2, 500000 }, /* 1000: 400 ms */
+ { 1, 666666 }, /* 1001: 600 ms */
+ { 1, 250000 }, /* 1010: 800 ms */
+ { 1, 0 }, /* 1011: 1 s */
+ { 0, 500000 }, /* 1100: 2 s */
+ { 0, 333333 }, /* 1101: 3 s */
+ { 0, 250000 }, /* 1110: 4 s */
+ { 0, 200000 }, /* 1111: 5 s */
+};
+static const unsigned int sx9310_scan_period_table[] = {
+ 2, 15, 30, 45, 60, 90, 120, 200,
+ 400, 600, 800, 1000, 2000, 3000, 4000, 5000,
+};
+
+static ssize_t sx9310_show_samp_freq_avail(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ size_t len = 0;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sx9310_samp_freq_table); i++)
+ len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%d ",
+ sx9310_samp_freq_table[i].val,
+ sx9310_samp_freq_table[i].val2);
+ buf[len - 1] = '\n';
+ return len;
+}
+static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(sx9310_show_samp_freq_avail);
+
+static const struct regmap_range sx9310_writable_reg_ranges[] = {
+ regmap_reg_range(SX9310_REG_IRQ_MSK, SX9310_REG_IRQ_FUNC),
+ regmap_reg_range(SX9310_REG_PROX_CTRL0, SX9310_REG_PROX_CTRL19),
+ regmap_reg_range(SX9310_REG_SAR_CTRL0, SX9310_REG_SAR_CTRL2),
+ regmap_reg_range(SX9310_REG_SENSOR_SEL, SX9310_REG_SENSOR_SEL),
+ regmap_reg_range(SX9310_REG_OFFSET_MSB, SX9310_REG_OFFSET_LSB),
+ regmap_reg_range(SX9310_REG_PAUSE, SX9310_REG_PAUSE),
+ regmap_reg_range(SX9310_REG_RESET, SX9310_REG_RESET),
+};
+
+static const struct regmap_access_table sx9310_writeable_regs = {
+ .yes_ranges = sx9310_writable_reg_ranges,
+ .n_yes_ranges = ARRAY_SIZE(sx9310_writable_reg_ranges),
+};
+
+static const struct regmap_range sx9310_readable_reg_ranges[] = {
+ regmap_reg_range(SX9310_REG_IRQ_SRC, SX9310_REG_IRQ_FUNC),
+ regmap_reg_range(SX9310_REG_PROX_CTRL0, SX9310_REG_PROX_CTRL19),
+ regmap_reg_range(SX9310_REG_SAR_CTRL0, SX9310_REG_SAR_CTRL2),
+ regmap_reg_range(SX9310_REG_SENSOR_SEL, SX9310_REG_SAR_LSB),
+ regmap_reg_range(SX9310_REG_I2CADDR, SX9310_REG_WHOAMI),
+ regmap_reg_range(SX9310_REG_RESET, SX9310_REG_RESET),
+};
+
+static const struct regmap_access_table sx9310_readable_regs = {
+ .yes_ranges = sx9310_readable_reg_ranges,
+ .n_yes_ranges = ARRAY_SIZE(sx9310_readable_reg_ranges),
+};
+
+static const struct regmap_range sx9310_volatile_reg_ranges[] = {
+ regmap_reg_range(SX9310_REG_IRQ_SRC, SX9310_REG_STAT1),
+ regmap_reg_range(SX9310_REG_USE_MSB, SX9310_REG_DIFF_LSB),
+ regmap_reg_range(SX9310_REG_SAR_MSB, SX9310_REG_SAR_LSB),
+ regmap_reg_range(SX9310_REG_RESET, SX9310_REG_RESET),
+};
+
+static const struct regmap_access_table sx9310_volatile_regs = {
+ .yes_ranges = sx9310_volatile_reg_ranges,
+ .n_yes_ranges = ARRAY_SIZE(sx9310_volatile_reg_ranges),
+};
+
+static const struct regmap_config sx9310_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = SX9310_REG_RESET,
+ .cache_type = REGCACHE_RBTREE,
+
+ .wr_table = &sx9310_writeable_regs,
+ .rd_table = &sx9310_readable_regs,
+ .volatile_table = &sx9310_volatile_regs,
+};
+
+static int sx9310_update_chan_en(struct sx9310_data *data,
+ unsigned int chan_read,
+ unsigned int chan_event)
+{
+ int ret;
+
+ if ((data->chan_read | data->chan_event) != (chan_read | chan_event)) {
+ ret = regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL0,
+ SX9310_CHAN_ENABLED_MASK,
+ chan_read | chan_event);
+ if (ret)
+ return ret;
+ }
+ data->chan_read = chan_read;
+ data->chan_event = chan_event;
+ return 0;
+}
+
+static int sx9310_get_read_channel(struct sx9310_data *data, int channel)
+{
+ return sx9310_update_chan_en(data, data->chan_read | BIT(channel),
+ data->chan_event);
+}
+
+static int sx9310_put_read_channel(struct sx9310_data *data, int channel)
+{
+ return sx9310_update_chan_en(data, data->chan_read & ~BIT(channel),
+ data->chan_event);
+}
+
+static int sx9310_get_event_channel(struct sx9310_data *data, int channel)
+{
+ return sx9310_update_chan_en(data, data->chan_read,
+ data->chan_event | BIT(channel));
+}
+
+static int sx9310_put_event_channel(struct sx9310_data *data, int channel)
+{
+ return sx9310_update_chan_en(data, data->chan_read,
+ data->chan_event & ~BIT(channel));
+}
+
+static int sx9310_enable_irq(struct sx9310_data *data, unsigned int irq)
+{
+ return regmap_update_bits(data->regmap, SX9310_REG_IRQ_MSK, irq, irq);
+}
+
+static int sx9310_disable_irq(struct sx9310_data *data, unsigned int irq)
+{
+ return regmap_update_bits(data->regmap, SX9310_REG_IRQ_MSK, irq, 0);
+}
+
+static int sx9310_read_prox_data(struct sx9310_data *data,
+ const struct iio_chan_spec *chan, __be16 *val)
+{
+ int ret;
+
+ ret = regmap_write(data->regmap, SX9310_REG_SENSOR_SEL, chan->channel);
+ if (ret < 0)
+ return ret;
+
+ return regmap_bulk_read(data->regmap, chan->address, val, 2);
+}
+
+/*
+ * If we have no interrupt support, we have to wait for a scan period
+ * after enabling a channel to get a result.
+ */
+static int sx9310_wait_for_sample(struct sx9310_data *data)
+{
+ int ret;
+ unsigned int val;
+
+ ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL0, &val);
+ if (ret < 0)
+ return ret;
+
+ val = (val & SX9310_SCAN_PERIOD_MASK) >> SX9310_SCAN_PERIOD_SHIFT;
+
+ msleep(sx9310_scan_period_table[val]);
+
+ return 0;
+}
+
+static int sx9310_read_proximity(struct sx9310_data *data,
+ const struct iio_chan_spec *chan, int *val)
+{
+ int ret = 0;
+ __be16 rawval;
+
+ mutex_lock(&data->mutex);
+
+ ret = sx9310_get_read_channel(data, chan->channel);
+ if (ret < 0)
+ goto out;
+
+ ret = sx9310_enable_irq(data, SX9310_CONVDONE_IRQ);
+ if (ret < 0)
+ goto out_put_channel;
+
+ mutex_unlock(&data->mutex);
+
+ if (data->client->irq > 0) {
+ ret = wait_for_completion_interruptible(&data->completion);
+ reinit_completion(&data->completion);
+ } else {
+ ret = sx9310_wait_for_sample(data);
+ }
+
+ mutex_lock(&data->mutex);
+
+ if (ret < 0)
+ goto out_disable_irq;
+
+ ret = sx9310_read_prox_data(data, chan, &rawval);
+ if (ret < 0)
+ goto out_disable_irq;
+
+ *val = sign_extend32(be16_to_cpu(rawval),
+ (chan->address == SX9310_REG_DIFF_MSB ? 11 : 15));
+
+ ret = sx9310_disable_irq(data, SX9310_CONVDONE_IRQ);
+ if (ret < 0)
+ goto out_put_channel;
+
+ ret = sx9310_put_read_channel(data, chan->channel);
+ if (ret < 0)
+ goto out;
+
+ mutex_unlock(&data->mutex);
+
+ return IIO_VAL_INT;
+
+out_disable_irq:
+ sx9310_disable_irq(data, SX9310_CONVDONE_IRQ);
+out_put_channel:
+ sx9310_put_read_channel(data, chan->channel);
+out:
+ mutex_unlock(&data->mutex);
+
+ return ret;
+}
+
+static int sx9310_read_samp_freq(struct sx9310_data *data, int *val, int *val2)
+{
+ unsigned int regval;
+ int ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL0, &regval);
+
+ if (ret < 0)
+ return ret;
+
+ regval = (regval & SX9310_SCAN_PERIOD_MASK) >> SX9310_SCAN_PERIOD_SHIFT;
+ *val = sx9310_samp_freq_table[regval].val;
+ *val2 = sx9310_samp_freq_table[regval].val2;
+
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static int sx9310_read_raw(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan, int *val,
+ int *val2, long mask)
+{
+ struct sx9310_data *data = iio_priv(indio_dev);
+ int ret;
+
+ if (chan->type != IIO_PROXIMITY)
+ return -EINVAL;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
+ ret = sx9310_read_proximity(data, chan, val);
+ iio_device_release_direct_mode(indio_dev);
+ return ret;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return sx9310_read_samp_freq(data, val, val2);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int sx9310_set_samp_freq(struct sx9310_data *data, int val, int val2)
+{
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(sx9310_samp_freq_table); i++)
+ if (val == sx9310_samp_freq_table[i].val &&
+ val2 == sx9310_samp_freq_table[i].val2)
+ break;
+
+ if (i == ARRAY_SIZE(sx9310_samp_freq_table))
+ return -EINVAL;
+
+ mutex_lock(&data->mutex);
+
+ ret = regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL0,
+ SX9310_SCAN_PERIOD_MASK,
+ i << SX9310_SCAN_PERIOD_SHIFT);
+
+ mutex_unlock(&data->mutex);
+
+ return ret;
+}
+
+static int sx9310_write_raw(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan, int val, int val2,
+ long mask)
+{
+ struct sx9310_data *data = iio_priv(indio_dev);
+
+ if (chan->type != IIO_PROXIMITY)
+ return -EINVAL;
+
+ if (mask != IIO_CHAN_INFO_SAMP_FREQ)
+ return -EINVAL;
+
+ return sx9310_set_samp_freq(data, val, val2);
+}
+
+static irqreturn_t sx9310_irq_handler(int irq, void *private)
+{
+ struct iio_dev *indio_dev = private;
+ struct sx9310_data *data = iio_priv(indio_dev);
+
+ if (data->trigger_enabled)
+ iio_trigger_poll(data->trig);
+
+ /*
+ * Even if no event is enabled, we need to wake the thread to
+ * clear the interrupt state by reading SX9310_REG_IRQ_SRC. It
+ * is not possible to do that here because regmap_read takes a
+ * mutex.
+ */
+ return IRQ_WAKE_THREAD;
+}
+
+static void sx9310_push_events(struct iio_dev *indio_dev)
+{
+ int ret;
+ unsigned int val, chan;
+ struct sx9310_data *data = iio_priv(indio_dev);
+ s64 timestamp = iio_get_time_ns(indio_dev);
+
+ /* Read proximity state on all channels */
+ ret = regmap_read(data->regmap, SX9310_REG_STAT0, &val);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "i2c transfer error in irq\n");
+ return;
+ }
+
+ for (chan = 0; chan < SX9310_NUM_CHANNELS; chan++) {
+ int dir;
+ u64 ev;
+ bool new_prox = val & BIT(chan);
+
+ if (!(data->chan_event & BIT(chan)))
+ continue;
+ if (new_prox == data->prox_stat[chan])
+ /* No change on this channel. */
+ continue;
+
+ dir = new_prox ? IIO_EV_DIR_FALLING : IIO_EV_DIR_RISING;
+ ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, chan,
+ IIO_EV_TYPE_THRESH, dir);
+
+ iio_push_event(indio_dev, ev, timestamp);
+ data->prox_stat[chan] = new_prox;
+ }
+}
+
+static irqreturn_t sx9310_irq_thread_handler(int irq, void *private)
+{
+ struct iio_dev *indio_dev = private;
+ struct sx9310_data *data = iio_priv(indio_dev);
+ int ret;
+ unsigned int val;
+
+ mutex_lock(&data->mutex);
+
+ ret = regmap_read(data->regmap, SX9310_REG_IRQ_SRC, &val);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "i2c transfer error in irq\n");
+ goto out;
+ }
+
+ if (val & SX9310_EVENT_IRQ)
+ sx9310_push_events(indio_dev);
+
+ if (val & SX9310_CONVDONE_IRQ)
+ complete(&data->completion);
+
+out:
+ mutex_unlock(&data->mutex);
+
+ return IRQ_HANDLED;
+}
+
+static int sx9310_read_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir)
+{
+ struct sx9310_data *data = iio_priv(indio_dev);
+
+ return !!(data->chan_event & BIT(chan->channel));
+}
+
+static int sx9310_write_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir, int state)
+{
+ struct sx9310_data *data = iio_priv(indio_dev);
+ int ret;
+
+ /* If the state hasn't changed, there's nothing to do. */
+ if (!!(data->chan_event & BIT(chan->channel)) == state)
+ return 0;
+
+ mutex_lock(&data->mutex);
+ if (state) {
+ ret = sx9310_get_event_channel(data, chan->channel);
+ if (ret < 0)
+ goto out_unlock;
+ if (!(data->chan_event & ~BIT(chan->channel))) {
+ ret = sx9310_enable_irq(data, SX9310_EVENT_IRQ);
+ if (ret < 0)
+ sx9310_put_event_channel(data, chan->channel);
+ }
+ } else {
+ ret = sx9310_put_event_channel(data, chan->channel);
+ if (ret < 0)
+ goto out_unlock;
+ if (!data->chan_event) {
+ ret = sx9310_disable_irq(data, SX9310_EVENT_IRQ);
+ if (ret < 0)
+ sx9310_get_event_channel(data, chan->channel);
+ }
+ }
+
+out_unlock:
+ mutex_unlock(&data->mutex);
+ return ret;
+}
+
+static struct attribute *sx9310_attributes[] = {
+ &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group sx9310_attribute_group = {
+ .attrs = sx9310_attributes,
+};
+
+static const struct iio_info sx9310_info = {
+ .attrs = &sx9310_attribute_group,
+ .read_raw = sx9310_read_raw,
+ .write_raw = sx9310_write_raw,
+ .read_event_config = sx9310_read_event_config,
+ .write_event_config = sx9310_write_event_config,
+};
+
+static int sx9310_set_trigger_state(struct iio_trigger *trig, bool state)
+{
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+ struct sx9310_data *data = iio_priv(indio_dev);
+ int ret = 0;
+
+ mutex_lock(&data->mutex);
+
+ if (state)
+ ret = sx9310_enable_irq(data, SX9310_CONVDONE_IRQ);
+ else if (!data->chan_read)
+ ret = sx9310_disable_irq(data, SX9310_CONVDONE_IRQ);
+ if (ret < 0)
+ goto out;
+
+ data->trigger_enabled = state;
+
+out:
+ mutex_unlock(&data->mutex);
+
+ return ret;
+}
+
+static const struct iio_trigger_ops sx9310_trigger_ops = {
+ .set_trigger_state = sx9310_set_trigger_state,
+};
+
+static irqreturn_t sx9310_trigger_handler(int irq, void *private)
+{
+ struct iio_poll_func *pf = private;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct sx9310_data *data = iio_priv(indio_dev);
+ __be16 val;
+ int bit, ret, i = 0;
+
+ mutex_lock(&data->mutex);
+
+ for_each_set_bit(bit, indio_dev->active_scan_mask,
+ indio_dev->masklength) {
+ ret = sx9310_read_prox_data(data, &indio_dev->channels[bit],
+ &val);
+ if (ret < 0)
+ goto out;
+
+ data->buffer[i++] = val;
+ }
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+ pf->timestamp);
+
+out:
+ mutex_unlock(&data->mutex);
+
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int sx9310_buffer_preenable(struct iio_dev *indio_dev)
+{
+ struct sx9310_data *data = iio_priv(indio_dev);
+ unsigned int channels = 0;
+ int bit, ret;
+
+ mutex_lock(&data->mutex);
+ for_each_set_bit(bit, indio_dev->active_scan_mask,
+ indio_dev->masklength)
+ channels |= BIT(indio_dev->channels[bit].channel);
+
+ ret = sx9310_update_chan_en(data, channels, data->chan_event);
+ mutex_unlock(&data->mutex);
+ return ret;
+}
+
+static int sx9310_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct sx9310_data *data = iio_priv(indio_dev);
+ int ret;
+
+ mutex_lock(&data->mutex);
+ ret = sx9310_update_chan_en(data, 0, data->chan_event);
+ mutex_unlock(&data->mutex);
+ return ret;
+}
+
+static const struct iio_buffer_setup_ops sx9310_buffer_setup_ops = {
+ .preenable = sx9310_buffer_preenable,
+ .postdisable = sx9310_buffer_postdisable,
+};
+
+struct sx9310_reg_default {
+ u8 reg;
+ u8 def;
+};
+
+#define SX_INIT(_reg, _def) \
+ { \
+ .reg = SX9310_REG_##_reg, \
+ .def = _def, \
+ }
+
+static const struct sx9310_reg_default sx9310_default_regs[] = {
+ SX_INIT(IRQ_MSK, 0x00),
+ SX_INIT(IRQ_FUNC, 0x00),
+ /*
+ * The lower 4 bits should not be set as it enable sensors measurements.
+ * Turning the detection on before the configuration values are set to
+ * good values can cause the device to return erroneous readings.
+ */
+ SX_INIT(PROX_CTRL0, SX9310_REG_PROX_CTRL0_PROXSTAT2),
+ SX_INIT(PROX_CTRL1, 0x00),
+ SX_INIT(PROX_CTRL2, SX9310_REG_PROX_CTRL2_COMBMODE_ALL |
+ SX9310_REG_PROX_CTRL2_SHIELDEN_DYNAMIC),
+ SX_INIT(PROX_CTRL3, SX9310_REG_PROX_CTRL3_GAIN0_X8 |
+ SX9310_REG_PROX_CTRL3_GAIN12_X4),
+ SX_INIT(PROX_CTRL4, SX9310_REG_PROX_CTRL4_RESOLUTION_FINEST),
+ SX_INIT(PROX_CTRL5, SX9310_REG_PROX_CTRL5_RANGE_SMALL |
+ SX9310_REG_PROX_CTRL5_STARTUPSENS_CS1 |
+ SX9310_REG_PROX_CTRL5_RAWFILT_1P25),
+ SX_INIT(PROX_CTRL6, SX9310_REG_PROX_CTRL6_COMP_COMMON),
+ SX_INIT(PROX_CTRL7, SX9310_REG_PROX_CTRL7_AVGNEGFILT_2 |
+ SX9310_REG_PROX_CTRL7_AVGPOSFILT_512),
+ SX_INIT(PROX_CTRL8, SX9310_REG_PROX_CTRL8_9_PTHRESH_96 |
+ SX9310_REG_PROX_CTRL8_9_BODYTHRESH_1500),
+ SX_INIT(PROX_CTRL9, SX9310_REG_PROX_CTRL8_9_PTHRESH12_28 |
+ SX9310_REG_PROX_CTRL8_9_BODYTHRESH_900),
+ SX_INIT(PROX_CTRL10, SX9310_REG_PROX_CTRL10_HYST_6PCT |
+ SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_8 |
+ SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_8),
+ SX_INIT(PROX_CTRL11, 0x00),
+ SX_INIT(PROX_CTRL12, 0x00),
+ SX_INIT(PROX_CTRL13, 0x00),
+ SX_INIT(PROX_CTRL14, 0x00),
+ SX_INIT(PROX_CTRL15, 0x00),
+ SX_INIT(PROX_CTRL16, 0x00),
+ SX_INIT(PROX_CTRL17, 0x00),
+ SX_INIT(PROX_CTRL18, 0x00),
+ SX_INIT(PROX_CTRL19, 0x00),
+ SX_INIT(SAR_CTRL0, SX9310_REG_SAR_CTRL0_SARDEB_4_SAMPLES |
+ SX9310_REG_SAR_CTRL0_SARHYST_8),
+ SX_INIT(SAR_CTRL1, SX9310_REG_SAR_CTRL1_SLOPE(10781250)),
+ SX_INIT(SAR_CTRL2, SX9310_REG_SAR_CTRL2_SAROFFSET_DEFAULT),
+};
+
+/* Activate all channels and perform an initial compensation. */
+static int sx9310_init_compensation(struct iio_dev *indio_dev)
+{
+ struct sx9310_data *data = iio_priv(indio_dev);
+ int i, ret;
+ unsigned int val;
+ unsigned int ctrl0;
+
+ ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL0, &ctrl0);
+ if (ret < 0)
+ return ret;
+
+ /* run the compensation phase on all channels */
+ ret = regmap_write(data->regmap, SX9310_REG_PROX_CTRL0,
+ ctrl0 | SX9310_REG_PROX_CTRL0_EN_MASK);
+ if (ret < 0)
+ return ret;
+
+ for (i = 100; i >= 0; i--) {
+ msleep(20);
+ ret = regmap_read(data->regmap, SX9310_REG_STAT1, &val);
+ if (ret < 0)
+ goto out;
+ if (!(val & SX9310_COMPSTAT_MASK))
+ break;
+ }
+
+ if (i < 0) {
+ dev_err(&data->client->dev,
+ "initial compensation timed out: 0x%02x", val);
+ ret = -ETIMEDOUT;
+ }
+
+out:
+ regmap_write(data->regmap, SX9310_REG_PROX_CTRL0, ctrl0);
+ return ret;
+}
+
+static int sx9310_init_device(struct iio_dev *indio_dev)
+{
+ struct sx9310_data *data = iio_priv(indio_dev);
+ const struct sx9310_reg_default *initval;
+ int ret;
+ unsigned int i, val;
+
+ ret = regmap_write(data->regmap, SX9310_REG_RESET, SX9310_SOFT_RESET);
+ if (ret < 0)
+ return ret;
+
+ usleep_range(1000, 2000); /* power-up time is ~1ms. */
+
+ /* Clear reset interrupt state by reading SX9310_REG_IRQ_SRC. */
+ ret = regmap_read(data->regmap, SX9310_REG_IRQ_SRC, &val);
+ if (ret < 0)
+ return ret;
+
+ /* Program some sane defaults. */
+ for (i = 0; i < ARRAY_SIZE(sx9310_default_regs); i++) {
+ initval = &sx9310_default_regs[i];
+ ret = regmap_write(data->regmap, initval->reg, initval->def);
+ if (ret < 0)
+ return ret;
+ }
+
+ return sx9310_init_compensation(indio_dev);
+}
+
+static int sx9310_set_indio_dev_name(struct device *dev,
+ struct iio_dev *indio_dev,
+ const struct i2c_device_id *id, int whoami)
+{
+ const struct acpi_device_id *acpi_id;
+
+ /* id will be NULL when enumerated via ACPI */
+ if (id) {
+ if (id->driver_data != whoami)
+ dev_err(dev, "WHOAMI does not match i2c_device_id: %s",
+ id->name);
+ } else if (ACPI_HANDLE(dev)) {
+ acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev);
+ if (!acpi_id)
+ return -ENODEV;
+ if (acpi_id->driver_data != whoami)
+ dev_err(dev, "WHOAMI does not match acpi_device_id: %s",
+ acpi_id->id);
+ } else
+ return -ENODEV;
+
+ switch (whoami) {
+ case SX9310_WHOAMI_VALUE:
+ indio_dev->name = "sx9310";
+ break;
+ case SX9311_WHOAMI_VALUE:
+ indio_dev->name = "sx9311";
+ break;
+ default:
+ dev_err(dev, "unexpected WHOAMI response: %u", whoami);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int sx9310_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int ret;
+ struct iio_dev *indio_dev;
+ struct sx9310_data *data;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (indio_dev == NULL)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ data->client = client;
+ mutex_init(&data->mutex);
+ init_completion(&data->completion);
+
+ data->regmap = devm_regmap_init_i2c(client, &sx9310_regmap_config);
+ if (IS_ERR(data->regmap))
+ return PTR_ERR(data->regmap);
+
+ ret = regmap_read(data->regmap, SX9310_REG_WHOAMI, &data->whoami);
+ if (ret < 0) {
+ dev_err(&client->dev, "error in reading WHOAMI register: %d",
+ ret);
+ return ret;
+ }
+
+ ret = sx9310_set_indio_dev_name(&client->dev, indio_dev, id,
+ data->whoami);
+ if (ret < 0)
+ return ret;
+
+ ACPI_COMPANION_SET(&indio_dev->dev, ACPI_COMPANION(&client->dev));
+ indio_dev->channels = sx9310_channels;
+ indio_dev->num_channels = ARRAY_SIZE(sx9310_channels);
+ indio_dev->info = &sx9310_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ i2c_set_clientdata(client, indio_dev);
+
+ ret = sx9310_init_device(indio_dev);
+ if (ret < 0)
+ return ret;
+
+ if (client->irq) {
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ sx9310_irq_handler,
+ sx9310_irq_thread_handler,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ "sx9310_event", indio_dev);
+ if (ret < 0)
+ return ret;
+
+ data->trig =
+ devm_iio_trigger_alloc(&client->dev, "%s-dev%d",
+ indio_dev->name, indio_dev->id);
+ if (!data->trig)
+ return -ENOMEM;
+
+ data->trig->dev.parent = &client->dev;
+ data->trig->ops = &sx9310_trigger_ops;
+ iio_trigger_set_drvdata(data->trig, indio_dev);
+
+ ret = devm_iio_trigger_register(&client->dev, data->trig);
+ if (ret)
+ return ret;
+ }
+
+ ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,
+ iio_pollfunc_store_time,
+ sx9310_trigger_handler,
+ &sx9310_buffer_setup_ops);
+ if (ret < 0)
+ return ret;
+
+ return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static int __maybe_unused sx9310_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+ struct sx9310_data *data = iio_priv(indio_dev);
+ u8 ctrl0;
+ int ret;
+
+ disable_irq_nosync(data->client->irq);
+
+ mutex_lock(&data->mutex);
+ ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL0,
+ &data->suspend_ctrl0);
+
+ if (ret)
+ goto out;
+
+ ctrl0 = data->suspend_ctrl0 & ~SX9310_REG_PROX_CTRL0_EN_MASK;
+ ret = regmap_write(data->regmap, SX9310_REG_PROX_CTRL0, ctrl0);
+ if (ret)
+ goto out;
+
+ ret = regmap_write(data->regmap, SX9310_REG_PAUSE, 0);
+
+out:
+ mutex_unlock(&data->mutex);
+ return ret;
+}
+
+static int __maybe_unused sx9310_resume(struct device *dev)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+ struct sx9310_data *data = iio_priv(indio_dev);
+ int ret;
+
+ mutex_lock(&data->mutex);
+ ret = regmap_write(data->regmap, SX9310_REG_PAUSE, 1);
+ if (ret)
+ goto out;
+
+ ret = regmap_write(data->regmap, SX9310_REG_PROX_CTRL0,
+ data->suspend_ctrl0);
+
+out:
+ mutex_unlock(&data->mutex);
+
+ enable_irq(data->client->irq);
+
+ return ret;
+}
+
+static const struct dev_pm_ops sx9310_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(sx9310_suspend, sx9310_resume)
+};
+
+static const struct acpi_device_id sx9310_acpi_match[] = {
+ { "STH9310", SX9310_WHOAMI_VALUE },
+ { "STH9311", SX9311_WHOAMI_VALUE },
+ {},
+};
+MODULE_DEVICE_TABLE(acpi, sx9310_acpi_match);
+
+static const struct of_device_id sx9310_of_match[] = {
+ { .compatible = "semtech,sx9310" },
+ { .compatible = "semtech,sx9311" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, sx9310_of_match);
+
+static const struct i2c_device_id sx9310_id[] = {
+ { "sx9310", SX9310_WHOAMI_VALUE },
+ { "sx9311", SX9311_WHOAMI_VALUE },
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, sx9310_id);
+
+static struct i2c_driver sx9310_driver = {
+ .driver = {
+ .name = "sx9310",
+ .acpi_match_table = ACPI_PTR(sx9310_acpi_match),
+ .of_match_table = of_match_ptr(sx9310_of_match),
+ .pm = &sx9310_pm_ops,
+ },
+ .probe = sx9310_probe,
+ .id_table = sx9310_id,
+};
+module_i2c_driver(sx9310_driver);
+
+MODULE_AUTHOR("Gwendal Grignou <gwendal@chromium.org>");
+MODULE_AUTHOR("Daniel Campello <campello@chromium.org>");
+MODULE_DESCRIPTION("Driver for Semtech SX9310/SX9311 proximity sensor");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c
index 287d288e40c2..acb821cbad46 100644
--- a/drivers/iio/proximity/sx9500.c
+++ b/drivers/iio/proximity/sx9500.c
@@ -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);
diff --git a/drivers/iio/proximity/vcnl3020.c b/drivers/iio/proximity/vcnl3020.c
new file mode 100644
index 000000000000..37264f801ad0
--- /dev/null
+++ b/drivers/iio/proximity/vcnl3020.c
@@ -0,0 +1,257 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Support for Vishay VCNL3020 proximity sensor on i2c bus.
+ * Based on Vishay VCNL4000 driver code.
+ *
+ * TODO: interrupts.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/regmap.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#define VCNL3020_PROD_ID 0x21
+
+#define VCNL_COMMAND 0x80 /* Command register */
+#define VCNL_PROD_REV 0x81 /* Product ID and Revision ID */
+#define VCNL_PROXIMITY_RATE 0x82 /* Rate of Proximity Measurement */
+#define VCNL_LED_CURRENT 0x83 /* IR LED current for proximity mode */
+#define VCNL_PS_RESULT_HI 0x87 /* Proximity result register, MSB */
+#define VCNL_PS_RESULT_LO 0x88 /* Proximity result register, LSB */
+#define VCNL_PS_ICR 0x89 /* Interrupt Control Register */
+#define VCNL_PS_LO_THR_HI 0x8a /* High byte of low threshold value */
+#define VCNL_PS_LO_THR_LO 0x8b /* Low byte of low threshold value */
+#define VCNL_PS_HI_THR_HI 0x8c /* High byte of high threshold value */
+#define VCNL_PS_HI_THR_LO 0x8d /* Low byte of high threshold value */
+#define VCNL_ISR 0x8e /* Interrupt Status Register */
+#define VCNL_PS_MOD_ADJ 0x8f /* Proximity Modulator Timing Adjustment */
+
+/* Bit masks for COMMAND register */
+#define VCNL_PS_RDY BIT(5) /* proximity data ready? */
+#define VCNL_PS_OD BIT(3) /* start on-demand proximity
+ * measurement
+ */
+
+#define VCNL_ON_DEMAND_TIMEOUT_US 100000
+#define VCNL_POLL_US 20000
+
+/**
+ * struct vcnl3020_data - vcnl3020 specific data.
+ * @regmap: device register map.
+ * @dev: vcnl3020 device.
+ * @rev: revision id.
+ * @lock: lock for protecting access to device hardware registers.
+ */
+struct vcnl3020_data {
+ struct regmap *regmap;
+ struct device *dev;
+ u8 rev;
+ struct mutex lock;
+};
+
+/**
+ * struct vcnl3020_property - vcnl3020 property.
+ * @name: property name.
+ * @reg: i2c register offset.
+ * @conversion_func: conversion function.
+ */
+struct vcnl3020_property {
+ const char *name;
+ u32 reg;
+ u32 (*conversion_func)(u32 *val);
+};
+
+static u32 microamp_to_reg(u32 *val)
+{
+ /*
+ * An example of conversion from uA to reg val:
+ * 200000 uA == 200 mA == 20
+ */
+ return *val /= 10000;
+};
+
+static struct vcnl3020_property vcnl3020_led_current_property = {
+ .name = "vishay,led-current-microamp",
+ .reg = VCNL_LED_CURRENT,
+ .conversion_func = microamp_to_reg,
+};
+
+static int vcnl3020_get_and_apply_property(struct vcnl3020_data *data,
+ struct vcnl3020_property prop)
+{
+ int rc;
+ u32 val;
+
+ rc = device_property_read_u32(data->dev, prop.name, &val);
+ if (rc)
+ return 0;
+
+ if (prop.conversion_func)
+ prop.conversion_func(&val);
+
+ rc = regmap_write(data->regmap, prop.reg, val);
+ if (rc) {
+ dev_err(data->dev, "Error (%d) setting property (%s)\n",
+ rc, prop.name);
+ }
+
+ return rc;
+}
+
+static int vcnl3020_init(struct vcnl3020_data *data)
+{
+ int rc;
+ unsigned int reg;
+
+ rc = regmap_read(data->regmap, VCNL_PROD_REV, &reg);
+ if (rc) {
+ dev_err(data->dev,
+ "Error (%d) reading product revision\n", rc);
+ return rc;
+ }
+
+ if (reg != VCNL3020_PROD_ID) {
+ dev_err(data->dev,
+ "Product id (%x) did not match vcnl3020 (%x)\n", reg,
+ VCNL3020_PROD_ID);
+ return -ENODEV;
+ }
+
+ data->rev = reg;
+ mutex_init(&data->lock);
+
+ return vcnl3020_get_and_apply_property(data,
+ vcnl3020_led_current_property);
+};
+
+static int vcnl3020_measure_proximity(struct vcnl3020_data *data, int *val)
+{
+ int rc;
+ unsigned int reg;
+ __be16 res;
+
+ mutex_lock(&data->lock);
+
+ rc = regmap_write(data->regmap, VCNL_COMMAND, VCNL_PS_OD);
+ if (rc)
+ goto err_unlock;
+
+ /* wait for data to become ready */
+ rc = regmap_read_poll_timeout(data->regmap, VCNL_COMMAND, reg,
+ reg & VCNL_PS_RDY, VCNL_POLL_US,
+ VCNL_ON_DEMAND_TIMEOUT_US);
+ if (rc) {
+ dev_err(data->dev,
+ "Error (%d) reading vcnl3020 command register\n", rc);
+ goto err_unlock;
+ }
+
+ /* high & low result bytes read */
+ rc = regmap_bulk_read(data->regmap, VCNL_PS_RESULT_HI, &res,
+ sizeof(res));
+ if (rc)
+ goto err_unlock;
+
+ *val = be16_to_cpu(res);
+
+err_unlock:
+ mutex_unlock(&data->lock);
+
+ return rc;
+}
+
+static const struct iio_chan_spec vcnl3020_channels[] = {
+ {
+ .type = IIO_PROXIMITY,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ },
+};
+
+static int vcnl3020_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val,
+ int *val2, long mask)
+{
+ int rc;
+ struct vcnl3020_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ rc = vcnl3020_measure_proximity(data, val);
+ if (rc)
+ return rc;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info vcnl3020_info = {
+ .read_raw = vcnl3020_read_raw,
+};
+
+static const struct regmap_config vcnl3020_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = VCNL_PS_MOD_ADJ,
+};
+
+static int vcnl3020_probe(struct i2c_client *client)
+{
+ struct vcnl3020_data *data;
+ struct iio_dev *indio_dev;
+ struct regmap *regmap;
+ int rc;
+
+ regmap = devm_regmap_init_i2c(client, &vcnl3020_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(&client->dev, "regmap_init failed\n");
+ return PTR_ERR(regmap);
+ }
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ data->regmap = regmap;
+ data->dev = &client->dev;
+
+ rc = vcnl3020_init(data);
+ if (rc)
+ return rc;
+
+ indio_dev->info = &vcnl3020_info;
+ indio_dev->channels = vcnl3020_channels;
+ indio_dev->num_channels = ARRAY_SIZE(vcnl3020_channels);
+ indio_dev->name = "vcnl3020";
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct of_device_id vcnl3020_of_match[] = {
+ {
+ .compatible = "vishay,vcnl3020",
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, vcnl3020_of_match);
+
+static struct i2c_driver vcnl3020_driver = {
+ .driver = {
+ .name = "vcnl3020",
+ .of_match_table = vcnl3020_of_match,
+ },
+ .probe_new = vcnl3020_probe,
+};
+module_i2c_driver(vcnl3020_driver);
+
+MODULE_AUTHOR("Ivan Mikhaylov <i.mikhaylov@yadro.com>");
+MODULE_DESCRIPTION("Vishay VCNL3020 proximity sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/proximity/vl53l0x-i2c.c b/drivers/iio/proximity/vl53l0x-i2c.c
index b48216cc1858..5fbda9475ba9 100644
--- a/drivers/iio/proximity/vl53l0x-i2c.c
+++ b/drivers/iio/proximity/vl53l0x-i2c.c
@@ -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;
diff --git a/drivers/iio/resolver/ad2s1200.c b/drivers/iio/resolver/ad2s1200.c
index a391f46ee06b..6007abad116b 100644
--- a/drivers/iio/resolver/ad2s1200.c
+++ b/drivers/iio/resolver/ad2s1200.c
@@ -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;
diff --git a/drivers/iio/resolver/ad2s90.c b/drivers/iio/resolver/ad2s90.c
index a41f5cb10da5..d6a91f137e13 100644
--- a/drivers/iio/resolver/ad2s90.c
+++ b/drivers/iio/resolver/ad2s90.c
@@ -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;
diff --git a/drivers/iio/temperature/hid-sensor-temperature.c b/drivers/iio/temperature/hid-sensor-temperature.c
index eda55b9c1e9b..81688f1b932f 100644
--- a/drivers/iio/temperature/hid-sensor-temperature.c
+++ b/drivers/iio/temperature/hid-sensor-temperature.c
@@ -7,8 +7,6 @@
#include <linux/hid-sensor-hub.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
-#include <linux/iio/triggered_buffer.h>
-#include <linux/iio/trigger_consumer.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@@ -225,17 +223,12 @@ 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;
- ret = devm_iio_triggered_buffer_setup(&pdev->dev, indio_dev,
- &iio_pollfunc_store_time, NULL, NULL);
- if (ret)
- return ret;
-
atomic_set(&temp_st->common_attributes.data_ready, 0);
+
ret = hid_sensor_setup_trigger(indio_dev, name,
&temp_st->common_attributes);
if (ret)
@@ -258,7 +251,7 @@ static int hid_temperature_probe(struct platform_device *pdev)
error_remove_callback:
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TEMPERATURE);
error_remove_trigger:
- hid_sensor_remove_trigger(&temp_st->common_attributes);
+ hid_sensor_remove_trigger(indio_dev, &temp_st->common_attributes);
return ret;
}
@@ -270,7 +263,7 @@ static int hid_temperature_remove(struct platform_device *pdev)
struct temperature_state *temp_st = iio_priv(indio_dev);
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TEMPERATURE);
- hid_sensor_remove_trigger(&temp_st->common_attributes);
+ hid_sensor_remove_trigger(indio_dev, &temp_st->common_attributes);
return 0;
}
diff --git a/drivers/iio/temperature/iqs620at-temp.c b/drivers/iio/temperature/iqs620at-temp.c
index 3fd52b3eb030..fe126e1fb783 100644
--- a/drivers/iio/temperature/iqs620at-temp.c
+++ b/drivers/iio/temperature/iqs620at-temp.c
@@ -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;
diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c
index d39c0d6b77f1..55ff28a0f1c7 100644
--- a/drivers/iio/temperature/ltc2983.c
+++ b/drivers/iio/temperature/ltc2983.c
@@ -390,8 +390,8 @@ static struct ltc2983_custom_sensor *__ltc2983_custom_sensor_new(
* For custom steinhart, the full u32 is taken. For all the others
* the MSB is discarded.
*/
- const u8 n_size = (is_steinhart == true) ? 4 : 3;
- const u8 e_size = (is_steinhart == true) ? sizeof(u32) : sizeof(u64);
+ const u8 n_size = is_steinhart ? 4 : 3;
+ const u8 e_size = is_steinhart ? sizeof(u32) : sizeof(u64);
n_entries = of_property_count_elems_of_size(np, propname, e_size);
/* n_entries must be an even number */
@@ -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;
diff --git a/drivers/iio/temperature/max31856.c b/drivers/iio/temperature/max31856.c
index b4cb21ab2e85..1954322e43be 100644
--- a/drivers/iio/temperature/max31856.c
+++ b/drivers/iio/temperature/max31856.c
@@ -14,6 +14,7 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/util_macros.h>
+#include <asm/unaligned.h>
#include <dt-bindings/iio/temperature/thermocouple.h>
/*
* The MSB of the register value determines whether the following byte will
@@ -168,7 +169,7 @@ static int max31856_thermocouple_read(struct max31856_data *data,
if (ret)
return ret;
/* Skip last 5 dead bits of LTCBL */
- *val = (reg_val[0] << 16 | reg_val[1] << 8 | reg_val[2]) >> 5;
+ *val = get_unaligned_be24(&reg_val[0]) >> 5;
/* Check 7th bit of LTCBH reg. value for sign*/
if (reg_val[0] & 0x80)
*val -= 0x80000;
@@ -185,7 +186,7 @@ static int max31856_thermocouple_read(struct max31856_data *data,
/* Get Cold Junction Temp. offset register value */
offset_cjto = reg_val[0];
/* Get CJTH and CJTL value and skip last 2 dead bits of CJTL */
- *val = (reg_val[1] << 8 | reg_val[2]) >> 2;
+ *val = get_unaligned_be16(&reg_val[1]) >> 2;
/* As per datasheet add offset into CJTH and CJTL */
*val += offset_cjto;
/* Check 7th bit of CJTH reg. value for sign */
@@ -416,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;
diff --git a/drivers/iio/temperature/maxim_thermocouple.c b/drivers/iio/temperature/maxim_thermocouple.c
index 8d21116c7a22..0297e215b61a 100644
--- a/drivers/iio/temperature/maxim_thermocouple.c
+++ b/drivers/iio/temperature/maxim_thermocouple.c
@@ -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;
diff --git a/drivers/iio/temperature/mlx90614.c b/drivers/iio/temperature/mlx90614.c
index b7c56ddf884f..ef0fec94d269 100644
--- a/drivers/iio/temperature/mlx90614.c
+++ b/drivers/iio/temperature/mlx90614.c
@@ -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;
diff --git a/drivers/iio/temperature/mlx90632.c b/drivers/iio/temperature/mlx90632.c
index eaca6ba06864..51b812bcff2e 100644
--- a/drivers/iio/temperature/mlx90632.c
+++ b/drivers/iio/temperature/mlx90632.c
@@ -164,8 +164,8 @@ static s32 mlx90632_pwr_continuous(struct regmap *regmap)
}
/**
- * mlx90632_perform_measurement - Trigger and retrieve current measurement cycle
- * @*data: pointer to mlx90632_data object containing regmap information
+ * mlx90632_perform_measurement() - Trigger and retrieve current measurement cycle
+ * @data: pointer to mlx90632_data object containing regmap information
*
* Perform a measurement and return latest measurement cycle position reported
* by sensor. This is a blocking function for 500ms, as that is default sensor
@@ -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;
diff --git a/drivers/iio/temperature/tmp006.c b/drivers/iio/temperature/tmp006.c
index cc45d8345eb9..54976c7dad92 100644
--- a/drivers/iio/temperature/tmp006.c
+++ b/drivers/iio/temperature/tmp006.c
@@ -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;
diff --git a/drivers/iio/temperature/tmp007.c b/drivers/iio/temperature/tmp007.c
index 7df234d96f94..f90fe9e5617b 100644
--- a/drivers/iio/temperature/tmp007.c
+++ b/drivers/iio/temperature/tmp007.c
@@ -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;
diff --git a/drivers/iio/temperature/tsys01.c b/drivers/iio/temperature/tsys01.c
index d41f050c2fea..2c631a1ca33b 100644
--- a/drivers/iio/temperature/tsys01.c
+++ b/drivers/iio/temperature/tsys01.c
@@ -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);
diff --git a/drivers/iio/temperature/tsys02d.c b/drivers/iio/temperature/tsys02d.c
index 6735af400b22..fc96e5f9d3fc 100644
--- a/drivers/iio/temperature/tsys02d.c
+++ b/drivers/iio/temperature/tsys02d.c
@@ -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);
diff --git a/drivers/iio/trigger/iio-trig-hrtimer.c b/drivers/iio/trigger/iio-trig-hrtimer.c
index a5e670726717..f59bf8d58586 100644
--- a/drivers/iio/trigger/iio-trig-hrtimer.c
+++ b/drivers/iio/trigger/iio-trig-hrtimer.c
@@ -4,7 +4,7 @@
*
* Copyright (C) Intuitive Aerial AB
* Written by Marten Svanfeldt, marten@intuitiveaerial.com
- * Copyright (C) 2012, Analog Device Inc.
+ * Copyright (C) 2012, Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
* Copyright (C) 2015, Intel Corporation
*/
diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c
index 7d8962d6566a..3aa9e8bba005 100644
--- a/drivers/iio/trigger/stm32-timer-trigger.c
+++ b/drivers/iio/trigger/stm32-timer-trigger.c
@@ -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)