diff options
Diffstat (limited to 'drivers/iio')
383 files changed, 7503 insertions, 1579 deletions
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 1080637ca40e..2e0c62c39155 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -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 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 265722e4b13f..5b7a467c7b27 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -1038,7 +1038,6 @@ static int bma180_probe(struct i2c_client *client, goto err_chip_disable; mutex_init(&data->mutex); - indio_dev->dev.parent = dev; indio_dev->channels = data->part_info->channels; indio_dev->num_channels = data->part_info->num_channels; indio_dev->name = id->name; 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..24864d9dfab5 100644 --- a/drivers/iio/accel/bmc150-accel-core.c +++ b/drivers/iio/accel/bmc150-accel-core.c @@ -1411,7 +1411,7 @@ static int bmc150_accel_buffer_postenable(struct iio_dev *indio_dev) int ret = 0; if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) - return iio_triggered_buffer_postenable(indio_dev); + return 0; mutex_lock(&data->mutex); @@ -1443,7 +1443,7 @@ static int bmc150_accel_buffer_predisable(struct iio_dev *indio_dev) struct bmc150_accel_data *data = iio_priv(indio_dev); if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) - return iio_triggered_buffer_predisable(indio_dev); + return 0; mutex_lock(&data->mutex); @@ -1574,7 +1574,6 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq, mutex_init(&data->mutex); - indio_dev->dev.parent = dev; indio_dev->channels = data->chip_info->channels; indio_dev->num_channels = data->chip_info->num_channels; indio_dev->name = name ? name : data->chip_info->name; 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 ef89bded7390..de2868c28d95 100644 --- a/drivers/iio/accel/dmard06.c +++ b/drivers/iio/accel/dmard06.c @@ -161,7 +161,6 @@ static int dmard06_probe(struct i2c_client *client, dmard06->chip_id = ret; i2c_set_clientdata(client, indio_dev); - indio_dev->dev.parent = &client->dev; indio_dev->name = DMARD06_DRV_NAME; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = dmard06_channels; 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 0ec0533448bc..4c5e594024f8 100644 --- a/drivers/iio/accel/hid-sensor-accel-3d.c +++ b/drivers/iio/accel/hid-sensor-accel-3d.c @@ -384,7 +384,6 @@ static int hid_accel_3d_probe(struct platform_device *pdev) goto error_free_dev_mem; } - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &accel_3d_info; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; 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.c b/drivers/iio/accel/kxsd9.c index 0b876b2dc5bd..66b2e4cf24cf 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -252,8 +252,6 @@ static int kxsd9_buffer_postdisable(struct iio_dev *indio_dev) static const struct iio_buffer_setup_ops kxsd9_buffer_setup_ops = { .preenable = kxsd9_buffer_preenable, - .postenable = iio_triggered_buffer_postenable, - .predisable = iio_triggered_buffer_predisable, .postdisable = kxsd9_buffer_postdisable, }; @@ -411,7 +409,6 @@ int kxsd9_common_probe(struct device *dev, indio_dev->channels = kxsd9_channels; indio_dev->num_channels = ARRAY_SIZE(kxsd9_channels); indio_dev->name = name; - indio_dev->dev.parent = dev; indio_dev->info = &kxsd9_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->available_scan_masks = kxsd9_scan_masks; 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..7e99bcb3398d 100644 --- a/drivers/iio/accel/mma7455_core.c +++ b/drivers/iio/accel/mma7455_core.c @@ -260,7 +260,6 @@ int mma7455_core_probe(struct device *dev, struct regmap *regmap, indio_dev->info = &mma7455_info; indio_dev->name = name; - indio_dev->dev.parent = dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = mma7455_channels; indio_dev->num_channels = ARRAY_SIZE(mma7455_channels); 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 813bca7cfc3e..ba27f8673131 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -1592,7 +1592,6 @@ static int mma8452_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); indio_dev->info = &mma8452_info; indio_dev->name = id->name; - indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = data->chip_info->channels; indio_dev->num_channels = data->chip_info->num_channels; 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 9d07642c0de1..f877263dc6ef 100644 --- a/drivers/iio/accel/mxc4005.c +++ b/drivers/iio/accel/mxc4005.c @@ -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_buffer.c b/drivers/iio/accel/st_accel_buffer.c index b5c814ef1637..492263589e04 100644 --- a/drivers/iio/accel/st_accel_buffer.c +++ b/drivers/iio/accel/st_accel_buffer.c @@ -33,13 +33,9 @@ static int st_accel_buffer_postenable(struct iio_dev *indio_dev) { int err; - err = iio_triggered_buffer_postenable(indio_dev); - if (err < 0) - return err; - err = st_sensors_set_axis_enable(indio_dev, indio_dev->active_scan_mask[0]); if (err < 0) - goto st_accel_buffer_predisable; + return err; err = st_sensors_set_enable(indio_dev, true); if (err < 0) @@ -49,27 +45,19 @@ static int st_accel_buffer_postenable(struct iio_dev *indio_dev) st_accel_buffer_enable_all_axis: st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); -st_accel_buffer_predisable: - iio_triggered_buffer_predisable(indio_dev); return err; } static int st_accel_buffer_predisable(struct iio_dev *indio_dev) { - int err, err2; + int err; err = st_sensors_set_enable(indio_dev, false); if (err < 0) - goto st_accel_buffer_predisable; - - err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); - -st_accel_buffer_predisable: - err2 = iio_triggered_buffer_predisable(indio_dev); - if (!err) - err = err2; + return err; - return err; + return st_sensors_set_axis_enable(indio_dev, + ST_SENSORS_ENABLE_ALL_AXIS); } static const struct iio_buffer_setup_ops st_accel_buffer_setup_ops = { 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 ff3569635ce0..66d9cc073157 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -294,7 +294,7 @@ config ASPEED_ADC config AT91_ADC tristate "Atmel AT91 ADC" - depends on ARCH_AT91 + depends on ARCH_AT91 || COMPILE_TEST depends on INPUT && SYSFS select IIO_BUFFER select IIO_TRIGGERED_BUFFER @@ -500,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. diff --git a/drivers/iio/adc/ab8500-gpadc.c b/drivers/iio/adc/ab8500-gpadc.c index fd5b18d7f0c2..7fdc5d2d1d35 100644 --- a/drivers/iio/adc/ab8500-gpadc.c +++ b/drivers/iio/adc/ab8500-gpadc.c @@ -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..8dce06e9e69c 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 = "ad7127-4", + .chip_id = CHIPID_AD7124_4, .num_inputs = 8, }, [ID_AD7124_8] = { + .name = "ad7127-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 4e816d714ad2..66c55ae67791 100644 --- a/drivers/iio/adc/ad7476.c +++ b/drivers/iio/adc/ad7476.c @@ -300,9 +300,6 @@ static int ad7476_probe(struct spi_device *spi) st->spi = spi; - /* Establish that the iio_dev is a child of the spi device */ - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = st->chip_info->channel; 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 b33fe6c3907e..42e7e8e595d1 100644 --- a/drivers/iio/adc/ad7780.c +++ b/drivers/iio/adc/ad7780.c @@ -320,7 +320,6 @@ static int ad7780_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = &st->chip_info->channel; diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c index 48432b6f6002..d57ad966e17c 100644 --- a/drivers/iio/adc/ad7791.c +++ b/drivers/iio/adc/ad7791.c @@ -425,8 +425,6 @@ static int ad7791_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = st->info->channels; diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c index 808485f42415..5e980a06258e 100644 --- a/drivers/iio/adc/ad7793.c +++ b/drivers/iio/adc/ad7793.c @@ -818,8 +818,6 @@ static int ad7793_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = st->chip_info->channels; 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/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c index dd3d54b3bc8b..86039e9ecaca 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -345,10 +345,6 @@ static int ad_sd_buffer_postenable(struct iio_dev *indio_dev) unsigned int channel; int ret; - ret = iio_triggered_buffer_postenable(indio_dev); - if (ret < 0) - return ret; - channel = find_first_bit(indio_dev->active_scan_mask, indio_dev->masklength); ret = ad_sigma_delta_set_channel(sigma_delta, @@ -402,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); @@ -419,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; } @@ -441,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 index 7af8f0510535..86b6b65916ee 100644 --- a/drivers/iio/adc/adi-axi-adc.c +++ b/drivers/iio/adc/adi-axi-adc.c @@ -435,7 +435,6 @@ static int adi_axi_adc_probe(struct platform_device *pdev) } indio_dev->info = &adi_axi_adc_info; - indio_dev->dev.parent = &pdev->dev; indio_dev->name = "adi-axi-adc"; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->num_channels = conv->chip_info->num_channels; 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 9abbbdcc7420..de9583d6cddd 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -347,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 @@ -369,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 @@ -402,6 +402,7 @@ struct at91_adc_state { wait_queue_head_t wq_data_available; struct at91_adc_dma dma_st; struct at91_adc_touch touch_st; + struct iio_dev *indio_dev; u16 buffer[AT91_BUFFER_MAX_HWORDS]; /* * lock to prevent concurrent 'single conversion' requests through @@ -642,13 +643,13 @@ static u16 at91_adc_touch_pos(struct at91_adc_state *st, int reg) /* first half of register is the x or y, second half is the scale */ val = at91_adc_readl(st, reg); if (!val) - dev_dbg(&iio_priv_to_dev(st)->dev, "pos is 0\n"); + dev_dbg(&st->indio_dev->dev, "pos is 0\n"); pos = val & AT91_SAMA5D2_XYZ_MASK; result = (pos << AT91_SAMA5D2_MAX_POS_BITS) - pos; scale = (val >> 16) & AT91_SAMA5D2_XYZ_MASK; if (scale == 0) { - dev_err(&iio_priv_to_dev(st)->dev, "scale is 0\n"); + dev_err(&st->indio_dev->dev, "scale is 0\n"); return 0; } result /= scale; @@ -937,14 +938,6 @@ static int at91_adc_buffer_preenable(struct iio_dev *indio_dev) return 0; } -static int at91_adc_buffer_postenable(struct iio_dev *indio_dev) -{ - if (at91_adc_current_chan_is_touch(indio_dev)) - return 0; - - return iio_triggered_buffer_postenable(indio_dev); -} - static int at91_adc_buffer_postdisable(struct iio_dev *indio_dev) { struct at91_adc_state *st = iio_priv(indio_dev); @@ -995,19 +988,9 @@ static int at91_adc_buffer_postdisable(struct iio_dev *indio_dev) return 0; } -static int at91_adc_buffer_predisable(struct iio_dev *indio_dev) -{ - if (at91_adc_current_chan_is_touch(indio_dev)) - return 0; - - return iio_triggered_buffer_predisable(indio_dev); -} - static const struct iio_buffer_setup_ops at91_buffer_setup_ops = { .preenable = &at91_adc_buffer_preenable, .postdisable = &at91_adc_buffer_postdisable, - .postenable = &at91_adc_buffer_postenable, - .predisable = &at91_adc_buffer_predisable, }; static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio, @@ -1204,9 +1187,9 @@ static unsigned at91_adc_startup_time(unsigned startup_time_min, return i; } -static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq) +static void at91_adc_setup_samp_freq(struct iio_dev *indio_dev, unsigned freq) { - struct iio_dev *indio_dev = iio_priv_to_dev(st); + struct at91_adc_state *st = iio_priv(indio_dev); unsigned f_per, prescal, startup, mr; f_per = clk_get_rate(st->per_clk); @@ -1275,9 +1258,9 @@ static void at91_adc_pen_detect_interrupt(struct at91_adc_state *st) st->touch_st.touching = true; } -static void at91_adc_no_pen_detect_interrupt(struct at91_adc_state *st) +static void at91_adc_no_pen_detect_interrupt(struct iio_dev *indio_dev) { - struct iio_dev *indio_dev = iio_priv_to_dev(st); + struct at91_adc_state *st = iio_priv(indio_dev); at91_adc_writel(st, AT91_SAMA5D2_TRGR, AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER); @@ -1297,7 +1280,7 @@ static void at91_adc_workq_handler(struct work_struct *workq) struct at91_adc_touch, workq); struct at91_adc_state *st = container_of(touch_st, struct at91_adc_state, touch_st); - struct iio_dev *indio_dev = iio_priv_to_dev(st); + struct iio_dev *indio_dev = st->indio_dev; iio_push_to_buffers(indio_dev, st->buffer); } @@ -1318,7 +1301,7 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private) at91_adc_pen_detect_interrupt(st); } else if ((status & AT91_SAMA5D2_IER_NOPEN)) { /* nopen detected IRQ */ - at91_adc_no_pen_detect_interrupt(st); + at91_adc_no_pen_detect_interrupt(indio); } else if ((status & AT91_SAMA5D2_ISR_PENS) && ((status & rdy_mask) == rdy_mask)) { /* periodic trigger IRQ - during pen sense */ @@ -1486,7 +1469,7 @@ static int at91_adc_write_raw(struct iio_dev *indio_dev, val > st->soc_info.max_sample_rate) return -EINVAL; - at91_adc_setup_samp_freq(st, val); + at91_adc_setup_samp_freq(indio_dev, val); return 0; default: return -EINVAL; @@ -1624,8 +1607,10 @@ static int at91_adc_update_scan_mode(struct iio_dev *indio_dev, return 0; } -static void at91_adc_hw_init(struct at91_adc_state *st) +static void at91_adc_hw_init(struct iio_dev *indio_dev) { + struct at91_adc_state *st = iio_priv(indio_dev); + at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST); at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff); /* @@ -1635,7 +1620,7 @@ static void at91_adc_hw_init(struct at91_adc_state *st) at91_adc_writel(st, AT91_SAMA5D2_MR, AT91_SAMA5D2_MR_TRANSFER(2) | AT91_SAMA5D2_MR_ANACH); - at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate); + at91_adc_setup_samp_freq(indio_dev, st->soc_info.min_sample_rate); /* configure extended mode register */ at91_adc_config_emr(st); @@ -1710,7 +1695,6 @@ static int at91_adc_probe(struct platform_device *pdev) if (!indio_dev) return -ENOMEM; - indio_dev->dev.parent = &pdev->dev; indio_dev->name = dev_name(&pdev->dev); indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; indio_dev->info = &at91_adc_info; @@ -1718,6 +1702,7 @@ static int at91_adc_probe(struct platform_device *pdev) indio_dev->num_channels = ARRAY_SIZE(at91_adc_channels); st = iio_priv(indio_dev); + st->indio_dev = indio_dev; bitmap_set(&st->touch_st.channels_bitmask, AT91_SAMA5D2_TOUCH_X_CHAN_IDX, 1); @@ -1829,7 +1814,7 @@ static int at91_adc_probe(struct platform_device *pdev) goto vref_disable; } - at91_adc_hw_init(st); + at91_adc_hw_init(indio_dev); ret = clk_prepare_enable(st->per_clk); if (ret) @@ -1945,7 +1930,7 @@ static __maybe_unused int at91_adc_resume(struct device *dev) if (ret) goto vref_disable_resume; - at91_adc_hw_init(st); + at91_adc_hw_init(indio_dev); /* reconfiguring trigger hardware state */ if (!iio_buffer_enabled(indio_dev)) diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 0368b6dc6d60..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(); @@ -1161,7 +1161,7 @@ static int at91_adc_probe(struct platform_device *pdev) st = iio_priv(idev); if (pdev->dev.of_node) - ret = at91_adc_probe_dt(st, pdev); + ret = at91_adc_probe_dt(idev, pdev); else ret = at91_adc_probe_pdata(st, pdev); @@ -1172,7 +1172,6 @@ static int at91_adc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, idev); - idev->dev.parent = &pdev->dev; idev->name = dev_name(&pdev->dev); idev->modes = INDIO_DIRECT_MODE; idev->info = &at91_adc_info; @@ -1301,11 +1300,11 @@ static int at91_adc_probe(struct platform_device *pdev) goto error_disable_adc_clk; } } else { - ret = at91_ts_register(st, pdev); + ret = at91_ts_register(idev, pdev); if (ret) goto error_disable_adc_clk; - at91_ts_hw_init(st, adc_clk_khz); + at91_ts_hw_init(idev, adc_clk_khz); } ret = iio_device_register(idev); 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..84a1733e5913 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. @@ -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 6bda4f4d89fe..7d23b6c33284 100644 --- a/drivers/iio/adc/exynos_adc.c +++ b/drivers/iio/adc/exynos_adc.c @@ -867,8 +867,6 @@ static int exynos_adc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, indio_dev); indio_dev->name = dev_name(&pdev->dev); - indio_dev->dev.parent = &pdev->dev; - indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->info = &exynos_adc_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = exynos_adc_iio_channels; diff --git a/drivers/iio/adc/fsl-imx25-gcq.c b/drivers/iio/adc/fsl-imx25-gcq.c index b0a4dc88ba9b..8cb51cf7a816 100644 --- a/drivers/iio/adc/fsl-imx25-gcq.c +++ b/drivers/iio/adc/fsl-imx25-gcq.c @@ -350,7 +350,6 @@ static int mx25_gcq_probe(struct platform_device *pdev) goto err_clk_unprepare; } - indio_dev->dev.parent = &pdev->dev; indio_dev->channels = mx25_gcq_channels; indio_dev->num_channels = ARRAY_SIZE(mx25_gcq_channels); indio_dev->info = &mx25_gcq_iio_info; 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..5ed63e874292 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -273,7 +273,7 @@ static int ina2xx_read_raw(struct iio_dev *indio_dev, * Available averaging rates for ina226. The indices correspond with * the bit values expected by the chip (according to the ina226 datasheet, * table 3 AVG bit settings, found at - * http://www.ti.com/lit/ds/symlink/ina226.pdf. + * https://www.ti.com/lit/ds/symlink/ina226.pdf. */ static const int ina226_avg_tab[] = { 1, 4, 16, 64, 128, 256, 512, 1024 }; @@ -1015,8 +1015,6 @@ static int ina2xx_probe(struct i2c_client *client, } indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; - indio_dev->dev.parent = &client->dev; - indio_dev->dev.of_node = client->dev.of_node; if (id->driver_data == ina226) { indio_dev->channels = ina226_channels; indio_dev->num_channels = ARRAY_SIZE(ina226_channels); 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 a6d2e1f27e76..75394350eb4c 100644 --- a/drivers/iio/adc/intel_mrfld_adc.c +++ b/drivers/iio/adc/intel_mrfld_adc.c @@ -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 = <c2471_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 = <c2485_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 = <c2497core_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..01b20e420ac4 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> @@ -225,7 +226,6 @@ static int max1118_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->dev.parent = &spi->dev; indio_dev->info = &max1118_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = max1118_channels; @@ -281,8 +281,6 @@ static const struct spi_device_id max1118_id[] = { }; MODULE_DEVICE_TABLE(spi, max1118_id); -#ifdef CONFIG_OF - static const struct of_device_id max1118_dt_ids[] = { { .compatible = "maxim,max1117" }, { .compatible = "maxim,max1118" }, @@ -291,12 +289,10 @@ static const struct of_device_id max1118_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, max1118_dt_ids); -#endif - static struct spi_driver max1118_spi_driver = { .driver = { .name = "max1118", - .of_match_table = of_match_ptr(max1118_dt_ids), + .of_match_table = max1118_dt_ids, }, .probe = max1118_probe, .remove = max1118_remove, diff --git a/drivers/iio/adc/max1241.c b/drivers/iio/adc/max1241.c index 541939c7abca..0cbbb3c56d08 100644 --- a/drivers/iio/adc/max1241.c +++ b/drivers/iio/adc/max1241.c @@ -192,7 +192,6 @@ static int max1241_probe(struct spi_device *spi) dev_dbg(dev, "no shutdown pin passed, low-power mode disabled"); indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->dev.parent = dev; indio_dev->info = &max1241_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = max1241_channels; diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c index 9d92017c79b2..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,7 +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 + * @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 @@ -1529,8 +1529,6 @@ done: return IRQ_HANDLED; } -#ifdef CONFIG_OF - #define MAX1363_COMPATIBLE(of_compatible, cfg) { \ .compatible = of_compatible, \ .data = &max1363_chip_info_tbl[cfg], \ @@ -1578,7 +1576,6 @@ static const struct of_device_id max1363_of_match[] = { { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, max1363_of_match); -#endif static int max1363_probe(struct i2c_client *client, const struct i2c_device_id *id) @@ -1593,7 +1590,6 @@ static int max1363_probe(struct i2c_client *client, if (!indio_dev) return -ENOMEM; - indio_dev->dev.of_node = client->dev.of_node; ret = iio_map_array_register(indio_dev, client->dev.platform_data); if (ret < 0) return ret; @@ -1614,7 +1610,7 @@ static int max1363_probe(struct i2c_client *client, /* this is only used for device removal purposes */ i2c_set_clientdata(client, indio_dev); - st->chip_info = of_device_get_match_data(&client->dev); + st->chip_info = device_get_match_data(&client->dev); if (!st->chip_info) st->chip_info = &max1363_chip_info_tbl[id->driver_data]; st->client = client; @@ -1652,9 +1648,6 @@ static int max1363_probe(struct i2c_client *client, if (ret) goto error_disable_reg; - /* Establish that the iio_dev is a child of the i2c device */ - indio_dev->dev.parent = &client->dev; - indio_dev->dev.of_node = client->dev.of_node; indio_dev->name = id->name; indio_dev->channels = st->chip_info->channels; indio_dev->num_channels = st->chip_info->num_channels; @@ -1760,7 +1753,7 @@ MODULE_DEVICE_TABLE(i2c, max1363_id); static struct i2c_driver max1363_driver = { .driver = { .name = "max1363", - .of_match_table = of_match_ptr(max1363_of_match), + .of_match_table = max1363_of_match, }, .probe = max1363_probe, .remove = max1363_remove, 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 d86c0b5d80a3..5f1706d1c3c0 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,9 @@ #include <linux/err.h> #include <linux/i2c.h> #include <linux/module.h> +#include <linux/mod_devicetable.h> #include <linux/delay.h> #include <linux/sysfs.h> -#include <linux/of.h> #include <asm/unaligned.h> #include <linux/iio/iio.h> @@ -347,8 +347,6 @@ static int mcp3422_probe(struct i2c_client *client, mutex_init(&adc->lock); - indio_dev->dev.parent = &client->dev; - indio_dev->dev.of_node = client->dev.of_node; indio_dev->name = dev_name(&client->dev); indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &mcp3422_info; @@ -404,18 +402,16 @@ static const struct i2c_device_id mcp3422_id[] = { }; MODULE_DEVICE_TABLE(i2c, mcp3422_id); -#ifdef CONFIG_OF static const struct of_device_id mcp3422_of_match[] = { { .compatible = "mcp3422" }, { } }; MODULE_DEVICE_TABLE(of, mcp3422_of_match); -#endif static struct i2c_driver mcp3422_driver = { .driver = { .name = "mcp3422", - .of_match_table = of_match_ptr(mcp3422_of_match), + .of_match_table = mcp3422_of_match, }, .probe = mcp3422_probe, .id_table = mcp3422_id, 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..93c2252c0b89 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -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/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..b4b73c9920b4 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; 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.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 0f2c1738a90d..99b43f28e879 100644 --- a/drivers/iio/adc/sun4i-gpadc-iio.c +++ b/drivers/iio/adc/sun4i-gpadc-iio.c @@ -619,8 +619,6 @@ static int sun4i_gpadc_probe(struct platform_device *pdev) info->indio_dev = indio_dev; init_completion(&info->completion); indio_dev->name = dev_name(&pdev->dev); - indio_dev->dev.parent = &pdev->dev; - indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->info = &sun4i_gpadc_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/ti-adc081c.c b/drivers/iio/adc/ti-adc081c.c index 0235863ff77b..9426f70a8005 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> @@ -181,8 +181,6 @@ static int adc081c_probe(struct i2c_client *client, if (err < 0) return err; - iio->dev.parent = &client->dev; - iio->dev.of_node = client->dev.of_node; iio->name = dev_name(&client->dev); iio->modes = INDIO_DIRECT_MODE; iio->info = &adc081c_info; @@ -232,7 +230,6 @@ static const struct i2c_device_id adc081c_id[] = { }; MODULE_DEVICE_TABLE(i2c, adc081c_id); -#ifdef CONFIG_OF static const struct of_device_id adc081c_of_match[] = { { .compatible = "ti,adc081c" }, { .compatible = "ti,adc101c" }, @@ -240,7 +237,6 @@ static const struct of_device_id adc081c_of_match[] = { { } }; MODULE_DEVICE_TABLE(of, adc081c_of_match); -#endif #ifdef CONFIG_ACPI static const struct acpi_device_id adc081c_acpi_match[] = { @@ -255,7 +251,7 @@ MODULE_DEVICE_TABLE(acpi, adc081c_acpi_match); static struct i2c_driver adc081c_driver = { .driver = { .name = "adc081c", - .of_match_table = of_match_ptr(adc081c_of_match), + .of_match_table = adc081c_of_match, .acpi_match_table = ACPI_PTR(adc081c_acpi_match), }, .probe = adc081c_probe, 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..9017e1e24273 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> @@ -187,8 +188,6 @@ static const struct iio_info adc084s021_info = { static const struct iio_buffer_setup_ops adc084s021_buffer_setup_ops = { .preenable = adc084s021_buffer_preenable, - .postenable = iio_triggered_buffer_postenable, - .predisable = iio_triggered_buffer_predisable, .postdisable = adc084s021_buffer_postdisable, }; @@ -211,8 +210,6 @@ static int adc084s021_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); /* Initiate the Industrial I/O device */ - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &adc084s021_info; @@ -258,7 +255,7 @@ MODULE_DEVICE_TABLE(spi, adc084s021_id); static struct spi_driver adc084s021_driver = { .driver = { .name = ADC084S021_DRIVER_NAME, - .of_match_table = of_match_ptr(adc084s021_of_match), + .of_match_table = adc084s021_of_match, }, .probe = adc084s021_probe, .id_table = adc084s021_id, 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..f42ab112986e 100644 --- a/drivers/iio/adc/ti-ads1015.c +++ b/drivers/iio/adc/ti-ads1015.c @@ -788,8 +788,6 @@ static int ads1015_buffer_postdisable(struct iio_dev *indio_dev) static const struct iio_buffer_setup_ops ads1015_buffer_setup_ops = { .preenable = ads1015_buffer_preenable, - .postenable = iio_triggered_buffer_postenable, - .predisable = iio_triggered_buffer_predisable, .postdisable = ads1015_buffer_postdisable, .validate_scan_mask = &iio_validate_scan_mask_onehot, }; @@ -939,8 +937,6 @@ static int ads1015_probe(struct i2c_client *client, mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; - indio_dev->dev.of_node = client->dev.of_node; indio_dev->name = ADS1015_DRV_NAME; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/ti-ads124s08.c b/drivers/iio/adc/ti-ads124s08.c index f1ee3b1e2827..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> @@ -325,8 +325,6 @@ static int ads124s_probe(struct spi_device *spi) ads124s_priv->spi = spi; indio_dev->name = spi_id->name; - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = ads124s_priv->chip_info->channels; indio_dev->num_channels = ads124s_priv->chip_info->num_channels; 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 d7fecab9252e..d0b7ef296afb 100644 --- a/drivers/iio/adc/xilinx-xadc-core.c +++ b/drivers/iio/adc/xilinx-xadc-core.c @@ -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/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-triggered-buffer.c b/drivers/iio/buffer/industrialio-triggered-buffer.c index e8046c1ecd6b..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; diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig index 7f21afd73b1c..10bb431bc3ce 100644 --- a/drivers/iio/chemical/Kconfig +++ b/drivers/iio/chemical/Kconfig @@ -85,6 +85,39 @@ config PMS7003 To compile this driver as a module, choose M here: the module will be called pms7003. +config SCD30_CORE + tristate "SCD30 carbon dioxide sensor driver" + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say Y here to build support for the Sensirion SCD30 sensor with carbon + dioxide, relative humidity and temperature sensing capabilities. + + To compile this driver as a module, choose M here: the module will + be called scd30_core. + +config SCD30_I2C + tristate "SCD30 carbon dioxide sensor I2C driver" + depends on SCD30_CORE && I2C + select CRC8 + help + Say Y here to build support for the Sensirion SCD30 I2C interface + driver. + + To compile this driver as a module, choose M here: the module will + be called scd30_i2c. + +config SCD30_SERIAL + tristate "SCD30 carbon dioxide sensor serial driver" + depends on SCD30_CORE && SERIAL_DEV_BUS + select CRC16 + help + Say Y here to build support for the Sensirion SCD30 serial interface + driver. + + To compile this driver as a module, choose M here: the module will + be called scd30_serial. + config SENSIRION_SGP30 tristate "Sensirion SGPxx gas sensors" depends on I2C diff --git a/drivers/iio/chemical/Makefile b/drivers/iio/chemical/Makefile index aba4167db745..fef63dd5bf92 100644 --- a/drivers/iio/chemical/Makefile +++ b/drivers/iio/chemical/Makefile @@ -12,6 +12,9 @@ obj-$(CONFIG_BME680_SPI) += bme680_spi.o obj-$(CONFIG_CCS811) += ccs811.o obj-$(CONFIG_IAQCORE) += ams-iaq-core.o obj-$(CONFIG_PMS7003) += pms7003.o +obj-$(CONFIG_SCD30_CORE) += scd30_core.o +obj-$(CONFIG_SCD30_I2C) += scd30_i2c.o +obj-$(CONFIG_SCD30_SERIAL) += scd30_serial.o obj-$(CONFIG_SENSIRION_SGP30) += sgp30.o obj-$(CONFIG_SPS30) += sps30.o obj-$(CONFIG_VZ89X) += vz89x.o 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 index f5a6d8ec6d4d..8b72bb012363 100644 --- a/drivers/iio/chemical/atlas-ezo-sensor.c +++ b/drivers/iio/chemical/atlas-ezo-sensor.c @@ -69,13 +69,13 @@ static int atlas_ezo_read_raw(struct iio_dev *indio_dev, { struct atlas_ezo_data *data = iio_priv(indio_dev); struct i2c_client *client = data->client; - int ret = 0; if (chan->type != IIO_CONCENTRATION) return -EINVAL; switch (mask) { case IIO_CHAN_INFO_RAW: { + int ret; long tmp; mutex_lock(&data->lock); @@ -110,7 +110,7 @@ static int atlas_ezo_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT_PLUS_MICRO; } - return ret; + return 0; } static const struct iio_info atlas_info = { @@ -152,7 +152,6 @@ static int atlas_ezo_probe(struct i2c_client *client, indio_dev->channels = chip->channels; indio_dev->num_channels = chip->num_channels; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->dev.parent = &client->dev; data = iio_priv(indio_dev); data->client = client; diff --git a/drivers/iio/chemical/atlas-sensor.c b/drivers/iio/chemical/atlas-sensor.c index 78a27e36bf32..43069636fcd5 100644 --- a/drivers/iio/chemical/atlas-sensor.c +++ b/drivers/iio/chemical/atlas-sensor.c @@ -410,10 +410,6 @@ static int atlas_buffer_postenable(struct iio_dev *indio_dev) struct atlas_data *data = iio_priv(indio_dev); int ret; - ret = iio_triggered_buffer_postenable(indio_dev); - if (ret) - return ret; - ret = pm_runtime_get_sync(&data->client->dev); if (ret < 0) { pm_runtime_put_noidle(&data->client->dev); @@ -437,7 +433,7 @@ static int atlas_buffer_predisable(struct iio_dev *indio_dev) if (ret) return ret; - return iio_triggered_buffer_predisable(indio_dev); + return 0; } static const struct iio_trigger_ops atlas_interrupt_trigger_ops = { @@ -644,7 +640,6 @@ static int atlas_probe(struct i2c_client *client, indio_dev->channels = chip->channels; indio_dev->num_channels = chip->num_channels; indio_dev->modes = INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE; - indio_dev->dev.parent = &client->dev; trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", indio_dev->name, indio_dev->id); diff --git a/drivers/iio/chemical/bme680_core.c b/drivers/iio/chemical/bme680_core.c index 13773e01699b..6ea99e4cbf92 100644 --- a/drivers/iio/chemical/bme680_core.c +++ b/drivers/iio/chemical/bme680_core.c @@ -923,7 +923,6 @@ int bme680_core_probe(struct device *dev, struct regmap *regmap, data = iio_priv(indio_dev); dev_set_drvdata(dev, indio_dev); data->regmap = regmap; - indio_dev->dev.parent = dev; indio_dev->name = name; indio_dev->channels = bme680_channels; indio_dev->num_channels = ARRAY_SIZE(bme680_channels); diff --git a/drivers/iio/chemical/ccs811.c b/drivers/iio/chemical/ccs811.c index 3ecd633f9ed3..2b007e7568b2 100644 --- a/drivers/iio/chemical/ccs811.c +++ b/drivers/iio/chemical/ccs811.c @@ -464,7 +464,6 @@ static int ccs811_probe(struct i2c_client *client, mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->name = id->name; indio_dev->info = &ccs811_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/chemical/pms7003.c b/drivers/iio/chemical/pms7003.c index 07bb90d72434..e9d4405654bc 100644 --- a/drivers/iio/chemical/pms7003.c +++ b/drivers/iio/chemical/pms7003.c @@ -280,7 +280,6 @@ static int pms7003_probe(struct serdev_device *serdev) state = iio_priv(indio_dev); serdev_device_set_drvdata(serdev, indio_dev); state->serdev = serdev; - indio_dev->dev.parent = &serdev->dev; indio_dev->info = &pms7003_info; indio_dev->name = PMS7003_DRIVER_NAME; indio_dev->channels = pms7003_channels, diff --git a/drivers/iio/chemical/scd30.h b/drivers/iio/chemical/scd30.h new file mode 100644 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 a88c1fb875a0..5a29e32c295f 100644 --- a/drivers/iio/chemical/sps30.c +++ b/drivers/iio/chemical/sps30.c @@ -487,7 +487,6 @@ static int sps30_probe(struct i2c_client *client) i2c_set_clientdata(client, indio_dev); state->client = client; state->state = RESET; - indio_dev->dev.parent = &client->dev; indio_dev->info = &sps30_info; indio_dev->name = client->name; indio_dev->channels = sps30_channels; 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..ea480c1d4349 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 @@ -281,7 +281,6 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; state->msg->outsize = sizeof(struct ec_params_motion_sense); - indio_dev->dev.parent = &pdev->dev; indio_dev->name = pdev->name; if (physical_device) { @@ -352,7 +351,7 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, } else { /* * The only way to get samples in buffer is to set a - * software tigger (systrig, hrtimer). + * software trigger (systrig, hrtimer). */ ret = devm_iio_triggered_buffer_setup( dev, indio_dev, NULL, trigger_capture, @@ -824,5 +823,26 @@ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, } EXPORT_SYMBOL_GPL(cros_ec_sensors_core_write); +static int __maybe_unused cros_ec_sensors_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct cros_ec_sensors_core_state *st = iio_priv(indio_dev); + int ret = 0; + + if (st->range_updated) { + mutex_lock(&st->cmd_lock); + st->param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; + st->param.sensor_range.data = st->curr_range; + st->param.sensor_range.roundup = 1; + ret = cros_ec_motion_send_host_cmd(st, 0); + mutex_unlock(&st->cmd_lock); + } + return ret; +} + +SIMPLE_DEV_PM_OPS(cros_ec_sensors_pm_ops, NULL, cros_ec_sensors_resume); +EXPORT_SYMBOL_GPL(cros_ec_sensors_pm_ops); + MODULE_DESCRIPTION("ChromeOS EC sensor hub core functions"); MODULE_LICENSE("GPL v2"); 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_i2c.c b/drivers/iio/common/st_sensors/st_sensors_i2c.c index b400560bac93..b9e59ad32a02 100644 --- a/drivers/iio/common/st_sensors/st_sensors_i2c.c +++ b/drivers/iio/common/st_sensors/st_sensors_i2c.c @@ -56,7 +56,6 @@ int st_sensors_i2c_configure(struct iio_dev *indio_dev, i2c_set_clientdata(client, indio_dev); - indio_dev->dev.parent = &client->dev; indio_dev->name = client->name; sdata->dev = &client->dev; diff --git a/drivers/iio/common/st_sensors/st_sensors_spi.c b/drivers/iio/common/st_sensors/st_sensors_spi.c index ee70515bb89f..48fc41dc5633 100644 --- a/drivers/iio/common/st_sensors/st_sensors_spi.c +++ b/drivers/iio/common/st_sensors/st_sensors_spi.c @@ -108,7 +108,6 @@ int st_sensors_spi_configure(struct iio_dev *indio_dev, spi_set_drvdata(spi, indio_dev); - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi->modalias; sdata->dev = &spi->dev; 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 3e0c9e84e8da..602dd2ba61b5 100644 --- a/drivers/iio/dac/ad5360.c +++ b/drivers/iio/dac/ad5360.c @@ -67,7 +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 + * @lock: lock to protect the data buffer during SPI ops * @data: spi transfer buffers */ @@ -476,7 +476,6 @@ static int ad5360_probe(struct spi_device *spi) st->chip_info = &ad5360_chip_info_tbl[type]; st->spi = spi; - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->info = &ad5360_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c index b37e5675f716..37ef653564b0 100644 --- a/drivers/iio/dac/ad5380.c +++ b/drivers/iio/dac/ad5380.c @@ -51,7 +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 + * @lock: lock to protect the data buffer during regmap ops */ struct ad5380_state { @@ -240,7 +240,7 @@ static const struct iio_info ad5380_info = { .write_raw = ad5380_write_raw, }; -static struct iio_chan_spec_ext_info ad5380_ext_info[] = { +static const struct iio_chan_spec_ext_info ad5380_ext_info[] = { { .name = "powerdown", .read = ad5380_read_dac_powerdown, @@ -386,7 +386,6 @@ static int ad5380_probe(struct device *dev, struct regmap *regmap, st->chip_info = &ad5380_chip_info_tbl[type]; st->regmap = regmap; - indio_dev->dev.parent = dev; indio_dev->name = name; indio_dev->info = &ad5380_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/ad5421.c b/drivers/iio/dac/ad5421.c index fec27764cea8..eedf661d32b2 100644 --- a/drivers/iio/dac/ad5421.c +++ b/drivers/iio/dac/ad5421.c @@ -62,7 +62,7 @@ * @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 + * @lock: lock to protect the data buffer during SPI ops */ struct ad5421_state { struct spi_device *spi; @@ -487,7 +487,6 @@ static int ad5421_probe(struct spi_device *spi) st->spi = spi; - indio_dev->dev.parent = &spi->dev; indio_dev->name = "ad5421"; indio_dev->info = &ad5421_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c index 8f8afc8999bc..935a6177569f 100644 --- a/drivers/iio/dac/ad5446.c +++ b/drivers/iio/dac/ad5446.c @@ -29,11 +29,14 @@ /** * 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 - * @lock lock to protect the data buffer during write ops + * @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 { @@ -250,8 +253,6 @@ static int ad5446_probe(struct device *dev, const char *name, st->reg = reg; st->dev = dev; - /* Establish that the iio_dev is a child of the device */ - indio_dev->dev.parent = dev; indio_dev->name = name; indio_dev->info = &ad5446_info; indio_dev->modes = INDIO_DIRECT_MODE; @@ -313,7 +314,7 @@ static int ad5660_write(struct ad5446_state *st, unsigned val) 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 @@ -535,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 d739b10e5236..f5e93c6acc9d 100644 --- a/drivers/iio/dac/ad5449.c +++ b/drivers/iio/dac/ad5449.c @@ -56,7 +56,7 @@ 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 + * @lock: lock to protect the data buffer during SPI ops */ struct ad5449 { struct spi_device *spi; @@ -297,7 +297,6 @@ static int ad5449_spi_probe(struct spi_device *spi) if (ret) return ret; - indio_dev->dev.parent = &spi->dev; indio_dev->name = id->name; indio_dev->info = &ad5449_info; indio_dev->modes = INDIO_DIRECT_MODE; 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 410e90e5f75f..cc4875660a69 100644 --- a/drivers/iio/dac/ad5592r-base.c +++ b/drivers/iio/dac/ad5592r-base.c @@ -413,7 +413,7 @@ 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; @@ -444,7 +444,7 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev, ret = IIO_VAL_INT; break; default: - ret = -EINVAL; + return -EINVAL; } unlock: @@ -484,7 +484,7 @@ static ssize_t ad5592r_show_scale_available(struct iio_dev *iio_dev, st->scale_avail[1][0], st->scale_avail[1][1]); } -static struct iio_chan_spec_ext_info ad5592r_ext_info[] = { +static const struct iio_chan_spec_ext_info ad5592r_ext_info[] = { { .name = "scale_available", .read = ad5592r_show_scale_available, @@ -508,11 +508,11 @@ static void ad5592r_setup_channel(struct iio_dev *iio_dev, chan->ext_info = ad5592r_ext_info; } -static int ad5592r_alloc_channels(struct ad5592r_state *st) +static int ad5592r_alloc_channels(struct iio_dev *iio_dev) { + struct ad5592r_state *st = iio_priv(iio_dev); unsigned i, curr_channel = 0, num_channels = st->num_channels; - struct iio_dev *iio_dev = iio_priv_to_dev(st); struct iio_chan_spec *channels; struct fwnode_handle *child; u32 reg, tmp; @@ -618,7 +618,6 @@ int ad5592r_probe(struct device *dev, const char *name, return ret; } - iio_dev->dev.parent = dev; iio_dev->name = name; iio_dev->info = &ad5592r_info; iio_dev->modes = INDIO_DIRECT_MODE; @@ -636,7 +635,7 @@ int ad5592r_probe(struct device *dev, const char *name, if (ret) goto error_disable_reg; - ret = ad5592r_alloc_channels(st); + ret = ad5592r_alloc_channels(iio_dev); if (ret) goto error_disable_reg; diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c index 2015a5df840c..2b2b8edfd258 100644 --- a/drivers/iio/dac/ad5624r_spi.c +++ b/drivers/iio/dac/ad5624r_spi.c @@ -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 8dd67da0a7da..56cf9344d187 100644 --- a/drivers/iio/dac/ad5686.c +++ b/drivers/iio/dac/ad5686.c @@ -461,7 +461,6 @@ int ad5686_probe(struct device *dev, for (i = 0; i < st->chip_info->num_channels; i++) st->pwr_down_mode |= (0x01 << (i * 2)); - indio_dev->dev.parent = dev; indio_dev->name = name; indio_dev->info = &ad5686_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c index 7723bd313fc6..0df28acf074a 100644 --- a/drivers/iio/dac/ad5755.c +++ b/drivers/iio/dac/ad5755.c @@ -82,7 +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 + * @lock: lock to protect the data buffer during SPI ops * @data: spi transfer buffers */ struct ad5755_state { @@ -744,7 +744,6 @@ static int ad5755_probe(struct spi_device *spi) st->spi = spi; st->pwr_down = 0xf; - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->info = &ad5755_info; indio_dev->modes = INDIO_DIRECT_MODE; 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 67c4fa75c6f1..e37e095e94fc 100644 --- a/drivers/iio/dac/ad5761.c +++ b/drivers/iio/dac/ad5761.c @@ -57,7 +57,7 @@ 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 + * @lock: lock to protect the data buffer during SPI ops * @data: cache aligned spi buffer */ struct ad5761_state { @@ -376,7 +376,6 @@ static int ad5761_probe(struct spi_device *spi) if (ret) goto disable_regulator_err; - iio_dev->dev.parent = &spi->dev; iio_dev->info = &ad5761_info; iio_dev->modes = INDIO_DIRECT_MODE; iio_dev->channels = &chip_info->channel; diff --git a/drivers/iio/dac/ad5764.c b/drivers/iio/dac/ad5764.c index 5b0f0fe354f6..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,7 +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 + * @lock: lock to protect the data buffer during SPI ops * @data: spi transfer buffers */ @@ -290,7 +289,6 @@ static int ad5764_probe(struct spi_device *spi) st->spi = spi; st->chip_info = &ad5764_chip_infos[type]; - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->info = &ad5764_info; indio_dev->modes = INDIO_DIRECT_MODE; 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..b3835fb6b862 100644 --- a/drivers/iio/dac/dpot-dac.c +++ b/drivers/iio/dac/dpot-dac.c @@ -177,7 +177,6 @@ static int dpot_dac_probe(struct platform_device *pdev) dac = iio_priv(indio_dev); indio_dev->name = dev_name(dev); - indio_dev->dev.parent = dev; indio_dev->info = &dpot_dac_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = &dpot_dac_iio_channel; 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 = <c1660_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 f891311f05cf..4002ed0868be 100644 --- a/drivers/iio/dac/ltc2632.c +++ b/drivers/iio/dac/ltc2632.c @@ -38,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; @@ -362,7 +362,6 @@ static int ltc2632_probe(struct spi_device *spi) } } - indio_dev->dev.parent = &spi->dev; indio_dev->name = dev_of_node(&spi->dev) ? dev_of_node(&spi->dev)->name : spi_get_device_id(spi)->name; indio_dev->info = <c2632_info; 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 de0c6573cd97..07c9f39d54f1 100644 --- a/drivers/iio/dac/ti-dac7612.c +++ b/drivers/iio/dac/ti-dac7612.c @@ -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; diff --git a/drivers/iio/dac/vf610_dac.c b/drivers/iio/dac/vf610_dac.c index 9417a4a3e22a..636b4009f763 100644 --- a/drivers/iio/dac/vf610_dac.c +++ b/drivers/iio/dac/vf610_dac.c @@ -199,8 +199,6 @@ static int vf610_dac_probe(struct platform_device *pdev) platform_set_drvdata(pdev, indio_dev); indio_dev->name = dev_name(&pdev->dev); - indio_dev->dev.parent = &pdev->dev; - indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->info = &vf610_dac_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = vf610_dac_iio_channels; 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/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 2a9ec08ec561..b9c952e65b55 100644 --- a/drivers/iio/gyro/adis16130.c +++ b/drivers/iio/gyro/adis16130.c @@ -155,7 +155,6 @@ static int adis16130_probe(struct spi_device *spi) indio_dev->name = spi->dev.driver->name; indio_dev->channels = adis16130_channels; indio_dev->num_channels = ARRAY_SIZE(adis16130_channels); - indio_dev->dev.parent = &spi->dev; indio_dev->info = &adis16130_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/gyro/adis16136.c b/drivers/iio/gyro/adis16136.c index afdc57af475d..d8a96f6bbae2 100644 --- a/drivers/iio/gyro/adis16136.c +++ b/drivers/iio/gyro/adis16136.c @@ -540,7 +540,6 @@ static int adis16136_probe(struct spi_device *spi) adis16136 = iio_priv(indio_dev); adis16136->chip_info = &adis16136_chip_info[id->driver_data]; - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->channels = adis16136_channels; indio_dev->num_channels = ARRAY_SIZE(adis16136_channels); 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/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 7f382aae1dfd..6698f5f535f6 100644 --- a/drivers/iio/gyro/hid-sensor-gyro-3d.c +++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c @@ -319,7 +319,6 @@ static int hid_gyro_3d_probe(struct platform_device *pdev) } indio_dev->num_channels = ARRAY_SIZE(gyro_3d_channels); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &gyro_3d_info; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; 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/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 9c92ff7a82be..4feb7ada7195 100644 --- a/drivers/iio/gyro/st_gyro_buffer.c +++ b/drivers/iio/gyro/st_gyro_buffer.c @@ -33,13 +33,9 @@ static int st_gyro_buffer_postenable(struct iio_dev *indio_dev) { int err; - err = iio_triggered_buffer_postenable(indio_dev); - if (err < 0) - return err; - err = st_sensors_set_axis_enable(indio_dev, indio_dev->active_scan_mask[0]); if (err < 0) - goto st_gyro_buffer_predisable; + return err; err = st_sensors_set_enable(indio_dev, true); if (err < 0) @@ -49,27 +45,18 @@ static int st_gyro_buffer_postenable(struct iio_dev *indio_dev) st_gyro_buffer_enable_all_axis: st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); -st_gyro_buffer_predisable: - iio_triggered_buffer_predisable(indio_dev); return err; } static int st_gyro_buffer_predisable(struct iio_dev *indio_dev) { - int err, err2; + int err; err = st_sensors_set_enable(indio_dev, false); if (err < 0) - goto st_gyro_buffer_predisable; - - err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); - -st_gyro_buffer_predisable: - err2 = iio_triggered_buffer_predisable(indio_dev); - if (!err) - err = err2; + return err; - return err; + return st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); } static const struct iio_buffer_setup_ops st_gyro_buffer_setup_ops = { diff --git a/drivers/iio/health/afe4403.c b/drivers/iio/health/afe4403.c index a3507624b30f..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> */ @@ -512,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 cebb1fd4d0b1..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> */ @@ -519,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 546fc37ad75d..38aa2030f3c6 100644 --- a/drivers/iio/health/max30100.c +++ b/drivers/iio/health/max30100.c @@ -439,7 +439,6 @@ static int max30100_probe(struct i2c_client *client, indio_dev->available_scan_masks = max30100_scan_masks; indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE); indio_dev->setup_ops = &max30100_buffer_setup_ops; - indio_dev->dev.parent = &client->dev; data = iio_priv(indio_dev); data->indio_dev = indio_dev; diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c index 74fc260b957e..9b47d9472a4f 100644 --- a/drivers/iio/health/max30102.c +++ b/drivers/iio/health/max30102.c @@ -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 665eb7e38293..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> @@ -283,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; } @@ -301,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; } @@ -378,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 d2318c4aab0f..52f605114ef7 100644 --- a/drivers/iio/humidity/hid-sensor-humidity.c +++ b/drivers/iio/humidity/hid-sensor-humidity.c @@ -226,7 +226,6 @@ static int hid_humidity_probe(struct platform_device *pdev) indio_dev->channels = humid_chans; indio_dev->num_channels = ARRAY_SIZE(humidity_channels); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &humidity_info; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/humidity/hts221.h b/drivers/iio/humidity/hts221.h index b2eb5abeaccd..721359e226cb 100644 --- a/drivers/iio/humidity/hts221.h +++ b/drivers/iio/humidity/hts221.h @@ -49,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 ba7d413d75ba..95e56917677f 100644 --- a/drivers/iio/humidity/hts221_buffer.c +++ b/drivers/iio/humidity/hts221_buffer.c @@ -72,10 +72,10 @@ static irqreturn_t hts221_trigger_handler_thread(int irq, void *private) return IRQ_HANDLED; } -int hts221_allocate_trigger(struct hts221_hw *hw) +int hts221_allocate_trigger(struct iio_dev *iio_dev) { + struct hts221_hw *hw = iio_priv(iio_dev); struct st_sensors_platform_data *pdata = dev_get_platdata(hw->dev); - struct iio_dev *iio_dev = iio_priv_to_dev(hw); bool irq_active_low = false, open_drain = false; unsigned long irq_type; int err; @@ -153,8 +153,6 @@ static int hts221_buffer_postdisable(struct iio_dev *iio_dev) static const struct iio_buffer_setup_ops hts221_buffer_ops = { .preenable = hts221_buffer_preenable, - .postenable = iio_triggered_buffer_postenable, - .predisable = iio_triggered_buffer_predisable, .postdisable = hts221_buffer_postdisable, }; @@ -191,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/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 fc4123d518bc..f02883b08480 100644 --- a/drivers/iio/imu/Kconfig +++ b/drivers/iio/imu/Kconfig @@ -91,6 +91,7 @@ config KMX61 To compile this driver as module, choose M here: the module will be called kmx61. +source "drivers/iio/imu/inv_icm42600/Kconfig" source "drivers/iio/imu/inv_mpu6050/Kconfig" source "drivers/iio/imu/st_lsm6dsx/Kconfig" diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile index 88b2c4555230..13e9ff442b11 100644 --- a/drivers/iio/imu/Makefile +++ b/drivers/iio/imu/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_FXOS8700) += fxos8700_core.o obj-$(CONFIG_FXOS8700_I2C) += fxos8700_i2c.o obj-$(CONFIG_FXOS8700_SPI) += fxos8700_spi.o +obj-y += inv_icm42600/ obj-y += inv_mpu6050/ obj-$(CONFIG_KMX61) += kmx61.o diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c index 229f2ff98469..1ebe3e50d3e6 100644 --- a/drivers/iio/imu/adis16400.c +++ b/drivers/iio/imu/adis16400.c @@ -1181,7 +1181,6 @@ static int adis16400_probe(struct spi_device *spi) /* setup the industrialio driver allocated elements */ st->variant = &adis16400_chips[spi_get_device_id(spi)->driver_data]; - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->channels = st->variant->channels; indio_dev->num_channels = st->variant->num_channels; diff --git a/drivers/iio/imu/adis16460.c b/drivers/iio/imu/adis16460.c index ad20c488a3ba..b26a5f1bc51a 100644 --- a/drivers/iio/imu/adis16460.c +++ b/drivers/iio/imu/adis16460.c @@ -393,7 +393,6 @@ static int adis16460_probe(struct spi_device *spi) st = iio_priv(indio_dev); st->chip_info = &adis16460_chip_info; - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->channels = st->chip_info->channels; indio_dev->num_channels = st->chip_info->num_channels; diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c index c6dac4fc67a1..35d10ccb66c2 100644 --- a/drivers/iio/imu/adis16475.c +++ b/drivers/iio/imu/adis16475.c @@ -1289,7 +1289,6 @@ static int adis16475_probe(struct spi_device *spi) if (ret) return ret; - indio_dev->dev.parent = &spi->dev; indio_dev->name = st->info->name; indio_dev->channels = st->info->channels; indio_dev->num_channels = st->info->num_channels; diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c index 6a471eee110e..1eb4f98076f1 100644 --- a/drivers/iio/imu/adis16480.c +++ b/drivers/iio/imu/adis16480.c @@ -1102,12 +1102,12 @@ static int adis16480_config_irq_pin(struct device_node *of_node, /* * Get the interrupt line behaviour. The data ready polarity can be * configured as positive or negative, corresponding to - * IRQF_TRIGGER_RISING or IRQF_TRIGGER_FALLING respectively. + * IRQ_TYPE_EDGE_RISING or IRQ_TYPE_EDGE_FALLING respectively. */ irq_type = irqd_get_trigger_type(desc); - if (irq_type == IRQF_TRIGGER_RISING) { /* Default */ + if (irq_type == IRQ_TYPE_EDGE_RISING) { /* Default */ val |= ADIS16480_DRDY_POL(1); - } else if (irq_type == IRQF_TRIGGER_FALLING) { + } else if (irq_type == IRQ_TYPE_EDGE_FALLING) { val |= ADIS16480_DRDY_POL(0); } else { dev_err(&st->adis.spi->dev, @@ -1229,7 +1229,6 @@ static int adis16480_probe(struct spi_device *spi) st = iio_priv(indio_dev); st->chip_info = &adis16480_chip_info[id->driver_data]; - indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->channels = st->chip_info->channels; indio_dev->num_channels = st->chip_info->num_channels; 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/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, + ®val); + 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, + ®val); + 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, + ®val); + 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, ×tamp, &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, ×tamp, &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, + ®val); + 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, + ®val); + 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, + ®val); + 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, ×tamp, &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 c27d06035c8b..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) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 4d604fe842e5..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: @@ -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. * @@ -1275,7 +1275,7 @@ static const struct iio_info mpu_info = { .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) @@ -1530,7 +1530,6 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, } dev_set_drvdata(dev, indio_dev); - indio_dev->dev.parent = dev; /* name will be NULL when enumerated via ACPI */ if (name) indio_dev->name = name; 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/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 b56df409ed0f..d80ba2e688ed 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -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 0b776cb91928..346c24281d26 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -2152,7 +2152,6 @@ static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw, return NULL; iio_dev->modes = INDIO_DIRECT_MODE; - iio_dev->dev.parent = hw->dev; iio_dev->available_scan_masks = st_lsm6dsx_available_scan_masks; iio_dev->channels = hw->settings->channels[id].chan; iio_dev->num_channels = hw->settings->channels[id].len; @@ -2458,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 c1f83fe0d8da..ed83471dc7dd 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c @@ -163,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 @@ -195,7 +195,7 @@ out: return err; } -/** +/* * st_lsm6dsx_shub_write_reg - write i2c controller register * * Write st_lsm6dsx i2c controller register @@ -273,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 @@ -323,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 @@ -735,7 +735,6 @@ st_lsm6dsx_shub_alloc_iiodev(struct st_lsm6dsx_hw *hw, return NULL; iio_dev->modes = INDIO_DIRECT_MODE; - iio_dev->dev.parent = hw->dev; iio_dev->info = &st_lsm6dsx_ext_info; sensor = iio_priv(iio_dev); diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 9fa238c0a7d4..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> @@ -598,8 +600,10 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev, static void iio_buffer_activate(struct iio_dev *indio_dev, struct iio_buffer *buffer) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); + iio_buffer_get(buffer); - list_add(&buffer->buffer_list, &indio_dev->buffer_list); + list_add(&buffer->buffer_list, &iio_dev_opaque->buffer_list); } static void iio_buffer_deactivate(struct iio_buffer *buffer) @@ -611,10 +615,11 @@ static void iio_buffer_deactivate(struct iio_buffer *buffer) static void iio_buffer_deactivate_all(struct iio_dev *indio_dev) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); struct iio_buffer *buffer, *_buffer; list_for_each_entry_safe(buffer, _buffer, - &indio_dev->buffer_list, buffer_list) + &iio_dev_opaque->buffer_list, buffer_list) iio_buffer_deactivate(buffer); } @@ -687,6 +692,7 @@ static int iio_verify_update(struct iio_dev *indio_dev, struct iio_buffer *insert_buffer, struct iio_buffer *remove_buffer, struct iio_device_config *config) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); unsigned long *compound_mask; const unsigned long *scan_mask; bool strict_scanmask = false; @@ -709,12 +715,12 @@ static int iio_verify_update(struct iio_dev *indio_dev, * to verify. */ if (remove_buffer && !insert_buffer && - list_is_singular(&indio_dev->buffer_list)) + list_is_singular(&iio_dev_opaque->buffer_list)) return 0; modes = indio_dev->modes; - list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) { + list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) { if (buffer == remove_buffer) continue; modes &= buffer->access->modes; @@ -735,7 +741,7 @@ static int iio_verify_update(struct iio_dev *indio_dev, * Keep things simple for now and only allow a single buffer to * be connected in hardware mode. */ - if (insert_buffer && !list_empty(&indio_dev->buffer_list)) + if (insert_buffer && !list_empty(&iio_dev_opaque->buffer_list)) return -EINVAL; config->mode = INDIO_BUFFER_HARDWARE; strict_scanmask = true; @@ -755,7 +761,7 @@ static int iio_verify_update(struct iio_dev *indio_dev, scan_timestamp = false; - list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) { + list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) { if (buffer == remove_buffer) continue; bitmap_or(compound_mask, compound_mask, buffer->scan_mask, @@ -901,10 +907,11 @@ error_clear_mux_table: static int iio_update_demux(struct iio_dev *indio_dev) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); struct iio_buffer *buffer; int ret; - list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) { + list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) { ret = iio_buffer_update_demux(indio_dev, buffer); if (ret < 0) goto error_clear_mux_table; @@ -912,7 +919,7 @@ static int iio_update_demux(struct iio_dev *indio_dev) return 0; error_clear_mux_table: - list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) + list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) iio_buffer_demux_free(buffer); return ret; @@ -921,6 +928,7 @@ error_clear_mux_table: static int iio_enable_buffers(struct iio_dev *indio_dev, struct iio_device_config *config) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); struct iio_buffer *buffer; int ret; @@ -957,25 +965,37 @@ static int iio_enable_buffers(struct iio_dev *indio_dev, indio_dev->info->hwfifo_set_watermark(indio_dev, config->watermark); - list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) { + list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) { ret = iio_buffer_enable(buffer, indio_dev); if (ret) goto err_disable_buffers; } + if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { + ret = iio_trigger_attach_poll_func(indio_dev->trig, + indio_dev->pollfunc); + if (ret) + goto err_disable_buffers; + } + if (indio_dev->setup_ops->postenable) { ret = indio_dev->setup_ops->postenable(indio_dev); if (ret) { dev_dbg(&indio_dev->dev, "Buffer not started: postenable failed (%d)\n", ret); - goto err_disable_buffers; + goto err_detach_pollfunc; } } return 0; +err_detach_pollfunc: + if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { + iio_trigger_detach_poll_func(indio_dev->trig, + indio_dev->pollfunc); + } err_disable_buffers: - list_for_each_entry_continue_reverse(buffer, &indio_dev->buffer_list, + list_for_each_entry_continue_reverse(buffer, &iio_dev_opaque->buffer_list, buffer_list) iio_buffer_disable(buffer, indio_dev); err_run_postdisable: @@ -990,12 +1010,13 @@ err_undo_config: static int iio_disable_buffers(struct iio_dev *indio_dev) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); struct iio_buffer *buffer; int ret = 0; int ret2; /* Wind down existing buffers - iff there are any */ - if (list_empty(&indio_dev->buffer_list)) + if (list_empty(&iio_dev_opaque->buffer_list)) return 0; /* @@ -1011,7 +1032,12 @@ static int iio_disable_buffers(struct iio_dev *indio_dev) ret = ret2; } - list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) { + if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) { + iio_trigger_detach_poll_func(indio_dev->trig, + indio_dev->pollfunc); + } + + list_for_each_entry(buffer, &iio_dev_opaque->buffer_list, buffer_list) { ret2 = iio_buffer_disable(buffer, indio_dev); if (ret2 && !ret) ret = ret2; @@ -1034,6 +1060,7 @@ static int __iio_update_buffers(struct iio_dev *indio_dev, struct iio_buffer *insert_buffer, struct iio_buffer *remove_buffer) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); struct iio_device_config new_config; int ret; @@ -1058,7 +1085,7 @@ static int __iio_update_buffers(struct iio_dev *indio_dev, iio_buffer_activate(indio_dev, insert_buffer); /* If no buffers in list, we are done */ - if (list_empty(&indio_dev->buffer_list)) + if (list_empty(&iio_dev_opaque->buffer_list)) return 0; ret = iio_enable_buffers(indio_dev, &new_config); @@ -1407,10 +1434,11 @@ static int iio_push_to_buffer(struct iio_buffer *buffer, const void *data) */ int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data) { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); int ret; struct iio_buffer *buf; - list_for_each_entry(buf, &indio_dev->buffer_list, buffer_list) { + list_for_each_entry(buf, &iio_dev_opaque->buffer_list, buffer_list) { ret = iio_push_to_buffer(buf, data); if (ret < 0) return ret; diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 352533342702..606d5e61c575 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> @@ -166,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 @@ -199,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) @@ -309,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; @@ -352,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) { @@ -379,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 @@ -1118,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) { @@ -1130,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) @@ -1146,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; @@ -1165,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; @@ -1180,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; @@ -1255,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; @@ -1390,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; @@ -1419,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) @@ -1429,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); @@ -1483,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 = { @@ -1495,23 +1525,27 @@ struct device_type iio_device_type = { * iio_device_alloc() - allocate an iio_dev from a driver * @sizeof_priv: Space to allocate for private structure. **/ -struct iio_dev *iio_device_alloc(int sizeof_priv) +struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv) { + struct iio_dev_opaque *iio_dev_opaque; struct iio_dev *dev; size_t alloc_size; - alloc_size = sizeof(struct iio_dev); + alloc_size = sizeof(struct iio_dev_opaque); if (sizeof_priv) { alloc_size = ALIGN(alloc_size, IIO_ALIGN); alloc_size += sizeof_priv; } - /* ensure 32-byte alignment of whole construct ? */ - alloc_size += IIO_ALIGN - 1; - dev = kzalloc(alloc_size, GFP_KERNEL); - if (!dev) + iio_dev_opaque = kzalloc(alloc_size, GFP_KERNEL); + if (!iio_dev_opaque) return NULL; + dev = &iio_dev_opaque->indio_dev; + dev->priv = (char *)iio_dev_opaque + + ALIGN(sizeof(struct iio_dev_opaque), IIO_ALIGN); + + dev->dev.parent = parent; dev->dev.groups = dev->groups; dev->dev.type = &iio_device_type; dev->dev.bus = &iio_bus_type; @@ -1519,17 +1553,17 @@ struct iio_dev *iio_device_alloc(int sizeof_priv) dev_set_drvdata(&dev->dev, (void *)dev); mutex_init(&dev->mlock); mutex_init(&dev->info_exist_lock); - INIT_LIST_HEAD(&dev->channel_attr_list); + INIT_LIST_HEAD(&iio_dev_opaque->channel_attr_list); dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); if (dev->id < 0) { /* cannot use a dev_err as the name isn't available */ pr_err("failed to get device id\n"); - kfree(dev); + kfree(iio_dev_opaque); return NULL; } dev_set_name(&dev->dev, "iio:device%d", dev->id); - INIT_LIST_HEAD(&dev->buffer_list); + INIT_LIST_HEAD(&iio_dev_opaque->buffer_list); return dev; } @@ -1553,7 +1587,7 @@ static void devm_iio_device_release(struct device *dev, void *res) /** * devm_iio_device_alloc - Resource-managed iio_device_alloc() - * @dev: Device to allocate iio_dev for + * @parent: Device to allocate iio_dev for, and parent for this IIO device * @sizeof_priv: Space to allocate for private structure. * * Managed iio_device_alloc. iio_dev allocated with this function is @@ -1562,7 +1596,7 @@ static void devm_iio_device_release(struct device *dev, void *res) * RETURNS: * Pointer to allocated iio_dev on success, NULL on failure. */ -struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv) +struct iio_dev *devm_iio_device_alloc(struct device *parent, int sizeof_priv) { struct iio_dev **ptr, *iio_dev; @@ -1571,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); } 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 53d1931f6be8..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 @@ -705,17 +705,3 @@ void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev) if (indio_dev->trig) iio_trigger_put(indio_dev->trig); } - -int iio_triggered_buffer_postenable(struct iio_dev *indio_dev) -{ - return iio_trigger_attach_poll_func(indio_dev->trig, - indio_dev->pollfunc); -} -EXPORT_SYMBOL(iio_triggered_buffer_postenable); - -int iio_triggered_buffer_predisable(struct iio_dev *indio_dev) -{ - return iio_trigger_detach_poll_func(indio_dev->trig, - indio_dev->pollfunc); -} -EXPORT_SYMBOL(iio_triggered_buffer_predisable); 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 03f2d8d123c4..abbf2e662e7d 100644 --- a/drivers/iio/light/bh1780.c +++ b/drivers/iio/light/bh1780.c @@ -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; diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c index 160eb3f99795..97649944f1df 100644 --- a/drivers/iio/light/cm32181.c +++ b/drivers/iio/light/cm32181.c @@ -93,10 +93,10 @@ static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val2); #ifdef CONFIG_ACPI /** * cm32181_acpi_get_cpm() - Get CPM object from ACPI - * @client pointer of struct i2c_client. - * @obj_name pointer of ACPI object name. - * @count maximum size of return array. - * @vals pointer of array for return elements. + * @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. * @@ -465,7 +465,6 @@ static int cm32181_probe(struct i2c_client *client) cm32181->dev = dev; mutex_init(&cm32181->lock); - indio_dev->dev.parent = dev; indio_dev->channels = cm32181_channels; indio_dev->num_channels = ARRAY_SIZE(cm32181_channels); indio_dev->info = &cm32181_info; diff --git a/drivers/iio/light/cm3232.c b/drivers/iio/light/cm3232.c index 867200825686..18a410340dc5 100644 --- a/drivers/iio/light/cm3232.c +++ b/drivers/iio/light/cm3232.c @@ -340,7 +340,6 @@ static int cm3232_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); chip->client = client; - indio_dev->dev.parent = &client->dev; indio_dev->channels = cm3232_channels; indio_dev->num_channels = ARRAY_SIZE(cm3232_channels); indio_dev->info = &cm3232_info; 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 7a2679bdc987..d5e1cd27eb46 100644 --- a/drivers/iio/light/gp2ap002.c +++ b/drivers/iio/light/gp2ap002.c @@ -596,7 +596,6 @@ static int gp2ap002_probe(struct i2c_client *client, pm_runtime_use_autosuspend(dev); pm_runtime_put(dev); - indio_dev->dev.parent = dev; indio_dev->info = &gp2ap002_info; indio_dev->name = "gp2ap002"; indio_dev->channels = gp2ap002_channels; diff --git a/drivers/iio/light/gp2ap020a00f.c b/drivers/iio/light/gp2ap020a00f.c index 070d4cd0cf54..e2850c1a7353 100644 --- a/drivers/iio/light/gp2ap020a00f.c +++ b/drivers/iio/light/gp2ap020a00f.c @@ -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; diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c index 81fa2a422797..a21c827e4953 100644 --- a/drivers/iio/light/hid-sensor-als.c +++ b/drivers/iio/light/hid-sensor-als.c @@ -301,7 +301,6 @@ static int hid_als_probe(struct platform_device *pdev) indio_dev->num_channels = ARRAY_SIZE(als_channels); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &als_info; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c index e9c04df07344..330cf359e0b8 100644 --- a/drivers/iio/light/hid-sensor-prox.c +++ b/drivers/iio/light/hid-sensor-prox.c @@ -279,7 +279,6 @@ static int hid_prox_probe(struct platform_device *pdev) } indio_dev->num_channels = ARRAY_SIZE(prox_channels); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &prox_info; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; 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 95611f5eff01..b93b85dbc3a6 100644 --- a/drivers/iio/light/isl29125.c +++ b/drivers/iio/light/isl29125.c @@ -216,36 +216,20 @@ static const struct iio_info isl29125_info = { static int isl29125_buffer_postenable(struct iio_dev *indio_dev) { struct isl29125_data *data = iio_priv(indio_dev); - int err; - - err = iio_triggered_buffer_postenable(indio_dev); - if (err) - return err; data->conf1 |= ISL29125_MODE_RGB; - err = i2c_smbus_write_byte_data(data->client, ISL29125_CONF1, + return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1, data->conf1); - if (err) { - iio_triggered_buffer_predisable(indio_dev); - return err; - } - - return 0; } static int isl29125_buffer_predisable(struct iio_dev *indio_dev) { struct isl29125_data *data = iio_priv(indio_dev); - int ret; data->conf1 &= ~ISL29125_MODE_MASK; data->conf1 |= ISL29125_MODE_PD; - ret = i2c_smbus_write_byte_data(data->client, ISL29125_CONF1, + return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1, data->conf1); - - iio_triggered_buffer_predisable(indio_dev); - - return ret; } static const struct iio_buffer_setup_ops isl29125_buffer_setup_ops = { @@ -268,7 +252,6 @@ static int isl29125_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); data->client = client; - indio_dev->dev.parent = &client->dev; indio_dev->info = &isl29125_info; indio_dev->name = ISL29125_DRV_NAME; indio_dev->channels = isl29125_channels; 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 5a3fcb127cd2..4bac0646398d 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -1480,7 +1480,6 @@ static int ltr501_probe(struct i2c_client *client, if ((partid >> 4) != data->chip_info->partid) return -ENODEV; - indio_dev->dev.parent = &client->dev; indio_dev->info = data->chip_info->info; indio_dev->channels = data->chip_info->channels; indio_dev->num_channels = data->chip_info->no_channels; 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..aa8ed1e3e89a 100644 --- a/drivers/iio/light/max44000.c +++ b/drivers/iio/light/max44000.c @@ -538,7 +538,6 @@ static int max44000_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->info = &max44000_info; indio_dev->name = MAX44000_DRV_NAME; indio_dev->channels = max44000_channels; 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 82abfa57b59c..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> @@ -768,7 +768,6 @@ static int opt3001_probe(struct i2c_client *client, iio->name = client->name; iio->channels = opt3001_channels; iio->num_channels = ARRAY_SIZE(opt3001_channels); - iio->dev.parent = dev; iio->modes = INDIO_DIRECT_MODE; iio->info = &opt3001_info; 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 c1adab2a50fd..c280b4195003 100644 --- a/drivers/iio/light/si1133.c +++ b/drivers/iio/light/si1133.c @@ -1015,7 +1015,6 @@ static int si1133_probe(struct i2c_client *client, i2c_set_clientdata(client, iio_dev); data->client = client; - iio_dev->dev.parent = &client->dev; iio_dev->name = id->name; iio_dev->channels = si1133_channels; iio_dev->num_channels = ARRAY_SIZE(si1133_channels); diff --git a/drivers/iio/light/si1145.c b/drivers/iio/light/si1145.c index 0476c2bc8138..155faaea8c72 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 @@ -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/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 27a5c28aac7f..abc8d7db8dc1 100644 --- a/drivers/iio/light/tsl2563.c +++ b/drivers/iio/light/tsl2563.c @@ -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 9fbde9b71b63..735399405417 100644 --- a/drivers/iio/light/tsl2772.c +++ b/drivers/iio/light/tsl2772.c @@ -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 2a4b3d331055..fff4b36b8b58 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -957,50 +957,29 @@ static int vcnl4010_buffer_postenable(struct iio_dev *indio_dev) int ret; int cmd; - ret = iio_triggered_buffer_postenable(indio_dev); - if (ret) - return ret; - /* Do not enable the buffer if we are already capturing events. */ - if (vcnl4010_is_in_periodic_mode(data)) { - ret = -EBUSY; - goto end; - } + if (vcnl4010_is_in_periodic_mode(data)) + return -EBUSY; ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, VCNL4010_INT_PROX_EN); if (ret < 0) - goto end; + return ret; cmd = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN; - ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, cmd); - if (ret < 0) - goto end; - - return 0; -end: - iio_triggered_buffer_predisable(indio_dev); - - return ret; + return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, cmd); } static int vcnl4010_buffer_predisable(struct iio_dev *indio_dev) { struct vcnl4000_data *data = iio_priv(indio_dev); - int ret, ret_disable; + int ret; ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, 0); if (ret < 0) - goto end; - - ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 0); - -end: - ret_disable = iio_triggered_buffer_predisable(indio_dev); - if (ret == 0) - ret = ret_disable; + return ret; - return ret; + return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 0); } static const struct iio_buffer_setup_ops vcnl4010_buffer_ops = { @@ -1058,7 +1037,6 @@ static int vcnl4000_probe(struct i2c_client *client, &data->near_level)) data->near_level = 0; - indio_dev->dev.parent = &client->dev; indio_dev->info = data->chip_spec->info; indio_dev->channels = data->chip_spec->channels; indio_dev->num_channels = data->chip_spec->num_channels; 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 ed7b02765b97..4775bd785e50 100644 --- a/drivers/iio/light/vl6180.c +++ b/drivers/iio/light/vl6180.c @@ -509,7 +509,6 @@ static int vl6180_probe(struct i2c_client *client, data->client = client; mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->info = &vl6180_info; indio_dev->channels = vl6180_channels; indio_dev->num_channels = ARRAY_SIZE(vl6180_channels); diff --git a/drivers/iio/light/zopt2201.c b/drivers/iio/light/zopt2201.c index 80ae530720cd..e0bc9df9c88b 100644 --- a/drivers/iio/light/zopt2201.c +++ b/drivers/iio/light/zopt2201.c @@ -527,7 +527,6 @@ static int zopt2201_probe(struct i2c_client *client, data->client = client; mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->info = &zopt2201_info; indio_dev->channels = zopt2201_channels; indio_dev->num_channels = ARRAY_SIZE(zopt2201_channels); diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c index 91c39352fba2..6a8ae145f0c0 100644 --- a/drivers/iio/magnetometer/ak8974.c +++ b/drivers/iio/magnetometer/ak8974.c @@ -180,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; @@ -893,7 +894,6 @@ static int ak8974_probe(struct i2c_client *i2c, goto disable_pm; } - indio_dev->dev.parent = &i2c->dev; switch (ak8974->variant) { case AK8974_WHOAMI_VALUE_AMI306: case AK8974_WHOAMI_VALUE_AMI305: diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 3c881541ae72..03d71f796177 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; @@ -384,10 +385,13 @@ static int ak8975_power_on(const struct ak8975_data *data) "Failed to enable specified Vid supply\n"); return ret; } + + gpiod_set_value_cansleep(data->reset_gpiod, 0); + /* - * According to the datasheet the power supply rise time i 200us + * According to the datasheet the power supply rise time is 200us * and the minimum wait time before mode setting is 100us, in - * total 300 us. Add some margin and say minimum 500us here. + * total 300us. Add some margin and say minimum 500us here. */ usleep_range(500, 1000); return 0; @@ -396,6 +400,8 @@ static int ak8975_power_on(const struct ak8975_data *data) /* Disable attached power regulator if any. */ static void ak8975_power_off(const struct ak8975_data *data) { + gpiod_set_value_cansleep(data->reset_gpiod, 1); + regulator_disable(data->vid); regulator_disable(data->vdd); } @@ -839,6 +845,7 @@ static int ak8975_probe(struct i2c_client *client, struct ak8975_data *data; struct iio_dev *indio_dev; struct gpio_desc *eoc_gpiod; + struct gpio_desc *reset_gpiod; const void *match; unsigned int i; int err; @@ -856,6 +863,16 @@ static int ak8975_probe(struct i2c_client *client, if (eoc_gpiod) gpiod_set_consumer_name(eoc_gpiod, "ak_8975"); + /* + * According to AK09911 datasheet, if reset GPIO is provided then + * deassert reset on ak8975_power_on() and assert reset on + * ak8975_power_off(). + */ + reset_gpiod = devm_gpiod_get_optional(&client->dev, + "reset", GPIOD_OUT_HIGH); + if (IS_ERR(reset_gpiod)) + return PTR_ERR(reset_gpiod); + /* Register with IIO */ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); if (indio_dev == NULL) @@ -866,6 +883,7 @@ static int ak8975_probe(struct i2c_client *client, data->client = client; data->eoc_gpiod = eoc_gpiod; + data->reset_gpiod = reset_gpiod; data->eoc_irq = 0; err = iio_read_mount_matrix(&client->dev, "mount-matrix", &data->orientation); @@ -922,7 +940,6 @@ static int ak8975_probe(struct i2c_client *client, } mutex_init(&data->lock); - indio_dev->dev.parent = &client->dev; indio_dev->channels = ak8975_channels; indio_dev->num_channels = ARRAY_SIZE(ak8975_channels); indio_dev->info = &ak8975_info; 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/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c index 0c09daf87794..97642ebd9168 100644 --- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c +++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c @@ -512,7 +512,6 @@ static int hid_magn_3d_probe(struct platform_device *pdev) indio_dev->channels = channels; indio_dev->num_channels = chan_count; - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &magn_3d_info; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; 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 1787d656d009..65f3d1ed0d59 100644 --- a/drivers/iio/magnetometer/mmc35240.c +++ b/drivers/iio/magnetometer/mmc35240.c @@ -301,7 +301,7 @@ static int mmc35240_read_measurement(struct mmc35240_data *data, __le16 buf[3]) /** * 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 43a2e420c9c4..7242897a05e9 100644 --- a/drivers/iio/magnetometer/rm3100-core.c +++ b/drivers/iio/magnetometer/rm3100-core.c @@ -463,8 +463,6 @@ static int rm3100_buffer_postdisable(struct iio_dev *indio_dev) static const struct iio_buffer_setup_ops rm3100_buffer_ops = { .preenable = rm3100_buffer_preenable, - .postenable = iio_triggered_buffer_postenable, - .predisable = iio_triggered_buffer_predisable, .postdisable = rm3100_buffer_postdisable, }; @@ -549,7 +547,6 @@ int rm3100_common_probe(struct device *dev, struct regmap *regmap, int irq) mutex_init(&data->lock); - indio_dev->dev.parent = dev; indio_dev->name = "rm3100"; indio_dev->info = &rm3100_info; indio_dev->channels = rm3100_channels; 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/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 6aac8bea233a..ae132a93bcae 100644 --- a/drivers/iio/orientation/hid-sensor-incl-3d.c +++ b/drivers/iio/orientation/hid-sensor-incl-3d.c @@ -339,7 +339,6 @@ static int hid_incl_3d_probe(struct platform_device *pdev) } indio_dev->num_channels = ARRAY_SIZE(incl_3d_channels); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &incl_3d_info; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c index b99f41240e3e..23bc61a7f018 100644 --- a/drivers/iio/orientation/hid-sensor-rotation.c +++ b/drivers/iio/orientation/hid-sensor-rotation.c @@ -281,7 +281,6 @@ static int hid_dev_rot_probe(struct platform_device *pdev) } indio_dev->num_channels = ARRAY_SIZE(dev_rot_channels); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &dev_rot_info; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; 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 126a56d31b6e..6b7da40f99c8 100644 --- a/drivers/iio/pressure/bmp280-core.c +++ b/drivers/iio/pressure/bmp280-core.c @@ -1004,7 +1004,6 @@ int bmp280_common_probe(struct device *dev, mutex_init(&data->lock); data->dev = dev; - indio_dev->dev.parent = dev; indio_dev->name = name; indio_dev->channels = bmp280_channels; indio_dev->info = &bmp280_info; 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 5e6663f757ae..5c458788f346 100644 --- a/drivers/iio/pressure/hid-sensor-press.c +++ b/drivers/iio/pressure/hid-sensor-press.c @@ -283,7 +283,6 @@ static int hid_press_probe(struct platform_device *pdev) indio_dev->num_channels = ARRAY_SIZE(press_channels); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &press_info; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; 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 1f931f5b7a65..986b7a59712e 100644 --- a/drivers/iio/pressure/hp206c.c +++ b/drivers/iio/pressure/hp206c.c @@ -378,7 +378,6 @@ static int hp206c_probe(struct i2c_client *client, indio_dev->info = &hp206c_info; indio_dev->name = id->name; - indio_dev->dev.parent = &client->dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = hp206c_channels; indio_dev->num_channels = ARRAY_SIZE(hp206c_channels); 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 f5db9fa086f3..214b0d25f598 100644 --- a/drivers/iio/pressure/ms5611_core.c +++ b/drivers/iio/pressure/ms5611_core.c @@ -440,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/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/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 799a8dc3e248..2cecbe0adb3f 100644 --- a/drivers/iio/pressure/zpa2326.c +++ b/drivers/iio/pressure/zpa2326.c @@ -1244,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) { @@ -1265,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) @@ -1289,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 }; @@ -1603,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/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..654564c45248 100644 --- a/drivers/iio/proximity/mb1232.c +++ b/drivers/iio/proximity/mb1232.c @@ -200,7 +200,6 @@ static int mb1232_probe(struct i2c_client *client, indio_dev->info = &mb1232_info; indio_dev->name = id->name; - indio_dev->dev.parent = dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = mb1232_channels; indio_dev->num_channels = ARRAY_SIZE(mb1232_channels); diff --git a/drivers/iio/proximity/ping.c b/drivers/iio/proximity/ping.c index 2e99eeb27f2e..1283ac1c2e03 100644 --- a/drivers/iio/proximity/ping.c +++ b/drivers/iio/proximity/ping.c @@ -309,7 +309,6 @@ static int ping_probe(struct platform_device *pdev) platform_set_drvdata(pdev, indio_dev); indio_dev->name = "ping"; - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &ping_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = ping_chan_spec; 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 index d161f3061e35..dc2e11b43431 100644 --- a/drivers/iio/proximity/sx9310.c +++ b/drivers/iio/proximity/sx9310.c @@ -736,8 +736,6 @@ static int sx9310_buffer_postdisable(struct iio_dev *indio_dev) static const struct iio_buffer_setup_ops sx9310_buffer_setup_ops = { .preenable = sx9310_buffer_preenable, - .postenable = iio_triggered_buffer_postenable, - .predisable = iio_triggered_buffer_predisable, .postdisable = sx9310_buffer_postdisable, }; @@ -931,7 +929,6 @@ static int sx9310_probe(struct i2c_client *client, return ret; ACPI_COMPANION_SET(&indio_dev->dev, ACPI_COMPANION(&client->dev)); - indio_dev->dev.parent = &client->dev; indio_dev->channels = sx9310_channels; indio_dev->num_channels = ARRAY_SIZE(sx9310_channels); indio_dev->info = &sx9310_info; 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 index 9ff1a164c2e6..37264f801ad0 100644 --- a/drivers/iio/proximity/vcnl3020.c +++ b/drivers/iio/proximity/vcnl3020.c @@ -226,7 +226,6 @@ static int vcnl3020_probe(struct i2c_client *client) if (rc) return rc; - indio_dev->dev.parent = &client->dev; indio_dev->info = &vcnl3020_info; indio_dev->channels = vcnl3020_channels; indio_dev->num_channels = ARRAY_SIZE(vcnl3020_channels); 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 8d1f434f109d..81688f1b932f 100644 --- a/drivers/iio/temperature/hid-sensor-temperature.c +++ b/drivers/iio/temperature/hid-sensor-temperature.c @@ -223,7 +223,6 @@ static int hid_temperature_probe(struct platform_device *pdev) indio_dev->channels = temp_chans; indio_dev->num_channels = ARRAY_SIZE(temperature_channels); - indio_dev->dev.parent = &pdev->dev; indio_dev->info = &temperature_info; indio_dev->name = name; indio_dev->modes = INDIO_DIRECT_MODE; 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 8976e8d59826..55ff28a0f1c7 100644 --- a/drivers/iio/temperature/ltc2983.c +++ b/drivers/iio/temperature/ltc2983.c @@ -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 b4c49a5d3685..1954322e43be 100644 --- a/drivers/iio/temperature/max31856.c +++ b/drivers/iio/temperature/max31856.c @@ -417,8 +417,6 @@ static int max31856_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); indio_dev->info = &max31856_info; - indio_dev->dev.parent = &spi->dev; - indio_dev->dev.of_node = spi->dev.of_node; indio_dev->name = id->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = max31856_channels; 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/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) |