diff options
Diffstat (limited to 'drivers/iio')
32 files changed, 1983 insertions, 226 deletions
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 4a1f133538ba..62a970a20219 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -223,7 +223,7 @@ config IIO_ST_ACCEL_3AXIS Say yes here to build support for STMicroelectronics accelerometers: LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC, LIS331DLH, LSM303DL, LSM303DLM, LSM330, LIS2DH12, H3LIS331DL, - LNG2DM, LIS3DE + LNG2DM, LIS3DE, LIS2DE12 This driver can also be built as a module. If so, these modules will be created: diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c index b4e2d9b04e1d..44d7c49fe2a1 100644 --- a/drivers/iio/accel/bmc150-accel-core.c +++ b/drivers/iio/accel/bmc150-accel-core.c @@ -394,7 +394,7 @@ static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on) if (ret < 0) { dev_err(dev, - "Failed: bmc150_accel_set_power_state for %d\n", on); + "Failed: %s for %d\n", __func__, on); if (on) pm_runtime_put_noidle(dev); diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index a5c9d3d8613f..2922a2e88a1b 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -451,7 +451,7 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on) } if (ret < 0) { dev_err(&data->client->dev, - "Failed: kxcjk1013_set_power_state for %d\n", on); + "Failed: %s for %d\n", __func__, on); if (on) pm_runtime_put_noidle(&data->client->dev); return ret; @@ -1491,6 +1491,7 @@ static const struct acpi_device_id kx_acpi_match[] = { {"KXCJ1013", KXCJK1013}, {"KXCJ1008", KXCJ91008}, {"KXCJ9000", KXCJ91008}, + {"KIOX0008", KXCJ91008}, {"KIOX0009", KXTJ21009}, {"KIOX000A", KXCJ91008}, {"KIOX010A", KXCJ91008}, /* KXCJ91008 inside the display of a 2-in-1 */ diff --git a/drivers/iio/accel/st_accel.h b/drivers/iio/accel/st_accel.h index fd53258656ca..9d25955af58e 100644 --- a/drivers/iio/accel/st_accel.h +++ b/drivers/iio/accel/st_accel.h @@ -34,6 +34,7 @@ enum st_accel_type { LIS3LV02DL, LIS2DW12, LIS3DHH, + LIS2DE12, ST_ACCEL_MAX, }; @@ -57,6 +58,7 @@ enum st_accel_type { #define LIS2DW12_ACCEL_DEV_NAME "lis2dw12" #define LIS3DHH_ACCEL_DEV_NAME "lis3dhh" #define LIS3DE_ACCEL_DEV_NAME "lis3de" +#define LIS2DE12_ACCEL_DEV_NAME "lis2de12" /** * struct st_sensors_platform_data - default accel platform data diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index 9930edf423bf..5ff04d9755d5 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -831,6 +831,82 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .multi_read_bit = false, .bootime = 2, }, + { + .wai = 0x33, + .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, + .sensors_supported = { + [0] = LIS2DE12_ACCEL_DEV_NAME, + }, + .ch = (struct iio_chan_spec *)st_accel_8bit_channels, + .odr = { + .addr = 0x20, + .mask = 0xf0, + .odr_avl = { + { .hz = 1, .value = 0x01, }, + { .hz = 10, .value = 0x02, }, + { .hz = 25, .value = 0x03, }, + { .hz = 50, .value = 0x04, }, + { .hz = 100, .value = 0x05, }, + { .hz = 200, .value = 0x06, }, + { .hz = 400, .value = 0x07, }, + { .hz = 1620, .value = 0x08, }, + { .hz = 5376, .value = 0x09, }, + }, + }, + .pw = { + .addr = 0x20, + .mask = 0xf0, + .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, + }, + .enable_axis = { + .addr = ST_SENSORS_DEFAULT_AXIS_ADDR, + .mask = ST_SENSORS_DEFAULT_AXIS_MASK, + }, + .fs = { + .addr = 0x23, + .mask = 0x30, + .fs_avl = { + [0] = { + .num = ST_ACCEL_FS_AVL_2G, + .value = 0x00, + .gain = IIO_G_TO_M_S_2(15600), + }, + [1] = { + .num = ST_ACCEL_FS_AVL_4G, + .value = 0x01, + .gain = IIO_G_TO_M_S_2(31200), + }, + [2] = { + .num = ST_ACCEL_FS_AVL_8G, + .value = 0x02, + .gain = IIO_G_TO_M_S_2(62500), + }, + [3] = { + .num = ST_ACCEL_FS_AVL_16G, + .value = 0x03, + .gain = IIO_G_TO_M_S_2(187500), + }, + }, + }, + .drdy_irq = { + .int1 = { + .addr = 0x22, + .mask = 0x10, + }, + .addr_ihl = 0x25, + .mask_ihl = 0x02, + .stat_drdy = { + .addr = ST_SENSORS_DEFAULT_STAT_ADDR, + .mask = 0x07, + }, + }, + .sim = { + .addr = 0x23, + .value = BIT(0), + }, + .multi_read_bit = true, + .bootime = 2, + }, }; static int st_accel_read_raw(struct iio_dev *indio_dev, diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c index de8ae4327094..4e54477ccf24 100644 --- a/drivers/iio/accel/st_accel_i2c.c +++ b/drivers/iio/accel/st_accel_i2c.c @@ -102,6 +102,10 @@ static const struct of_device_id st_accel_of_match[] = { .compatible = "st,lis3de", .data = LIS3DE_ACCEL_DEV_NAME, }, + { + .compatible = "st,lis2de12", + .data = LIS2DE12_ACCEL_DEV_NAME, + }, {}, }; MODULE_DEVICE_TABLE(of, st_accel_of_match); @@ -140,6 +144,7 @@ static const struct i2c_device_id st_accel_id_table[] = { { LIS3LV02DL_ACCEL_DEV_NAME }, { LIS2DW12_ACCEL_DEV_NAME }, { LIS3DE_ACCEL_DEV_NAME }, + { LIS2DE12_ACCEL_DEV_NAME }, {}, }; MODULE_DEVICE_TABLE(i2c, st_accel_id_table); diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 846c7ace4b96..2036eca546fd 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -553,7 +553,7 @@ config MAX1363 To compile this driver as a module, choose M here: the module will be called max1363. -config MAX9611 +config MAX9611 tristate "Maxim max9611/max9612 ADC driver" depends on I2C help @@ -821,7 +821,9 @@ config STM32_DFSDM_ADC depends on (ARCH_STM32 && OF) || COMPILE_TEST select STM32_DFSDM_CORE select REGMAP_MMIO + select IIO_BUFFER select IIO_BUFFER_HW_CONSUMER + select IIO_TRIGGERED_BUFFER help Select this option to support ADCSigma delta modulator for STMicroelectronics STM32 digital filter for sigma delta converter. @@ -968,7 +970,7 @@ config TI_ADS1015 config TI_ADS7950 tristate "Texas Instruments ADS7950 ADC driver" - depends on SPI + depends on SPI && GPIOLIB select IIO_BUFFER select IIO_TRIGGERED_BUFFER help @@ -979,6 +981,16 @@ config TI_ADS7950 To compile this driver as a module, choose M here: the module will be called ti-ads7950. +config TI_ADS8344 + tristate "Texas Instruments ADS8344" + depends on SPI && OF + help + If you say yes here you get support for Texas Instruments ADS8344 + ADC chips + + This driver can also be built as a module. If so, the module will be + called ti-ads8344. + config TI_ADS8688 tristate "Texas Instruments ADS8688" depends on SPI && OF diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 085a7512f8df..ef9cc485fb67 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -88,6 +88,7 @@ obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o obj-$(CONFIG_TI_ADC161S626) += ti-adc161s626.o obj-$(CONFIG_TI_ADS1015) += ti-ads1015.o obj-$(CONFIG_TI_ADS7950) += ti-ads7950.o +obj-$(CONFIG_TI_ADS8344) += ti-ads8344.o obj-$(CONFIG_TI_ADS8688) += ti-ads8688.o obj-$(CONFIG_TI_ADS124S08) += ti-ads124s08.o obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c index ebb8de03bbce..24c70c3cefb4 100644 --- a/drivers/iio/adc/ad7606.c +++ b/drivers/iio/adc/ad7606.c @@ -31,7 +31,7 @@ * Scales are computed as 5000/32768 and 10000/32768 respectively, * so that when applied to the raw values they provide mV values */ -static const unsigned int scale_avail[2] = { +static const unsigned int ad7606_scale_avail[2] = { 152588, 305176 }; @@ -39,6 +39,10 @@ static const unsigned int ad7606_oversampling_avail[7] = { 1, 2, 4, 8, 16, 32, 64, }; +static const unsigned int ad7616_oversampling_avail[8] = { + 1, 2, 4, 8, 16, 32, 64, 128, +}; + static int ad7606_reset(struct ad7606_state *st) { if (st->gpio_reset) { @@ -154,7 +158,7 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: *val = 0; - *val2 = scale_avail[st->range]; + *val2 = st->scale_avail[st->range]; return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_OVERSAMPLING_RATIO: *val = st->oversampling; @@ -163,21 +167,31 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, return -EINVAL; } -static ssize_t in_voltage_scale_available_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t ad7606_show_avail(char *buf, const unsigned int *vals, + unsigned int n, bool micros) { - int i, len = 0; - - for (i = 0; i < ARRAY_SIZE(scale_avail); i++) - len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ", - scale_avail[i]); + size_t len = 0; + int i; + for (i = 0; i < n; i++) { + len += scnprintf(buf + len, PAGE_SIZE - len, + micros ? "0.%06u " : "%u ", vals[i]); + } buf[len - 1] = '\n'; return len; } +static ssize_t in_voltage_scale_available_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct ad7606_state *st = iio_priv(indio_dev); + + return ad7606_show_avail(buf, st->scale_avail, st->num_scales, true); +} + static IIO_DEVICE_ATTR_RO(in_voltage_scale_available, 0); static int ad7606_write_raw(struct iio_dev *indio_dev, @@ -193,7 +207,7 @@ static int ad7606_write_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_SCALE: mutex_lock(&st->lock); - i = find_closest(val2, scale_avail, ARRAY_SIZE(scale_avail)); + i = find_closest(val2, st->scale_avail, st->num_scales); gpiod_set_value(st->gpio_range, i); st->range = i; mutex_unlock(&st->lock); @@ -202,15 +216,20 @@ static int ad7606_write_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_OVERSAMPLING_RATIO: if (val2) return -EINVAL; - i = find_closest(val, ad7606_oversampling_avail, - ARRAY_SIZE(ad7606_oversampling_avail)); + i = find_closest(val, st->oversampling_avail, + st->num_os_ratios); values[0] = i; mutex_lock(&st->lock); gpiod_set_array_value(ARRAY_SIZE(values), st->gpio_os->desc, st->gpio_os->info, values); - st->oversampling = ad7606_oversampling_avail[i]; + + /* AD7616 requires a reset to update value */ + if (st->chip_info->os_req_reset) + ad7606_reset(st); + + st->oversampling = st->oversampling_avail[i]; mutex_unlock(&st->lock); return 0; @@ -219,11 +238,23 @@ static int ad7606_write_raw(struct iio_dev *indio_dev, } } -static IIO_CONST_ATTR(oversampling_ratio_available, "1 2 4 8 16 32 64"); +static ssize_t ad7606_oversampling_ratio_avail(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct ad7606_state *st = iio_priv(indio_dev); + + return ad7606_show_avail(buf, st->oversampling_avail, + st->num_os_ratios, false); +} + +static IIO_DEVICE_ATTR(oversampling_ratio_available, 0444, + ad7606_oversampling_ratio_avail, NULL, 0); static struct attribute *ad7606_attributes_os_and_range[] = { &iio_dev_attr_in_voltage_scale_available.dev_attr.attr, - &iio_const_attr_oversampling_ratio_available.dev_attr.attr, + &iio_dev_attr_oversampling_ratio_available.dev_attr.attr, NULL, }; @@ -232,7 +263,7 @@ static const struct attribute_group ad7606_attribute_group_os_and_range = { }; static struct attribute *ad7606_attributes_os[] = { - &iio_const_attr_oversampling_ratio_available.dev_attr.attr, + &iio_dev_attr_oversampling_ratio_available.dev_attr.attr, NULL, }; @@ -292,6 +323,36 @@ static const struct iio_chan_spec ad7606_channels[] = { AD7606_CHANNEL(7), }; +/* + * The current assumption that this driver makes for AD7616, is that it's + * working in Hardware Mode with Serial, Burst and Sequencer modes activated. + * To activate them, following pins must be pulled high: + * -SER/PAR + * -SEQEN + * And following pins must be pulled low: + * -WR/BURST + * -DB4/SER1W + */ +static const struct iio_chan_spec ad7616_channels[] = { + IIO_CHAN_SOFT_TIMESTAMP(16), + AD7606_CHANNEL(0), + AD7606_CHANNEL(1), + AD7606_CHANNEL(2), + AD7606_CHANNEL(3), + AD7606_CHANNEL(4), + AD7606_CHANNEL(5), + AD7606_CHANNEL(6), + AD7606_CHANNEL(7), + AD7606_CHANNEL(8), + AD7606_CHANNEL(9), + AD7606_CHANNEL(10), + AD7606_CHANNEL(11), + AD7606_CHANNEL(12), + AD7606_CHANNEL(13), + AD7606_CHANNEL(14), + AD7606_CHANNEL(15), +}; + static const struct ad7606_chip_info ad7606_chip_info_tbl[] = { /* More devices added in future */ [ID_AD7605_4] = { @@ -301,17 +362,27 @@ static const struct ad7606_chip_info ad7606_chip_info_tbl[] = { [ID_AD7606_8] = { .channels = ad7606_channels, .num_channels = 9, - .has_oversampling = true, + .oversampling_avail = ad7606_oversampling_avail, + .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), }, [ID_AD7606_6] = { .channels = ad7606_channels, .num_channels = 7, - .has_oversampling = true, + .oversampling_avail = ad7606_oversampling_avail, + .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), }, [ID_AD7606_4] = { .channels = ad7606_channels, .num_channels = 5, - .has_oversampling = true, + .oversampling_avail = ad7606_oversampling_avail, + .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), + }, + [ID_AD7616] = { + .channels = ad7616_channels, + .num_channels = 17, + .oversampling_avail = ad7616_oversampling_avail, + .oversampling_num = ARRAY_SIZE(ad7616_oversampling_avail), + .os_req_reset = true, }, }; @@ -343,7 +414,7 @@ static int ad7606_request_gpios(struct ad7606_state *st) if (IS_ERR(st->gpio_frstdata)) return PTR_ERR(st->gpio_frstdata); - if (!st->chip_info->has_oversampling) + if (!st->chip_info->oversampling_num) return 0; st->gpio_os = devm_gpiod_get_array_optional(dev, @@ -467,6 +538,8 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, /* tied to logic low, analog input range is +/- 5V */ st->range = 0; st->oversampling = 1; + st->scale_avail = ad7606_scale_avail; + st->num_scales = ARRAY_SIZE(ad7606_scale_avail); st->reg = devm_regulator_get(dev, "avcc"); if (IS_ERR(st->reg)) @@ -484,6 +557,11 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, st->chip_info = &ad7606_chip_info_tbl[id]; + if (st->chip_info->oversampling_num) { + st->oversampling_avail = st->chip_info->oversampling_avail; + st->num_os_ratios = st->chip_info->oversampling_num; + } + ret = ad7606_request_gpios(st); if (ret) return ret; diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h index 5d12410f68e1..f9ef52131e74 100644 --- a/drivers/iio/adc/ad7606.h +++ b/drivers/iio/adc/ad7606.h @@ -12,12 +12,17 @@ * struct ad7606_chip_info - chip specific information * @channels: channel specification * @num_channels: number of channels - * @has_oversampling: whether the device has oversampling support + * @oversampling_avail pointer to the array which stores the available + * oversampling ratios. + * @oversampling_num number of elements stored in oversampling_avail array + * @os_req_reset some devices require a reset to update oversampling */ struct ad7606_chip_info { const struct iio_chan_spec *channels; unsigned int num_channels; - bool has_oversampling; + const unsigned int *oversampling_avail; + unsigned int oversampling_num; + bool os_req_reset; }; /** @@ -29,6 +34,11 @@ struct ad7606_chip_info { * @range voltage range selection, selects which scale to apply * @oversampling oversampling selection * @base_address address from where to read data in parallel operation + * @scale_avail pointer to the array which stores the available scales + * @num_scales number of elements stored in the scale_avail array + * @oversampling_avail pointer to the array which stores the available + * oversampling ratios. + * @num_os_ratios number of elements stored in oversampling_avail array * @lock protect sensor state from concurrent accesses to GPIOs * @gpio_convst GPIO descriptor for conversion start signal (CONVST) * @gpio_reset GPIO descriptor for device hard-reset @@ -50,6 +60,10 @@ struct ad7606_state { unsigned int range; unsigned int oversampling; void __iomem *base_address; + const unsigned int *scale_avail; + unsigned int num_scales; + const unsigned int *oversampling_avail; + unsigned int num_os_ratios; struct mutex lock; /* protect sensor state */ struct gpio_desc *gpio_convst; @@ -64,9 +78,9 @@ struct ad7606_state { /* * DMA (thus cache coherency maintenance) requires the * transfer buffers to live in their own cache lines. - * 8 * 16-bit samples + 64-bit timestamp + * 16 * 16-bit samples + 64-bit timestamp */ - unsigned short data[12] ____cacheline_aligned; + unsigned short data[20] ____cacheline_aligned; }; /** @@ -86,7 +100,8 @@ enum ad7606_supported_device_ids { ID_AD7605_4, ID_AD7606_8, ID_AD7606_6, - ID_AD7606_4 + ID_AD7606_4, + ID_AD7616, }; #ifdef CONFIG_PM_SLEEP diff --git a/drivers/iio/adc/ad7606_spi.c b/drivers/iio/adc/ad7606_spi.c index 4fd0ec36a086..b7faef69a58f 100644 --- a/drivers/iio/adc/ad7606_spi.c +++ b/drivers/iio/adc/ad7606_spi.c @@ -53,6 +53,7 @@ static const struct spi_device_id ad7606_id_table[] = { { "ad7606-4", ID_AD7606_4 }, { "ad7606-6", ID_AD7606_6 }, { "ad7606-8", ID_AD7606_8 }, + { "ad7616", ID_AD7616 }, {} }; MODULE_DEVICE_TABLE(spi, ad7606_id_table); @@ -62,6 +63,7 @@ static const struct of_device_id ad7606_of_match[] = { { .compatible = "adi,ad7606-4" }, { .compatible = "adi,ad7606-6" }, { .compatible = "adi,ad7606-8" }, + { .compatible = "adi,ad7616" }, { }, }; MODULE_DEVICE_TABLE(of, ad7606_of_match); diff --git a/drivers/iio/adc/imx7d_adc.c b/drivers/iio/adc/imx7d_adc.c index ad6764fb2a23..958a34dd88ac 100644 --- a/drivers/iio/adc/imx7d_adc.c +++ b/drivers/iio/adc/imx7d_adc.c @@ -388,8 +388,9 @@ static irqreturn_t imx7d_adc_isr(int irq, void *dev_id) * timeout flags. */ if (status & IMX7D_REG_ADC_INT_STATUS_CHANNEL_CONV_TIME_OUT) { - pr_err("%s: ADC got conversion time out interrupt: 0x%08x\n", - dev_name(info->dev), status); + dev_err(info->dev, + "ADC got conversion time out interrupt: 0x%08x\n", + status); status &= ~IMX7D_REG_ADC_INT_STATUS_CHANNEL_CONV_TIME_OUT; writel(status, info->regs + IMX7D_REG_ADC_INT_STATUS); } @@ -433,167 +434,139 @@ static void imx7d_adc_power_down(struct imx7d_adc *info) writel(adc_cfg, info->regs + IMX7D_REG_ADC_ADC_CFG); } +static int imx7d_adc_enable(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct imx7d_adc *info = iio_priv(indio_dev); + int ret; + + ret = regulator_enable(info->vref); + if (ret) { + dev_err(info->dev, + "Can't enable adc reference top voltage, err = %d\n", + ret); + return ret; + } + + ret = clk_prepare_enable(info->clk); + if (ret) { + dev_err(info->dev, + "Could not prepare or enable clock.\n"); + regulator_disable(info->vref); + return ret; + } + + imx7d_adc_hw_init(info); + + return 0; +} + +static int imx7d_adc_disable(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct imx7d_adc *info = iio_priv(indio_dev); + + imx7d_adc_power_down(info); + + clk_disable_unprepare(info->clk); + regulator_disable(info->vref); + + return 0; +} + +static void __imx7d_adc_disable(void *data) +{ + imx7d_adc_disable(data); +} + static int imx7d_adc_probe(struct platform_device *pdev) { struct imx7d_adc *info; struct iio_dev *indio_dev; - struct resource *mem; + struct device *dev = &pdev->dev; int irq; int ret; - indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*info)); if (!indio_dev) { dev_err(&pdev->dev, "Failed allocating iio device\n"); return -ENOMEM; } info = iio_priv(indio_dev); - info->dev = &pdev->dev; + info->dev = dev; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - info->regs = devm_ioremap_resource(&pdev->dev, mem); + info->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(info->regs)) { ret = PTR_ERR(info->regs); - dev_err(&pdev->dev, - "Failed to remap adc memory, err = %d\n", ret); + dev_err(dev, "Failed to remap adc memory, err = %d\n", ret); return ret; } irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "No irq resource?\n"); + dev_err(dev, "No irq resource?\n"); return irq; } - info->clk = devm_clk_get(&pdev->dev, "adc"); + info->clk = devm_clk_get(dev, "adc"); if (IS_ERR(info->clk)) { ret = PTR_ERR(info->clk); - dev_err(&pdev->dev, "Failed getting clock, err = %d\n", ret); + dev_err(dev, "Failed getting clock, err = %d\n", ret); return ret; } - info->vref = devm_regulator_get(&pdev->dev, "vref"); + info->vref = devm_regulator_get(dev, "vref"); if (IS_ERR(info->vref)) { ret = PTR_ERR(info->vref); - dev_err(&pdev->dev, + dev_err(dev, "Failed getting reference voltage, err = %d\n", ret); return ret; } - ret = regulator_enable(info->vref); - if (ret) { - dev_err(&pdev->dev, - "Can't enable adc reference top voltage, err = %d\n", - ret); - return ret; - } - platform_set_drvdata(pdev, indio_dev); init_completion(&info->completion); - indio_dev->name = dev_name(&pdev->dev); - indio_dev->dev.parent = &pdev->dev; + 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; indio_dev->num_channels = ARRAY_SIZE(imx7d_adc_iio_channels); - ret = clk_prepare_enable(info->clk); - if (ret) { - dev_err(&pdev->dev, - "Could not prepare or enable the clock.\n"); - goto error_adc_clk_enable; - } - - ret = devm_request_irq(info->dev, irq, - imx7d_adc_isr, 0, - dev_name(&pdev->dev), info); + ret = devm_request_irq(dev, irq, + imx7d_adc_isr, 0, + dev_name(dev), info); if (ret < 0) { - dev_err(&pdev->dev, "Failed requesting irq, irq = %d\n", irq); - goto error_iio_device_register; + dev_err(dev, "Failed requesting irq, irq = %d\n", irq); + return ret; } imx7d_adc_feature_config(info); - imx7d_adc_hw_init(info); - - ret = iio_device_register(indio_dev); - if (ret) { - imx7d_adc_power_down(info); - dev_err(&pdev->dev, "Couldn't register the device.\n"); - goto error_iio_device_register; - } - - return 0; - -error_iio_device_register: - clk_disable_unprepare(info->clk); -error_adc_clk_enable: - regulator_disable(info->vref); - - return ret; -} - -static int imx7d_adc_remove(struct platform_device *pdev) -{ - struct iio_dev *indio_dev = platform_get_drvdata(pdev); - struct imx7d_adc *info = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - - imx7d_adc_power_down(info); - - clk_disable_unprepare(info->clk); - regulator_disable(info->vref); - - return 0; -} - -static int __maybe_unused imx7d_adc_suspend(struct device *dev) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct imx7d_adc *info = iio_priv(indio_dev); - - imx7d_adc_power_down(info); - - clk_disable_unprepare(info->clk); - regulator_disable(info->vref); - - return 0; -} -static int __maybe_unused imx7d_adc_resume(struct device *dev) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct imx7d_adc *info = iio_priv(indio_dev); - int ret; + ret = imx7d_adc_enable(&indio_dev->dev); + if (ret) + return ret; - ret = regulator_enable(info->vref); - if (ret) { - dev_err(info->dev, - "Can't enable adc reference top voltage, err = %d\n", - ret); + ret = devm_add_action_or_reset(dev, __imx7d_adc_disable, + &indio_dev->dev); + if (ret) return ret; - } - ret = clk_prepare_enable(info->clk); + ret = devm_iio_device_register(dev, indio_dev); if (ret) { - dev_err(info->dev, - "Could not prepare or enable clock.\n"); - regulator_disable(info->vref); + dev_err(&pdev->dev, "Couldn't register the device.\n"); return ret; } - imx7d_adc_hw_init(info); - return 0; } -static SIMPLE_DEV_PM_OPS(imx7d_adc_pm_ops, imx7d_adc_suspend, imx7d_adc_resume); +static SIMPLE_DEV_PM_OPS(imx7d_adc_pm_ops, imx7d_adc_disable, imx7d_adc_enable); static struct platform_driver imx7d_adc_driver = { .probe = imx7d_adc_probe, - .remove = imx7d_adc_remove, .driver = { .name = "imx7d_adc", .of_match_table = imx7d_adc_match, diff --git a/drivers/iio/adc/qcom-spmi-adc5.c b/drivers/iio/adc/qcom-spmi-adc5.c index 6a866cc187f7..21fdcde77883 100644 --- a/drivers/iio/adc/qcom-spmi-adc5.c +++ b/drivers/iio/adc/qcom-spmi-adc5.c @@ -664,6 +664,7 @@ static const struct of_device_id adc5_match_table[] = { }, { } }; +MODULE_DEVICE_TABLE(of, adc5_match_table); static int adc5_get_dt_data(struct adc5_chip *adc, struct device_node *node) { diff --git a/drivers/iio/adc/ti-ads8344.c b/drivers/iio/adc/ti-ads8344.c new file mode 100644 index 000000000000..9a460807d46d --- /dev/null +++ b/drivers/iio/adc/ti-ads8344.c @@ -0,0 +1,204 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * ADS8344 16-bit 8-Channel ADC driver + * + * Author: Gregory CLEMENT <gregory.clement@bootlin.com> + * + * Datasheet: http://www.ti.com/lit/ds/symlink/ads8344.pdf + */ + +#include <linux/delay.h> +#include <linux/iio/buffer.h> +#include <linux/iio/iio.h> +#include <linux/module.h> +#include <linux/regulator/consumer.h> +#include <linux/spi/spi.h> + +#define ADS8344_START BIT(7) +#define ADS8344_SINGLE_END BIT(2) +#define ADS8344_CHANNEL(channel) ((channel) << 4) +#define ADS8344_CLOCK_INTERNAL 0x2 /* PD1 = 1 and PD0 = 0 */ + +struct ads8344 { + struct spi_device *spi; + struct regulator *reg; + /* + * Lock protecting access to adc->tx_buff and rx_buff, + * especiall |