diff options
Diffstat (limited to 'drivers/iio/adc')
33 files changed, 1542 insertions, 265 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 82c718c515a0..767577298ee3 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -153,6 +153,18 @@ config AXP288_ADC To compile this driver as a module, choose M here: the module will be called axp288_adc. +config BCM_IPROC_ADC + tristate "Broadcom IPROC ADC driver" + depends on ARCH_BCM_IPROC || COMPILE_TEST + depends on MFD_SYSCON + default ARCH_BCM_CYGNUS + help + Say Y here if you want to add support for the Broadcom static + ADC driver. + + Broadcom iProc ADC driver. Broadcom iProc ADC controller has 8 + channels. The driver allows the user to read voltage values. + config BERLIN2_ADC tristate "Marvell Berlin2 ADC driver" depends on ARCH_BERLIN @@ -242,6 +254,16 @@ config LP8788_ADC To compile this driver as a module, choose M here: the module will be called lp8788_adc. +config LPC18XX_ADC + tristate "NXP LPC18xx ADC driver" + depends on ARCH_LPC18XX || COMPILE_TEST + depends on OF && HAS_IOMEM + help + Say yes here to build support for NXP LPC18XX ADC. + + To compile this driver as a module, choose M here: the module will be + called lpc18xx_adc. + config MAX1027 tristate "Maxim max1027 ADC driver" depends on SPI @@ -367,6 +389,7 @@ config QCOM_SPMI_VADC config ROCKCHIP_SARADC tristate "Rockchip SARADC driver" depends on ARCH_ROCKCHIP || (ARM && COMPILE_TEST) + depends on RESET_CONTROLLER help Say yes here to build support for the SARADC found in SoCs from Rockchip. @@ -375,11 +398,11 @@ config ROCKCHIP_SARADC module will be called rockchip_saradc. config TI_ADC081C - tristate "Texas Instruments ADC081C021/027" + tristate "Texas Instruments ADC081C/ADC101C/ADC121C family" depends on I2C help - If you say yes here you get support for Texas Instruments ADC081C021 - and ADC081C027 ADC chips. + If you say yes here you get support for Texas Instruments ADC081C, + ADC101C and ADC121C ADC chips. This driver can also be built as a module. If so, the module will be called ti-adc081c. diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 0cb79210a4b0..0ba0d500eedb 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_AD799X) += ad799x.o obj-$(CONFIG_AT91_ADC) += at91_adc.o obj-$(CONFIG_AT91_SAMA5D2_ADC) += at91-sama5d2_adc.o obj-$(CONFIG_AXP288_ADC) += axp288_adc.o +obj-$(CONFIG_BCM_IPROC_ADC) += bcm_iproc_adc.o obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o @@ -25,6 +26,7 @@ obj-$(CONFIG_HI8435) += hi8435.o obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o +obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX1363) += max1363.o obj-$(CONFIG_MCP320X) += mcp320x.o diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c index 21e19b60e2b9..c0f6a98fd9bd 100644 --- a/drivers/iio/adc/ad7266.c +++ b/drivers/iio/adc/ad7266.c @@ -154,12 +154,11 @@ static int ad7266_read_raw(struct iio_dev *indio_dev, switch (m) { case IIO_CHAN_INFO_RAW: - if (iio_buffer_enabled(indio_dev)) - return -EBUSY; - - ret = ad7266_read_single(st, val, chan->address); + ret = iio_device_claim_direct_mode(indio_dev); if (ret) return ret; + ret = ad7266_read_single(st, val, chan->address); + iio_device_release_direct_mode(indio_dev); *val = (*val >> 2) & 0xfff; if (chan->scan_type.sign == 's') @@ -396,8 +395,8 @@ static int ad7266_probe(struct spi_device *spi) st = iio_priv(indio_dev); - st->reg = devm_regulator_get(&spi->dev, "vref"); - if (!IS_ERR_OR_NULL(st->reg)) { + st->reg = devm_regulator_get_optional(&spi->dev, "vref"); + if (!IS_ERR(st->reg)) { ret = regulator_enable(st->reg); if (ret) return ret; @@ -408,6 +407,9 @@ static int ad7266_probe(struct spi_device *spi) st->vref_mv = ret / 1000; } else { + /* Any other error indicates that the regulator does exist */ + if (PTR_ERR(st->reg) != -ENODEV) + return PTR_ERR(st->reg); /* Use internal reference */ st->vref_mv = 2500; } @@ -438,6 +440,7 @@ static int ad7266_probe(struct spi_device *spi) 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 c0eabf156702..1d90b02732bb 100644 --- a/drivers/iio/adc/ad7291.c +++ b/drivers/iio/adc/ad7291.c @@ -115,7 +115,7 @@ static irqreturn_t ad7291_event_handler(int irq, void *private) u16 t_status, v_status; u16 command; int i; - s64 timestamp = iio_get_time_ns(); + s64 timestamp = iio_get_time_ns(indio_dev); if (ad7291_i2c_read(chip, AD7291_T_ALERT_STATUS, &t_status)) return IRQ_HANDLED; @@ -505,6 +505,7 @@ static int ad7291_probe(struct i2c_client *client, 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/ad7298.c b/drivers/iio/adc/ad7298.c index 62bb8f7ce4a0..10ec8fce395f 100644 --- a/drivers/iio/adc/ad7298.c +++ b/drivers/iio/adc/ad7298.c @@ -163,7 +163,7 @@ static irqreturn_t ad7298_trigger_handler(int irq, void *p) goto done; iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf, - iio_get_time_ns()); + iio_get_time_ns(indio_dev)); done: iio_trigger_notify_done(indio_dev->trig); @@ -315,6 +315,7 @@ static int ad7298_probe(struct spi_device *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 be85c2a0ad97..b7ecf9aab90f 100644 --- a/drivers/iio/adc/ad7476.c +++ b/drivers/iio/adc/ad7476.c @@ -70,7 +70,7 @@ static irqreturn_t ad7476_trigger_handler(int irq, void *p) goto done; iio_push_to_buffers_with_timestamp(indio_dev, st->data, - iio_get_time_ns()); + iio_get_time_ns(indio_dev)); done: iio_trigger_notify_done(indio_dev->trig); @@ -106,12 +106,11 @@ static int ad7476_read_raw(struct iio_dev *indio_dev, switch (m) { case IIO_CHAN_INFO_RAW: - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) - ret = -EBUSY; - else - ret = ad7476_scan_direct(st); - mutex_unlock(&indio_dev->mlock); + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + ret = ad7476_scan_direct(st); + iio_device_release_direct_mode(indio_dev); if (ret < 0) return ret; @@ -228,6 +227,7 @@ static int ad7476_probe(struct spi_device *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/ad7791.c b/drivers/iio/adc/ad7791.c index cf172d58cd44..1817ebf5ad84 100644 --- a/drivers/iio/adc/ad7791.c +++ b/drivers/iio/adc/ad7791.c @@ -272,30 +272,22 @@ static ssize_t ad7791_write_frequency(struct device *dev, struct ad7791_state *st = iio_priv(indio_dev); int i, ret; - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) { - mutex_unlock(&indio_dev->mlock); - return -EBUSY; - } - mutex_unlock(&indio_dev->mlock); - - ret = -EINVAL; - - for (i = 0; i < ARRAY_SIZE(ad7791_sample_freq_avail); i++) { - if (sysfs_streq(ad7791_sample_freq_avail[i], buf)) { - - mutex_lock(&indio_dev->mlock); - st->filter &= ~AD7791_FILTER_RATE_MASK; - st->filter |= i; - ad_sd_write_reg(&st->sd, AD7791_REG_FILTER, - sizeof(st->filter), st->filter); - mutex_unlock(&indio_dev->mlock); - ret = 0; + for (i = 0; i < ARRAY_SIZE(ad7791_sample_freq_avail); i++) + if (sysfs_streq(ad7791_sample_freq_avail[i], buf)) break; - } - } + if (i == ARRAY_SIZE(ad7791_sample_freq_avail)) + return -EINVAL; + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + st->filter &= ~AD7791_FILTER_RATE_MASK; + st->filter |= i; + ad_sd_write_reg(&st->sd, AD7791_REG_FILTER, sizeof(st->filter), + st->filter); + iio_device_release_direct_mode(indio_dev); - return ret ? ret : len; + return len; } static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, @@ -383,6 +375,7 @@ 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 7b07bb651671..847789bae821 100644 --- a/drivers/iio/adc/ad7793.c +++ b/drivers/iio/adc/ad7793.c @@ -369,13 +369,6 @@ static ssize_t ad7793_write_frequency(struct device *dev, long lval; int i, ret; - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) { - mutex_unlock(&indio_dev->mlock); - return -EBUSY; - } - mutex_unlock(&indio_dev->mlock); - ret = kstrtol(buf, 10, &lval); if (ret) return ret; @@ -383,20 +376,21 @@ static ssize_t ad7793_write_frequency(struct device *dev, if (lval == 0) return -EINVAL; - ret = -EINVAL; - for (i = 0; i < 16; i++) - if (lval == st->chip_info->sample_freq_avail[i]) { - mutex_lock(&indio_dev->mlock); - st->mode &= ~AD7793_MODE_RATE(-1); - st->mode |= AD7793_MODE_RATE(i); - ad_sd_write_reg(&st->sd, AD7793_REG_MODE, - sizeof(st->mode), st->mode); - mutex_unlock(&indio_dev->mlock); - ret = 0; - } + if (lval == st->chip_info->sample_freq_avail[i]) + break; + if (i == 16) + return -EINVAL; - return ret ? ret : len; + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + st->mode &= ~AD7793_MODE_RATE(-1); + st->mode |= AD7793_MODE_RATE(i); + ad_sd_write_reg(&st->sd, AD7793_REG_MODE, sizeof(st->mode), st->mode); + iio_device_release_direct_mode(indio_dev); + + return len; } static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, @@ -790,6 +784,7 @@ 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 2d3c397e66ad..7a483bfbd70c 100644 --- a/drivers/iio/adc/ad7887.c +++ b/drivers/iio/adc/ad7887.c @@ -122,7 +122,7 @@ static irqreturn_t ad7887_trigger_handler(int irq, void *p) goto done; iio_push_to_buffers_with_timestamp(indio_dev, st->data, - iio_get_time_ns()); + iio_get_time_ns(indio_dev)); done: iio_trigger_notify_done(indio_dev->trig); @@ -156,12 +156,11 @@ static int ad7887_read_raw(struct iio_dev *indio_dev, switch (m) { case IIO_CHAN_INFO_RAW: - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) - ret = -EBUSY; - else - ret = ad7887_scan_direct(st, chan->address); - mutex_unlock(&indio_dev->mlock); + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + ret = ad7887_scan_direct(st, chan->address); + iio_device_release_direct_mode(indio_dev); if (ret < 0) return ret; @@ -265,6 +264,7 @@ static int ad7887_probe(struct spi_device *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 45e29ccd824f..77a675e11ebb 100644 --- a/drivers/iio/adc/ad7923.c +++ b/drivers/iio/adc/ad7923.c @@ -181,7 +181,7 @@ static irqreturn_t ad7923_trigger_handler(int irq, void *p) goto done; iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf, - iio_get_time_ns()); + iio_get_time_ns(indio_dev)); done: iio_trigger_notify_done(indio_dev->trig); @@ -233,12 +233,11 @@ static int ad7923_read_raw(struct iio_dev *indio_dev, switch (m) { case IIO_CHAN_INFO_RAW: - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) - ret = -EBUSY; - else - ret = ad7923_scan_direct(st, chan->address); - mutex_unlock(&indio_dev->mlock); + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + ret = ad7923_scan_direct(st, chan->address); + iio_device_release_direct_mode(indio_dev); if (ret < 0) return ret; @@ -289,6 +288,7 @@ static int ad7923_probe(struct spi_device *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 = info->channels; indio_dev->num_channels = info->num_channels; diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c index 01d71588d752..9704090b7908 100644 --- a/drivers/iio/adc/ad799x.c +++ b/drivers/iio/adc/ad799x.c @@ -212,7 +212,7 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p) goto out; iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf, - iio_get_time_ns()); + iio_get_time_ns(indio_dev)); out: iio_trigger_notify_done(indio_dev->trig); @@ -282,12 +282,11 @@ static int ad799x_read_raw(struct iio_dev *indio_dev, switch (m) { case IIO_CHAN_INFO_RAW: - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) - ret = -EBUSY; - else - ret = ad799x_scan_direct(st, chan->scan_index); - mutex_unlock(&indio_dev->mlock); + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + ret = ad799x_scan_direct(st, chan->scan_index); + iio_device_release_direct_mode(indio_dev); if (ret < 0) return ret; @@ -395,11 +394,9 @@ static int ad799x_write_event_config(struct iio_dev *indio_dev, struct ad799x_state *st = iio_priv(indio_dev); int ret; - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) { - ret = -EBUSY; - goto done; - } + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; if (state) st->config |= BIT(chan->scan_index) << AD799X_CHANNEL_SHIFT; @@ -412,10 +409,7 @@ static int ad799x_write_event_config(struct iio_dev *indio_dev, st->config &= ~AD7998_ALERT_EN; ret = ad799x_write_config(st, st->config); - -done: - mutex_unlock(&indio_dev->mlock); - + iio_device_release_direct_mode(indio_dev); return ret; } @@ -477,7 +471,7 @@ static int ad799x_read_event_value(struct iio_dev *indio_dev, if (ret < 0) return ret; *val = (ret >> chan->scan_type.shift) & - GENMASK(chan->scan_type.realbits - 1 , 0); + GENMASK(chan->scan_type.realbits - 1, 0); return IIO_VAL_INT; } @@ -508,7 +502,7 @@ static irqreturn_t ad799x_event_handler(int irq, void *private) (i >> 1), IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), - iio_get_time_ns()); + iio_get_time_ns(indio_dev)); } done: @@ -533,6 +527,7 @@ static struct attribute_group ad799x_event_attrs_group = { static const struct iio_info ad7991_info = { .read_raw = &ad799x_read_raw, .driver_module = THIS_MODULE, + .update_scan_mode = ad799x_update_scan_mode, }; static const struct iio_info ad7993_4_7_8_noirq_info = { @@ -812,6 +807,7 @@ 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/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index 2e154cb51685..e10dca3ed74b 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -66,8 +66,10 @@ #define AT91_SAMA5D2_MR_PRESCAL(v) ((v) << AT91_SAMA5D2_MR_PRESCAL_OFFSET) #define AT91_SAMA5D2_MR_PRESCAL_OFFSET 8 #define AT91_SAMA5D2_MR_PRESCAL_MAX 0xff +#define AT91_SAMA5D2_MR_PRESCAL_MASK GENMASK(15, 8) /* Startup Time */ #define AT91_SAMA5D2_MR_STARTUP(v) ((v) << 16) +#define AT91_SAMA5D2_MR_STARTUP_MASK GENMASK(19, 16) /* Analog Change */ #define AT91_SAMA5D2_MR_ANACH BIT(23) /* Tracking Time */ @@ -92,13 +94,13 @@ /* Last Converted Data Register */ #define AT91_SAMA5D2_LCDR 0x20 /* Interrupt Enable Register */ -#define AT91_SAMA5D2_IER 0x24 +#define AT91_SAMA5D2_IER 0x24 /* Interrupt Disable Register */ -#define AT91_SAMA5D2_IDR 0x28 +#define AT91_SAMA5D2_IDR 0x28 /* Interrupt Mask Register */ -#define AT91_SAMA5D2_IMR 0x2c +#define AT91_SAMA5D2_IMR 0x2c /* Interrupt Status Register */ -#define AT91_SAMA5D2_ISR 0x30 +#define AT91_SAMA5D2_ISR 0x30 /* Last Channel Trigger Mode Register */ #define AT91_SAMA5D2_LCTMR 0x34 /* Last Channel Compare Window Register */ @@ -106,17 +108,20 @@ /* Overrun Status Register */ #define AT91_SAMA5D2_OVER 0x3c /* Extended Mode Register */ -#define AT91_SAMA5D2_EMR 0x40 +#define AT91_SAMA5D2_EMR 0x40 /* Compare Window Register */ -#define AT91_SAMA5D2_CWR 0x44 +#define AT91_SAMA5D2_CWR 0x44 /* Channel Gain Register */ -#define AT91_SAMA5D2_CGR 0x48 +#define AT91_SAMA5D2_CGR 0x48 + /* Channel Offset Register */ -#define AT91_SAMA5D2_COR 0x4c +#define AT91_SAMA5D2_COR 0x4c +#define AT91_SAMA5D2_COR_DIFF_OFFSET 16 + /* Channel Data Register 0 */ #define AT91_SAMA5D2_CDR0 0x50 /* Analog Control Register */ -#define AT91_SAMA5D2_ACR 0x94 +#define AT91_SAMA5D2_ACR 0x94 /* Touchscreen Mode Register */ #define AT91_SAMA5D2_TSMR 0xb0 /* Touchscreen X Position Register */ @@ -130,7 +135,7 @@ /* Correction Select Register */ #define AT91_SAMA5D2_COSR 0xd0 /* Correction Value Register */ -#define AT91_SAMA5D2_CVR 0xd4 +#define AT91_SAMA5D2_CVR 0xd4 /* Channel Error Correction Register */ #define AT91_SAMA5D2_CECR 0xd8 /* Write Protection Mode Register */ @@ -140,7 +145,7 @@ /* Version Register */ #define AT91_SAMA5D2_VERSION 0xfc -#define AT91_AT91_SAMA5D2_CHAN(num, addr) \ +#define AT91_SAMA5D2_CHAN_SINGLE(num, addr) \ { \ .type = IIO_VOLTAGE, \ .channel = num, \ @@ -156,6 +161,24 @@ .indexed = 1, \ } +#define AT91_SAMA5D2_CHAN_DIFF(num, num2, addr) \ + { \ + .type = IIO_VOLTAGE, \ + .differential = 1, \ + .channel = num, \ + .channel2 = num2, \ + .address = addr, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 12, \ + }, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\ + .datasheet_name = "CH"#num"-CH"#num2, \ + .indexed = 1, \ + } + #define at91_adc_readl(st, reg) readl_relaxed(st->base + reg) #define at91_adc_writel(st, reg, val) writel_relaxed(val, st->base + reg) @@ -185,18 +208,24 @@ struct at91_adc_state { }; static const struct iio_chan_spec at91_adc_channels[] = { - AT91_AT91_SAMA5D2_CHAN(0, 0x50), - AT91_AT91_SAMA5D2_CHAN(1, 0x54), - AT91_AT91_SAMA5D2_CHAN(2, 0x58), - AT91_AT91_SAMA5D2_CHAN(3, 0x5c), - AT91_AT91_SAMA5D2_CHAN(4, 0x60), - AT91_AT91_SAMA5D2_CHAN(5, 0x64), - AT91_AT91_SAMA5D2_CHAN(6, 0x68), - AT91_AT91_SAMA5D2_CHAN(7, 0x6c), - AT91_AT91_SAMA5D2_CHAN(8, 0x70), - AT91_AT91_SAMA5D2_CHAN(9, 0x74), - AT91_AT91_SAMA5D2_CHAN(10, 0x78), - AT91_AT91_SAMA5D2_CHAN(11, 0x7c), + AT91_SAMA5D2_CHAN_SINGLE(0, 0x50), + AT91_SAMA5D2_CHAN_SINGLE(1, 0x54), + AT91_SAMA5D2_CHAN_SINGLE(2, 0x58), + AT91_SAMA5D2_CHAN_SINGLE(3, 0x5c), + AT91_SAMA5D2_CHAN_SINGLE(4, 0x60), + AT91_SAMA5D2_CHAN_SINGLE(5, 0x64), + AT91_SAMA5D2_CHAN_SINGLE(6, 0x68), + AT91_SAMA5D2_CHAN_SINGLE(7, 0x6c), + AT91_SAMA5D2_CHAN_SINGLE(8, 0x70), + AT91_SAMA5D2_CHAN_SINGLE(9, 0x74), + AT91_SAMA5D2_CHAN_SINGLE(10, 0x78), + AT91_SAMA5D2_CHAN_SINGLE(11, 0x7c), + AT91_SAMA5D2_CHAN_DIFF(0, 1, 0x50), + AT91_SAMA5D2_CHAN_DIFF(2, 3, 0x58), + AT91_SAMA5D2_CHAN_DIFF(4, 5, 0x60), + AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68), + AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70), + AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78), }; static unsigned at91_adc_startup_time(unsigned startup_time_min, @@ -226,7 +255,7 @@ static unsigned at91_adc_startup_time(unsigned startup_time_min, static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq) { struct iio_dev *indio_dev = iio_priv_to_dev(st); - unsigned f_per, prescal, startup; + unsigned f_per, prescal, startup, mr; f_per = clk_get_rate(st->per_clk); prescal = (f_per / (2 * freq)) - 1; @@ -234,10 +263,11 @@ static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq) startup = at91_adc_startup_time(st->soc_info.startup_time, freq / 1000); - at91_adc_writel(st, AT91_SAMA5D2_MR, - AT91_SAMA5D2_MR_TRANSFER(2) - | AT91_SAMA5D2_MR_STARTUP(startup) - | AT91_SAMA5D2_MR_PRESCAL(prescal)); + mr = at91_adc_readl(st, AT91_SAMA5D2_MR); + mr &= ~(AT91_SAMA5D2_MR_STARTUP_MASK | AT91_SAMA5D2_MR_PRESCAL_MASK); + mr |= AT91_SAMA5D2_MR_STARTUP(startup); + mr |= AT91_SAMA5D2_MR_PRESCAL(prescal); + at91_adc_writel(st, AT91_SAMA5D2_MR, mr); dev_dbg(&indio_dev->dev, "freq: %u, startup: %u, prescal: %u\n", freq, startup, prescal); @@ -278,6 +308,7 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { struct at91_adc_state *st = iio_priv(indio_dev); + u32 cor = 0; int ret; switch (mask) { @@ -286,6 +317,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, st->chan = chan; + if (chan->differential) + cor = (BIT(chan->channel) | BIT(chan->channel2)) << + AT91_SAMA5D2_COR_DIFF_OFFSET; + + at91_adc_writel(st, AT91_SAMA5D2_COR, cor); at91_adc_writel(st, AT91_SAMA5D2_CHER, BIT(chan->channel)); at91_adc_writel(st, AT91_SAMA5D2_IER, BIT(chan->channel)); at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_START); @@ -298,6 +334,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, if (ret > 0) { *val = st->conversion_value; + if (chan->scan_type.sign == 's') + *val = sign_extend32(*val, 11); ret = IIO_VAL_INT; st->conversion_done = false; } @@ -310,6 +348,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: *val = st->vref_uv / 1000; + if (chan->differential) + *val *= 2; *val2 = chan->scan_type.realbits; return IIO_VAL_FRACTIONAL_LOG2; @@ -444,6 +484,12 @@ static int at91_adc_probe(struct platform_device *pdev) at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST); at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff); + /* + * Transfer field must be set to 2 according to the datasheet and + * allows different analog settings for each channel. + */ + 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); diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index f284cd6a93d6..0438c68015e8 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -381,8 +381,8 @@ static irqreturn_t at91_adc_rl_interrupt(int irq, void *private) st->ts_bufferedmeasure = false; input_report_key(st->ts_input, BTN_TOUCH, 0); input_sync(st->ts_input); - } else if (status & AT91_ADC_EOC(3)) { - /* Conversion finished */ + } else if (status & AT91_ADC_EOC(3) && st->ts_input) { + /* Conversion finished and we've a touchscreen */ if (st->ts_bufferedmeasure) { /* * Last measurement is always discarded, since it can @@ -797,8 +797,8 @@ static u32 calc_startup_ticks_9x5(u32 startup_time, u32 adc_clk_khz) * Startup Time = <lookup_table_value> / ADC Clock */ const int startup_lookup[] = { - 0 , 8 , 16 , 24 , - 64 , 80 , 96 , 112, + 0, 8, 16, 24, + 64, 80, 96, 112, 512, 576, 640, 704, 768, 832, 896, 960 }; @@ -924,14 +924,14 @@ static int at91_adc_probe_dt(struct at91_adc_state *st, ret = -EINVAL; goto error_ret; } - trig->name = name; + trig->name = name; if (of_property_read_u32(trig_node, "trigger-value", &prop)) { dev_err(&idev->dev, "Missing trigger-value property in the DT.\n"); ret = -EINVAL; goto error_ret; } - trig->value = prop; + trig->value = prop; trig->is_external = of_property_read_bool(trig_node, "trigger-external"); i++; } diff --git a/drivers/iio/adc/bcm_iproc_adc.c b/drivers/iio/adc/bcm_iproc_adc.c new file mode 100644 index 000000000000..21d38c8af21e --- /dev/null +++ b/drivers/iio/adc/bcm_iproc_adc.c @@ -0,0 +1,644 @@ +/* + * Copyright 2016 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ + +#include <linux/module.h> +#include <linux/of.h> +#include <linux/io.h> +#include <linux/clk.h> +#include <linux/mfd/syscon.h> +#include <linux/regmap.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> + +#include <linux/iio/iio.h> + +/* Below Register's are common to IPROC ADC and Touchscreen IP */ +#define IPROC_REGCTL1 0x00 +#define IPROC_REGCTL2 0x04 +#define IPROC_INTERRUPT_THRES 0x08 +#define IPROC_INTERRUPT_MASK 0x0c +#define IPROC_INTERRUPT_STATUS 0x10 +#define IPROC_ANALOG_CONTROL 0x1c +#define IPROC_CONTROLLER_STATUS 0x14 +#define IPROC_AUX_DATA 0x20 +#define IPROC_SOFT_BYPASS_CONTROL 0x38 +#define IPROC_SOFT_BYPASS_DATA 0x3C + +/* IPROC ADC Channel register offsets */ +#define IPROC_ADC_CHANNEL_REGCTL1 0x800 +#define IPROC_ADC_CHANNEL_REGCTL2 0x804 +#define IPROC_ADC_CHANNEL_STATUS 0x808 +#define IPROC_ADC_CHANNEL_INTERRUPT_STATUS 0x80c +#define IPROC_ADC_CHANNEL_INTERRUPT_MASK 0x810 +#define IPROC_ADC_CHANNEL_DATA 0x814 +#define IPROC_ADC_CHANNEL_OFFSET 0x20 + +/* Bit definitions for IPROC_REGCTL2 */ +#define IPROC_ADC_AUXIN_SCAN_ENA BIT(0) +#define IPROC_ADC_PWR_LDO BIT(5) +#define IPROC_ADC_PWR_ADC BIT(4) +#define IPROC_ADC_PWR_BG BIT(3) +#define IPROC_ADC_CONTROLLER_EN BIT(17) + +/* Bit definitions for IPROC_INTERRUPT_MASK and IPROC_INTERRUPT_STATUS */ +#define IPROC_ADC_AUXDATA_RDY_INTR BIT(3) +#define IPROC_ADC_INTR 9 +#define IPROC_ADC_INTR_MASK (0xFF << IPROC_ADC_INTR) + +/* Bit definitions for IPROC_ANALOG_CONTROL */ +#define IPROC_ADC_CHANNEL_SEL 11 +#define IPROC_ADC_CHANNEL_SEL_MASK (0x7 << IPROC_ADC_CHANNEL_SEL) + +/* Bit definitions for IPROC_ADC_CHANNEL_REGCTL1 */ +#define IPROC_ADC_CHANNEL_ROUNDS 0x2 +#define IPROC_ADC_CHANNEL_ROUNDS_MASK (0x3F << IPROC_ADC_CHANNEL_ROUNDS) +#define IPROC_ADC_CHANNEL_MODE 0x1 +#define IPROC_ADC_CHANNEL_MODE_MASK (0x1 << IPROC_ADC_CHANNEL_MODE) +#define IPROC_ADC_CHANNEL_MODE_TDM 0x1 +#define IPROC_ADC_CHANNEL_MODE_SNAPSHOT 0x0 +#define IPROC_ADC_CHANNEL_ENABLE 0x0 +#define IPROC_ADC_CHANNEL_ENABLE_MASK 0x1 + +/* Bit definitions for IPROC_ADC_CHANNEL_REGCTL2 */ +#define IPROC_ADC_CHANNEL_WATERMARK 0x0 +#define IPROC_ADC_CHANNEL_WATERMARK_MASK \ + (0x3F << IPROC_ADC_CHANNEL_WATERMARK) + +#define IPROC_ADC_WATER_MARK_LEVEL 0x1 + +/* Bit definitions for IPROC_ADC_CHANNEL_STATUS */ +#define IPROC_ADC_CHANNEL_DATA_LOST 0x0 +#define IPROC_ADC_CHANNEL_DATA_LOST_MASK \ + (0x0 << IPROC_ADC_CHANNEL_DATA_LOST) +#define IPROC_ADC_CHANNEL_VALID_ENTERIES 0x1 +#define IPROC_ADC_CHANNEL_VALID_ENTERIES_MASK \ + (0xFF << IPROC_ADC_CHANNEL_VALID_ENTERIES) +#define IPROC_ADC_CHANNEL_TOTAL_ENTERIES 0x9 +#define IPROC_ADC_CHANNEL_TOTAL_ENTERIES_MASK \ + (0xFF << IPROC_ADC_CHANNEL_TOTAL_ENTERIES) + +/* Bit definitions for IPROC_ADC_CHANNEL_INTERRUPT_MASK */ +#define IPROC_ADC_CHANNEL_WTRMRK_INTR 0x0 +#define IPROC_ADC_CHANNEL_WTRMRK_INTR_MASK \ + (0x1 << IPROC_ADC_CHANNEL_WTRMRK_INTR) +#define IPROC_ADC_CHANNEL_FULL_INTR 0x1 +#define IPROC_ADC_CHANNEL_FULL_INTR_MASK \ + (0x1 << IPROC_ADC_IPROC_ADC_CHANNEL_FULL_INTR) +#define IPROC_ADC_CHANNEL_EMPTY_INTR 0x2 +#define IPROC_ADC_CHANNEL_EMPTY_INTR_MASK \ + (0x1 << IPROC_ADC_CHANNEL_EMPTY_INTR) + +#define IPROC_ADC_WATER_MARK_INTR_ENABLE 0x1 + +/* Number of time to retry a set of the interrupt mask reg */ +#define IPROC_ADC_INTMASK_RETRY_ATTEMPTS 10 + +#define IPROC_ADC_READ_TIMEOUT (HZ*2) + +#define iproc_adc_dbg_reg(dev, priv, reg) \ +do { \ + u32 val; \ + regmap_read(priv->regmap, reg, &val); \ + dev_dbg(dev, "%20s= 0x%08x\n", #reg, val); \ +} while (0) + +struct iproc_adc_priv { + struct regmap *regmap; + struct clk *adc_clk; + struct mutex mutex; + int irqno; + int chan_val; + int chan_id; + struct completion completion; +}; + +static void iproc_adc_reg_dump(struct iio_dev *indio_dev) +{ + struct device *dev = &indio_dev->dev; + struct iproc_adc_priv *adc_priv = iio_priv(indio_dev); + + iproc_adc_dbg_reg(dev, adc_priv, IPROC_REGCTL1); + iproc_adc_dbg_reg(dev, adc_priv, IPROC_REGCTL2); + iproc_adc_dbg_reg(dev, adc_priv, IPROC_INTERRUPT_THRES); + iproc_adc_dbg_reg(dev, adc_priv, IPROC_INTERRUPT_MASK); + iproc_adc_dbg_reg(dev, adc_priv, IPROC_INTERRUPT_STATUS); + iproc_adc_dbg_reg(dev, adc_priv, IPROC_CONTROLLER_STATUS); + iproc_adc_dbg_reg(dev, adc_priv, IPROC_ANALOG_CONTROL); + iproc_adc_dbg_reg(dev, adc_priv, IPROC_AUX_DATA); + iproc_adc_dbg_reg(dev, adc_priv, IPROC_SOFT_BYPASS_CONTROL); + iproc_adc_dbg_reg(dev, adc_priv, IPROC_SOFT_BYPASS_DATA); +} + +static irqreturn_t iproc_adc_interrupt_handler(int irq, void *data) +{ + u32 channel_intr_status; + u32 intr_status; + u32 intr_mask; + struct iio_dev *indio_dev = data; + struct iproc_adc_priv *adc_priv = iio_priv(indio_dev); + + /* + * This interrupt is shared with the touchscreen driver. + * Make sure this interrupt is intended for us. + * Handle only ADC channel specific interrupts. + */ + regmap_read(adc_priv->regmap, IPROC_INTERRUPT_STATUS, &intr_status); + regmap_read(adc_priv->regmap, IPROC_INTERRUPT_MASK, &intr_mask); + intr_status = intr_status & intr_mask; + channel_intr_status = (intr_status & IPROC_ADC_INTR_MASK) >> + IPROC_ADC_INTR; + if (channel_intr_status) + return IRQ_WAKE_THREAD; + + return IRQ_NONE; +} + +static irqreturn_t iproc_adc_interrupt_thread(int irq, void *data) +{ + irqreturn_t retval = IRQ_NONE; + struct iproc_adc_priv *adc_priv; + struct iio_dev *indio_dev = data; + unsigned int valid_entries; + u32 intr_status; + u32 intr_channels; + u32 channel_status; + u32 ch_intr_status; + + adc_priv = iio_priv(indio_dev); + + regmap_read(adc_priv->regmap, IPROC_INTERRUPT_STATUS, &intr_status); + dev_dbg(&indio_dev->dev, "iproc_adc_interrupt_thread(),INTRPT_STS:%x\n", + intr_status); + + intr_channels = (intr_status & IPROC_ADC_INTR_MASK) >> IPROC_ADC_INTR; + if (intr_channels) { + regmap_read(adc_priv->regmap, + IPROC_ADC_CHANNEL_INTERRUPT_STATUS + + IPROC_ADC_CHANNEL_OFFSET * adc_priv->chan_id, + &ch_intr_status); + + if (ch_intr_status & IPROC_ADC_CHANNEL_WTRMRK_INTR_MASK) { + regmap_read(adc_priv->regmap, + IPROC_ADC_CHANNEL_STATUS + + IPROC_ADC_CHANNEL_OFFSET * + adc_priv->chan_id, + &channel_status); + + valid_entries = ((channel_status & + IPROC_ADC_CHANNEL_VALID_ENTERIES_MASK) >> + IPROC_ADC_CHANNEL_VALID_ENTERIES); + if (valid_entries >= 1) { + regmap_read(adc_priv->regmap, + IPROC_ADC_CHANNEL_DATA + + IPROC_ADC_CHANNEL_OFFSET * + adc_priv->chan_id, + &adc_priv->chan_val); + complete(&adc_priv->completion); + } else { + dev_err(&indio_dev->dev, + "No data rcvd on channel %d\n", + adc_priv->chan_id); + } + regmap_write(adc_priv->regmap, + IPROC_ADC_CHANNEL_INTERRUPT_MASK + + IPROC_ADC_CHANNEL_OFFSET * + adc_priv->chan_id, + (ch_intr_status & + ~(IPROC_ADC_CHANNEL_WTRMRK_INTR_MASK))); + } + regmap_write(adc_priv->regmap, + IPROC_ADC_CHANNEL_INTERRUPT_STATUS + + IPROC_ADC_CHANNEL_OFFSET * adc_priv->chan_id, + ch_intr_status); + regmap_write(adc_priv->regmap, IPROC_INTERRUPT_STATUS, + intr_channels); + retval = IRQ_HANDLED; + } + + return retval; +} + +static int iproc_adc_do_read(struct iio_dev *indio_dev, + int channel, + u16 *p_adc_data) +{ + int read_len = 0; + u32 val; + u32 mask; + u32 val_check; + int failed_cnt = 0; + struct iproc_adc_priv *adc_priv = iio_priv(indio_dev); + + mutex_lock(&adc_priv->mutex); + + /* + * After a read is complete the ADC interrupts will be disabled so + * we can assume this section of code is safe from interrupts. + */ + adc_priv->chan_val = -1; + adc_priv->chan_id = channel; + + reinit_completion(&adc_priv->completion); + /* Clear any pending interrupt */ + regmap_update_bits(adc_priv->regmap, IPROC_INTERRUPT_STATUS, + IPROC_ADC_INTR_MASK | IPROC_ADC_AUXDATA_RDY_INTR, + ((0x0 << channel) << IPROC_ADC_INTR) | + IPROC_ADC_AUXDATA_RDY_INTR); + + /* Configure channel for snapshot mode and enable */ + val = (BIT(IPROC_ADC_CHANNEL_ROUNDS) | + (IPROC_ADC_CHANNEL_MODE_SNAPSHOT << IPROC_ADC_CHANNEL_MODE) | + (0x1 << IPROC_ADC_CHANNEL_ENABLE)); + + mask = IPROC_ADC_CHANNEL_ROUNDS_MASK | IPROC_ADC_CHANNEL_MODE_MASK | + IPROC_ADC_CHANNEL_ENABLE_MASK; + regmap_update_bits(adc_priv->regmap, (IPROC_ADC_CHANNEL_REGCTL1 + + IPROC_ADC_CHANNEL_OFFSET * channel), + mask, val); + + /* Set the Watermark for a channel */ + regmap_update_bits(adc_priv->regmap, (IPROC_ADC_CHANNEL_REGCTL2 + + IPROC_ADC_CHANNEL_OFFSET * channel), + IPROC_ADC_CHANNEL_WATERMARK_MASK, + 0x1); + + /* Enable water mark interrupt */ + regmap_update_bits(adc_priv->regmap, (IPROC_ADC_CHANNEL_INTERRUPT_MASK + + IPROC_ADC_CHANNEL_OFFSET * + channel), + IPROC_ADC_CHANNEL_WTRMRK_INTR_MASK, + IPROC_ADC_WATER_MARK_INTR_ENABLE); + regmap_read(adc_priv->regmap, IPROC_INTERRUPT_MASK, &val); + + /* Enable ADC interrupt for a channel */ + val |= (BIT(channel) << IPROC_ADC_INTR); + regmap_write(adc_priv->regmap, IPROC_INTERRUPT_MASK, val); + + /* + * There seems to be a very rare issue where writing to this register + * does not take effect. To work around the issue we will try multiple + * writes. In total we will spend about 10*10 = 100 us attempting this. + * Testing has shown that this may loop a few time, but we have never + * hit the full count. + */ + regmap_read(adc_priv->regmap, IPROC_INTERRUPT_MASK, &val_check); + while (val_check != val) { + failed_cnt++; + + if (failed_cnt > IPROC_ADC_INTMASK_RETRY_ATTEMPTS) + break; + + udelay(10); + regmap_update_bits(adc_priv->regmap, IPROC_INTERRUPT_MASK, + IPROC_ADC_INTR_MASK, + ((0x1 << channel) << + IPROC_ADC_INTR)); + + regmap_read(adc_priv->regmap, IPROC_INTERRUPT_MASK, &val_check); + } + + if (failed_cnt) { + dev_dbg(&indio_dev->dev, + "IntMask failed (%d times)", failed_cnt); + if (failed_cnt > IPROC_ADC_INTMASK_RETRY_ATTEMPTS) { + dev_err(&indio_dev->dev, + "IntMask set failed. Read will likely fail."); + read_len = -EIO; + goto adc_err; + }; + } + regmap_read(adc_priv->regmap, IPROC_INTERRUPT_MASK, &val_check); + + if (wait_for_completion_timeout(&adc_priv->completion, + IPROC_ADC_READ_TIMEOUT) > 0) { + + /* Only the lower 16 bits are relevant */ + *p_adc_data = adc_priv->chan_val & 0xFFFF; + read_len = sizeof(*p_adc_data); + + } else { + /* + * We never got the interrupt, something went wrong. + * Perhaps the interrupt may still be coming, we do not want + * that now. Lets disable the ADC interrupt, and clear the + * status to put it back in to normal state. + */ + read_len = -ETIMEDOUT; + goto adc_err; + } + mutex_unlock(&adc_priv->mutex); + + return read_len; + +adc_err: + regmap_update_bits(adc_priv->regmap, IPROC_INTERRUPT_MASK, + IPROC_ADC_INTR_MASK, + ((0x0 << channel) << IPROC_ADC_INTR)); + + regmap_update_bits(adc_priv->regmap, IPROC_INTERRUPT_STATUS, + IPROC_ADC_INTR_MASK, + ((0x0 << channel) << IPROC_ADC_INTR)); + + dev_err(&indio_dev->dev, "Timed out waiting for ADC data!\n"); + iproc_adc_reg_dump(indio_dev); + mutex_unlock(&adc_priv->mutex); + + return read_len; +} + +static int iproc_adc_enable(struct iio_dev *indio_dev) +{ + u32 val; + u32 channel_id; + struct iproc_adc_priv *adc_priv = iio_priv(indio_dev); + int ret; + + /* Set i_amux = 3b'000, select channel 0 */ + ret = regmap_update_bits(adc_priv->regmap, IPROC_ANALOG_CONTROL, + IPROC_ADC_CHANNEL_SEL_MASK, 0); + if (ret) { + dev_err(&indio_dev->dev, + "failed to write IPROC_ANALOG_CONTROL %d\n", ret); + return ret; + } + adc_priv->chan_val = -1; + + /* + * PWR up LDO, ADC, and Band Gap (0 to enable) + * Also enable ADC controller (set high) + */ + ret = regmap_read(adc_priv->regmap, IPROC_REGCTL2, &val); + if (ret) { + dev_err(&indio_dev->dev, + "failed to read IPROC_REGCTL2 %d\n", ret); + return ret; + } + + val &= ~(IPROC_ADC_PWR_LDO | IPROC_ADC_PWR_ADC | IPROC_ADC_PWR_BG); + + ret = regmap_write(adc_priv->regmap, IPROC_REGCTL2, val); + if (ret) { + dev_err(&indio_dev->dev, + "failed to write IPROC_REGCTL2 %d\n", ret); + return ret; + } + + ret = regmap_read(adc_priv->regmap, IPROC_REGCTL2, &val); + if (ret) { + dev_err(&indio_dev->dev, + "failed to read IPROC_REGCTL2 %d\n", ret); + return ret; + } + + val |= IPROC_ADC_CONTROLLER_EN; + ret = regmap_write(adc_priv->regmap, IPROC_REGCTL2, val); + if (ret) { + dev_err(&indio_dev->dev, + "failed to write IPROC_REGCTL2 %d\n", ret); + return ret; + } + + for (channel_id = 0; channel_id < indio_dev->num_channels; + channel_id++) { + ret = regmap_write(adc_priv->regmap, + IPROC_ADC_CHANNEL_INTERRUPT_MASK + + IPROC_ADC_CHANNEL_OFFSET * channel_id, 0); + if (ret) { + dev_err(&indio_dev->dev, + "failed to write ADC_CHANNEL_INTERRUPT_MASK %d\n", + ret); + return ret; + } + + ret = regmap_write(adc_priv->regmap, + IPROC_ADC_CHANNEL_INTERRUPT_STATUS + + IPROC_ADC_CHANNEL_OFFSET * channel_id, 0); + if (ret) { + dev_err(&indio_dev->dev, + "failed to write ADC_CHANNEL_INTERRUPT_STATUS %d\n", + ret); + return ret; + } + } + + return 0; +} + +static void iproc_adc_disable(struct iio_dev *indio_dev) +{ + u32 val; + int ret; + struct iproc_adc_priv *adc_priv = iio_priv(indio_dev); + + ret = regmap_read(adc_priv->regmap, IPROC_REGCTL2, &val); + if (ret) { + dev_err(&indio_dev->dev, + "failed to read IPROC_REGCTL2 %d\n", ret); + return; + } + + val &= ~IPROC_ADC_CONTROLLER_EN; + ret = regmap_write(adc_priv->regmap, IPROC_REGCTL2, val); + if (ret) { + dev_err(&indio_dev->dev, + "failed to write IPROC_REGCTL2 %d\n", ret); + return; + } +} + +static int iproc_adc_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + u16 adc_data; + int err; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + err = iproc_adc_do_read(indio_dev, chan->channel, &adc_data); + if (err < 0) + return err; + *val = adc_data; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_VOLTAGE: + *val = 1800; + *val2 = 10; + return IIO_VAL_FRACTIONAL_LOG2; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static const struct iio_info iproc_adc_iio_info = { + .read_raw = &iproc_adc_read_raw, + .driver_module = THIS_MODULE, +}; + +#define IPROC_ADC_CHANNEL(_index, _id) { \ + .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, \ +} + +static const struct iio_chan_spec iproc_adc_iio_channels[] = { + IPROC_ADC_CHANNEL(0, "adc0"), + IPROC_ADC_CHANNEL(1, "adc1"), + IPROC_ADC_CHANNEL(2, "adc2"), + IPROC_ADC_CHANNEL(3, "adc3"), + IPROC_ADC_CHANNEL(4, "adc4"), + IPROC_ADC_CHANNEL(5, "adc5"), + IPROC_ADC_CHANNEL(6, "adc6"), + IPROC_ADC_CHANNEL(7, "adc7"), +}; + +static int iproc_adc_probe(struct platform_device *pdev) +{ + struct iproc_adc_priv *adc_priv; + struct iio_dev *indio_dev = NULL; + int ret; + + indio_dev = devm_iio_device_alloc(&pdev->dev, + sizeof(*adc_priv)); + if (!indio_dev) { + dev_err(&pdev->dev, "failed to allocate iio device\n"); + return -ENOMEM; + } + + adc_priv = iio_priv(indio_dev); + platform_set_drvdata(pdev, indio_dev); + + mutex_init(&adc_priv->mutex); + + init_completion(&adc_priv->completion); + + adc_priv->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, + "adc-syscon"); + if (IS_ERR(adc_priv->regmap)) { + dev_err(&pdev->dev, "failed to get handle for tsc syscon\n"); + ret = PTR_ERR(adc_priv->regmap); + return ret; + } + + adc_priv->adc_clk = devm_clk_get(&pdev->dev, "tsc_clk"); + if (IS_ERR(adc_priv->adc_clk)) { + dev_err(&pdev->dev, + "failed getting clock tsc_clk\n"); + ret = PTR_ERR(adc_priv->adc_clk); + return ret; + } + + adc_priv->irqno = platform_get_irq(pdev, 0); + if (adc_priv->irqno <= 0) { + dev_err(&pdev->dev, "platform_get_irq failed\n"); + ret = -ENODEV; + return ret; + } + + ret = regmap_update_bits(adc_priv->regmap, IPROC_REGCTL2, + IPROC_ADC_AUXIN_SCAN_ENA, 0); + if (ret) { + dev_err(&pdev->dev, "failed to write IPROC_REGCTL2 %d\n", ret); + return ret; + } + + ret = devm_request_threaded_irq(&pdev->dev, adc_priv->irqno, + iproc_adc_interrupt_thread, + iproc_adc_interrupt_handler, + IRQF_SHARED, "iproc-adc", indio_dev); + if (ret) { + dev_err(&pdev->dev, "request_irq error %d\n", ret); + return ret; + } + + ret = clk_prepare_enable(adc_priv->adc_clk); + if (ret) { + dev_err(&pdev->dev, + "clk_prepare_enable failed %d\n", ret); + return ret; + } + + ret = iproc_adc_enable(indio_dev); + if (ret) { + dev_err(&pdev->dev, "failed to enable adc %d\n", ret); + goto err_adc_enable; + } + + 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; + indio_dev->num_channels = ARRAY_SIZE(iproc_adc_iio_channels); + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&pdev->dev, "iio_device_register failed:err %d\n", ret); + goto err_clk; + } + + return 0; + +err_clk: + iproc_adc_disable(indio_dev); +err_adc_enable: + clk_disable_unprepare(adc_priv->adc_clk); + + return ret; +} + +static int iproc_adc_remove(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct iproc_adc_priv *adc_priv = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + iproc_adc_disable(indio_dev); + clk_disable_unprepare(adc_priv->adc_clk); + + return 0; +} + +static const struct of_device_id iproc_adc_of_match[] = { + {.compatible = "brcm,iproc-static-adc", }, + { }, +}; +MODULE_DEVICE_TABLE(of, iproc_adc_of_match); + +static struct platform_driver iproc_adc_driver = { + .probe = iproc_adc_probe, + .remove = iproc_adc_remove, + .driver = { + .name = "iproc-static-adc", + .of_match_table = of_match_ptr(iproc_adc_of_match), + }, +}; +module_platform_driver(iproc_adc_driver); + +MODULE_DESCRIPTION("Broadcom iProc ADC controller driver"); +MODULE_AUTHOR("Raveendra Padasalagi <raveendra.padasalagi@broadcom.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/cc10001_adc.c b/drivers/iio/adc/cc10001_adc.c index 8254f529b2a9..91636c0ba5b5 100644 --- a/drivers/iio/adc/cc10001_adc.c +++ b/drivers/iio/adc/cc10001_adc.c @@ -186,7 +186,7 @@ done: if (!sample_invalid) iio_push_to_buffers_with_timestamp(indio_dev, data, - iio_get_time_ns()); + iio_get_time_ns(indio_dev)); iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; diff --git a/drivers/iio/adc/hi8435.c b/drivers/iio/adc/hi8435.c index c73c6c62a6ac..678e8c7ea763 100644 --- a/drivers/iio/adc/hi8435.c +++ b/drivers/iio/adc/hi8435.c @@ -400,7 +400,7 @@ static void hi8435_iio_push_event(struct iio_dev *idev, unsigned int val) iio_push_event(idev, IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i, IIO_EV_TYPE_THRESH, dir), - iio_get_time_ns()); + iio_get_time_ns(idev)); } } @@ -455,6 +455,7 @@ static int hi8435_probe(struct spi_device *spi) 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; diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index 65909d5858b1..955f3fdaf519 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -185,9 +185,9 @@ static int ina2xx_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: switch (chan->address) { case INA2XX_SHUNT_VOLTAGE: - /* processed (mV) = raw*1000/shunt_div */ + /* processed (mV) = raw/shunt_div */ *val2 = chip->config->shunt_div; - *val = 1000; + *val = 1; return IIO_VAL_FRACTIONAL; case INA2XX_BUS_VOLTAGE: @@ -350,6 +350,23 @@ static ssize_t ina2xx_allow_async_readout_store(struct device *dev, return len; } +/* + * Set current LSB to 1mA, shunt is in uOhms + * (equation 13 in datasheet). We hardcode a Current_LSB + * of 1.0 x10-6. The only remaining parameter is RShunt. + * There is no need to expose the CALIBRATION register + * to the user for now. But we need to reset this register + * if the user updates RShunt after driver init, e.g upon + * reading an EEPROM/Probe-type value. + */ +static int ina2xx_set_calibration(struct ina2xx_chip_info *chip) +{ + u16 regval = DIV_ROUND_CLOSEST(chip->config->calibration_factor, + chip->shunt_resistor); + + return regmap_write(chip->regmap, INA2XX_CALIBRATION, regval); +} + static int set_shunt_resistor(struct ina2xx_chip_info *chip, unsigned int val) { if (val <= 0 || val > chip->config->calibration_factor) @@ -385,6 +402,11 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev, if (ret) return ret; + /* Update the Calibration register */ + ret = ina2xx_set_calibration(chip); + if (ret) + return ret; + return len; } @@ -443,7 +465,7 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev) s64 time_a, time_b; unsigned int alert; - time_a = iio_get_time_ns(); + time_a = iio_get_time_ns(indio_dev); /* * Because the timer thread and the chip conversion clock @@ -482,7 +504,7 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev) data[i++] = val; } - time_b = iio_get_time_ns(); + time_b = iio_get_time_ns(indio_dev); iio_push_to_buffers_with_timestamp(indio_dev, (unsigned int *)data, time_a); @@ -532,7 +554,7 @@ static int ina2xx_buffer_enable(struct iio_dev *indio_dev) dev_dbg(&indio_dev->dev, "Async readout mode: %d\n", chip->allow_async_readout); - chip->prev_ns = iio_get_time_ns(); + chip->prev_ns = iio_get_time_ns(indio_dev); chip->task = kthread_run(ina2xx_capture_thread, (void *)indio_dev, "%s:%d-%uus", indio_dev->name, indio_dev->id, @@ -602,24 +624,11 @@ static const struct iio_info ina2xx_info = { /* Initialize the configuration and calibration registers. */ static int ina2xx_init(struct ina2xx_chip_info *chip, unsigned int config) { - u16 regval; - int ret; - - ret = regmap_write(chip->regmap, INA2XX_CONFIG, config); + int ret = regmap_write(chip->regmap, INA2XX_CONFIG, config); if (ret) return ret; - /* - * Set current LSB to 1mA, shunt is in uOhms - * (equation 13 in datasheet). We hardcode a Current_LSB - * of 1.0 x10-6. The only remaining parameter is RShunt. - * There is no need to expose the CALIBRATION register - * to the user for now. - */ - regval = DIV_ROUND_CLOSEST(chip->config->calibration_factor, - chip->shunt_resistor); - - return regmap_write(chip->regmap, INA2XX_CALIBRATION, regval); + return ina2xx_set_calibration(chip); } static int ina2xx_probe(struct i2c_client *client, @@ -682,6 +691,7 @@ 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; indio_dev->channels = ina2xx_channels; indio_dev->num_channels = ARRAY_SIZE(ina2xx_channels); indio_dev->name = id->name; diff --git a/drivers/iio/adc/lpc18xx_adc.c b/drivers/iio/adc/lpc18xx_adc.c new file mode 100644 index 000000000000..3ef18f4b27f0 --- /dev/null +++ b/drivers/iio/adc/lpc18xx_adc.c @@ -0,0 +1,231 @@ +/* + * IIO ADC driver for NXP LPC18xx ADC + * + * Copyright (C) 2016 Joachim Eastwood <manabian@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * UNSUPPORTED hardware features: + * - Hardware triggers + * - Burst mode + * - Interrupts + * - DMA + */ + +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/iio/iio.h> +#include <linux/iio/driver.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/regulator/consumer.h> + +/* LPC18XX ADC registers and bits */ +#define LPC18XX_ADC_CR 0x000 +#define LPC18XX_ADC_CR_CLKDIV_SHIFT 8 +#define LPC18XX_ADC_CR_PDN BIT(21) +#define LPC18XX_ADC_CR_START_NOW (0x1 << 24) +#define LPC18XX_ADC_GDR 0x004 + +/* Data register bits */ +#define LPC18XX_ADC_SAMPLE_SHIFT 6 +#define LPC18XX_ADC_SAMPLE_MASK 0x3ff +#define LPC18XX_ADC_CONV_DONE BIT(31) + +/* Clock should be 4.5 MHz or less */ +#define LPC18XX_ADC_CLK_TARGET 4500000 + +struct lpc18xx_adc { + struct regulator *vref; + void __iomem *base; + struct device *dev; + struct mutex lock; + struct clk *clk; + u32 cr_reg; +}; + +#define LPC18XX_ADC_CHAN(_idx) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = _idx, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ +} + +static const struct iio_chan_spec lpc18xx_adc_iio_channels[] = { + LPC18XX_ADC_CHAN(0), + LPC18XX_ADC_CHAN(1), + LPC18XX_ADC_CHAN(2), + LPC18XX_ADC_CHAN(3), + LPC18XX_ADC_CHAN(4), + LPC18XX_ADC_CHAN(5), + LPC18XX_ADC_CHAN(6), + LPC18XX_ADC_CHAN(7), +}; + +static int lpc18xx_adc_read_chan(struct lpc18xx_adc *adc, unsigned int ch) +{ + int ret; + u32 reg; + + reg = adc->cr_reg | BIT(ch) | LPC18XX_ADC_CR_START_NOW; + writel(reg, adc->base + LPC18XX_ADC_CR); + + ret = readl_poll_timeout(adc->base + LPC18XX_ADC_GDR, reg, + reg & LPC18XX_ADC_CONV_DONE, 3, 9); + if (ret) { + dev_warn(adc->dev, "adc read timed out\n"); + return ret; + } + + return (reg >> LPC18XX_ADC_SAMPLE_SHIFT) & LPC18XX_ADC_SAMPLE_MASK; +} + +static int lpc18xx_adc_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct lpc18xx_adc *adc = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&adc->lock); + *val = lpc18xx_adc_read_chan(adc, chan->channel); + mutex_unlock(&adc->lock); + if (*val < 0) + return *val; + + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + *val = regulator_get_voltage(adc->vref) / 1000; + *val2 = 10; + + return IIO_VAL_FRACTIONAL_LOG2; + } + + return -EINVAL; +} + +static const struct iio_info lpc18xx_adc_info = { + .read_raw = lpc18xx_adc_read_raw, + .driver_module = THIS_MODULE, +}; + +static int lpc18xx_adc_probe(struct platform_device *pdev) +{ + struct iio_dev *indio_dev; + struct lpc18xx_adc *adc; + struct resource *res; + unsigned int clkdiv; + unsigned long rate; + int ret; + + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc)); + if (!indio_dev) + return -ENOMEM; + + platform_set_drvdata(pdev, indio_dev); + adc = iio_priv(indio_dev); + adc->dev = &pdev->dev; + mutex_init(&adc->lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + adc->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(adc->base)) + return PTR_ERR(adc->base); + + adc->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(adc->clk)) { + dev_err(&pdev->dev, "error getting clock\n"); + return PTR_ERR(adc->clk); + } + + rate = clk_get_rate(adc->clk); + clkdiv = DIV_ROUND_UP(rate, LPC18XX_ADC_CLK_TARGET); + + adc->vref = devm_regulator_get(&pdev->dev, "vref"); + if (IS_ERR(adc->vref)) { + dev_err(&pdev->dev, "error getting regulator\n"); + return PTR_ERR(adc->vref); + } + + 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; + indio_dev->num_channels = ARRAY_SIZE(lpc18xx_adc_iio_channels); + + ret = regulator_enable(adc->vref); + if (ret) { + dev_err(&pdev->dev, "unable to enable regulator\n"); + return ret; + } + + ret = clk_prepare_enable(adc->clk); + if (ret) { + dev_err(&pdev->dev, "unable to enable clock\n"); + goto dis_reg; + } + + adc->cr_reg = (clkdiv << LPC18XX_ADC_CR_CLKDIV_SHIFT) | + LPC18XX_ADC_CR_PDN; + writel(adc->cr_reg, adc->base + LPC18XX_ADC_CR); + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&pdev->dev, "unable to register device\n"); + goto dis_clk; + } + + return 0; + +dis_clk: + writel(0, adc->base + LPC18XX_ADC_CR); + clk_disable_unprepare(adc->clk); +dis_reg: + regulator_disable(adc->vref); + return ret; +} + +static int lpc18xx_adc_remove(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct lpc18xx_adc *adc = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + writel(0, adc->base + LPC18XX_ADC_CR); + clk_disable_unprepare(adc->clk); + regulator_disable(adc->vref); + + return 0; +} + +static const struct of_device_id lpc18xx_adc_match[] = { + { .compatible = "nxp,lpc1850-adc" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, lpc18xx_adc_match); + +static struct platform_driver lpc18xx_adc_driver = { + .probe = lpc18xx_adc_probe, + .remove = lpc18xx_adc_remove, + .driver = { + .name = "lpc18xx-adc", + .of_match_table = lpc18xx_adc_match, + }, +}; +module_platform_driver(lpc18xx_adc_driver); + +MODULE_DESCRIPTION("LPC18xx ADC driver"); +MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c index 41d495c6035e..712fbd2b1f16 100644 --- a/drivers/iio/adc/max1027.c +++ b/drivers/iio/adc/max1027.c @@ -426,6 +426,7 @@ static int max1027_probe(struct spi_device *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->info = &max1027_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = st->info->channels; diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c index 998dc3caad4c..841a13c9b6ea 100644 --- a/drivers/iio/adc/max1363.c +++ b/drivers/iio/adc/max1363.c @@ -25,6 +25,8 @@ #include <linux/slab.h> #include <linux/err.h> #include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> @@ -788,7 +790,7 @@ static irqreturn_t max1363_event_handler(int irq, void *private) { struct iio_dev *indio_dev = private; struct max1363_state *st = iio_priv(indio_dev); - s64 timestamp = iio_get_time_ns(); + s64 timestamp = iio_get_time_ns(indio_dev); unsigned long mask, loc; u8 rx; u8 tx[2] = { st->setupbyte, @@ -1506,7 +1508,8 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p) if (b_sent < 0) goto done_free; - iio_push_to_buffers_with_timestamp(indio_dev, rxbuf, iio_get_time_ns()); + iio_push_to_buffers_with_timestamp(indio_dev, rxbuf, + iio_get_time_ns(indio_dev)); done_free: kfree(rxbuf); @@ -1516,6 +1519,56 @@ done: return IRQ_HANDLED; } +#ifdef CONFIG_OF + +#define MAX1363_COMPATIBLE(of_compatible, cfg) { \ + .compatible = of_compatible, \ + .data = &max1363_chip_info_tbl[cfg], \ +} + +static const struct of_device_id max1363_of_match[] = { + MAX1363_COMPATIBLE("maxim,max1361", max1361), + MAX1363_COMPATIBLE("maxim,max1362", max1362), + MAX1363_COMPATIBLE("maxim,max1363", max1363), + MAX1363_COMPATIBLE("maxim,max1364", max1364), + MAX1363_COMPATIBLE("maxim,max1036", max1036), + MAX1363_COMPATIBLE("maxim,max1037", max1037), + MAX1363_COMPATIBLE("maxim,max1038", max1038), + MAX1363_COMPATIBLE("maxim,max1039", max1039), + MAX1363_COMPATIBLE("maxim,max1136", max1136), + MAX1363_COMPATIBLE("maxim,max1137", max1137), + MAX1363_COMPATIBLE("maxim,max1138", max1138), + MAX1363_COMPATIBLE("maxim,max1139", max1139), + MAX1363_COMPATIBLE("maxim,max1236", max1236), + MAX1363_COMPATIBLE("maxim,max1237", max1237), + MAX1363_COMPATIBLE("maxim,max1238", max1238), + MAX1363_COMPATIBLE("maxim,max1239", max1239), + MAX1363_COMPATIBLE("maxim,max11600", max11600), + MAX1363_COMPATIBLE("maxim,max11601", max11601), + MAX1363_COMPATIBLE("maxim,max11602", max11602), + MAX1363_COMPATIBLE("maxim,max11603", max11603), + MAX1363_COMPATIBLE("maxim,max11604", max11604), + MAX1363_COMPATIBLE("maxim,max11605", max11605), + MAX1363_COMPATIBLE("maxim,max11606", max11606), + MAX1363_COMPATIBLE("maxim,max11607", max11607), + MAX1363_COMPATIBLE("maxim,max11608", max11608), + MAX1363_COMPATIBLE("maxim,max11609", max11609), + MAX1363_COMPATIBLE("maxim,max11610", max11610), + MAX1363_COMPATIBLE("maxim,max11611", max11611), + MAX1363_COMPATIBLE("maxim,max11612", max11612), + MAX1363_COMPATIBLE("maxim,max11613", max11613), + MAX1363_COMPATIBLE("maxim,max11614", max11614), + MAX1363_COMPATIBLE("maxim,max11615", max11615), + MAX1363_COMPATIBLE("maxim,max11616", max11616), + MAX1363_COMPATIBLE("maxim,max11617", max11617), + MAX1363_COMPATIBLE("maxim,max11644", max11644), + MAX1363_COMPATIBLE("maxim,max11645", max11645), + MAX1363_COMPATIBLE("maxim,max11646", max11646), + MAX1363_COMPATIBLE("maxim,max11647", max11647), + { /* sentinel */ } +}; +#endif + static int max1363_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1523,6 +1576,7 @@ static int max1363_probe(struct i2c_client *client, struct max1363_state *st; struct iio_dev *indio_dev; struct regulator *vref; + const struct of_device_id *match; indio_dev = devm_iio_device_alloc(&client->dev, sizeof(struct max1363_state)); @@ -1549,7 +1603,12 @@ 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 = &max1363_chip_info_tbl[id->driver_data]; + match = of_match_device(of_match_ptr(max1363_of_match), + &client->dev); + if (match) + st->chip_info = of_device_get_match_data(&client->dev); + else + st->chip_info = &max1363_chip_info_tbl[id->driver_data]; st->client = client; st->vref_uv = st->chip_info->int_vref_mv * 1000; @@ -1587,6 +1646,7 @@ static int max1363_probe(struct i2c_client *client, /* 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; @@ -1692,6 +1752,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), }, .probe = max1363_probe, .remove = max1363_remove, diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c index a850ca7d1eda..634717ae12f3 100644 --- a/drivers/iio/adc/mcp320x.c +++ b/drivers/iio/adc/mcp320x.c @@ -308,6 +308,7 @@ static int mcp320x_probe(struct spi_device *spi) 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; diff --git a/drivers/iio/adc/mcp3422.c b/drivers/iio/adc/mcp3422.c index d7b36efd2f3c..254135e07792 100644 --- a/drivers/iio/adc/mcp3422.c +++ b/drivers/iio/adc/mcp3422.c @@ -61,9 +61,9 @@ static const int mcp3422_scales[4][4] = { { 1000000, 500000, 250000, 125000 }, - { 250000 , 125000, 62500 , 31250 }, - { 62500 , 31250 , 15625 , 7812 }, - { 15625 , 7812 , 3906 , 1953 } }; + { 250000, 125000, 62500, 31250 }, + { 62500, 31250, 15625, 7812 }, + { 15625, 7812, 3906, 1953 } }; /* Constant msleep times for data acquisitions */ static const int mcp3422_read_times[4] = { @@ -352,6 +352,7 @@ 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; diff --git a/drivers/iio/adc/mxs-lradc.c b/drivers/iio/adc/mxs-lradc.c index 33051b87aac2..b84d37c80a94 100644 --- a/drivers/iio/adc/mxs-lradc.c +++ b/drivers/iio/adc/mxs-lradc.c @@ -373,13 +373,6 @@ static u32 mxs_lradc_plate_mask(struct mxs_lradc *lradc) return LRADC_CTRL0_MX28_PLATE_MASK; } -static u32 mxs_lradc_irq_en_mask(struct mxs_lradc *lradc) -{ - if (lradc->soc == IMX23_LRADC) - return LRADC_CTRL1_MX23_LRADC_IRQ_EN_MASK; - return LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK; -} - static u32 mxs_lradc_irq_mask(struct mxs_lradc *lradc) { if (lradc->soc == IMX23_LRADC) @@ -686,6 +679,17 @@ static void mxs_lradc_prepare_pressure(struct mxs_lradc *lradc) static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc) { + /* Configure the touchscreen type */ + if (lradc->soc == IMX28_LRADC) { + mxs_lradc_reg_clear(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, + LRADC_CTRL0); + + if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE) + mxs_lradc_reg_set(lradc, + LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, + LRADC_CTRL0); + } + mxs_lradc_setup_touch_detection(lradc); lradc->cur_plate = LRADC_TOUCH; @@ -1109,24 +1113,23 @@ static int mxs_lradc_ts_register(struct mxs_lradc *lradc) { struct input_dev *input; struct device *dev = lradc->dev; - int ret; if (!lradc->use_touchscreen) return 0; - input = input_allocate_device(); + input = devm_input_allocate_device(dev); if (!input) return -ENOMEM; input->name = DRIVER_NAME; input->id.bustype = BUS_HOST; - input->dev.parent = dev; input->open = mxs_lradc_ts_open; input->close = mxs_lradc_ts_close; __set_bit(EV_ABS, input->evbit); __set_bit(EV_KEY, input->evbit); __set_bit(BTN_TOUCH, input->keybit); + __set_bit(INPUT_PROP_DIRECT, input->propbit); input_set_abs_params(input, ABS_X, 0, LRADC_SINGLE_SAMPLE_MASK, 0, 0); input_set_abs_params(input, ABS_Y, 0, LRADC_SINGLE_SAMPLE_MASK, 0, 0); input_set_abs_params(input, ABS_PRESSURE, 0, LRADC_SINGLE_SAMPLE_MASK, @@ -1134,20 +1137,8 @@ static int mxs_lradc_ts_register(struct mxs_lradc *lradc) lradc->ts_input = input; input_set_drvdata(input, lradc); - ret = input_register_device(input); - if (ret) - input_free_device(lradc->ts_input); - - return ret; -} - -static void mxs_lradc_ts_unregister(struct mxs_lradc *lradc) -{ - if (!lradc->use_touchscreen) - return; - mxs_lradc_disable_ts(lradc); - input_unregister_device(lradc->ts_input); + return input_register_device(input); } /* @@ -1475,18 +1466,13 @@ static const struct iio_chan_spec mx28_lradc_chan_spec[] = { MXS_ADC_CHAN(15, IIO_VOLTAGE, "VDD5V"), }; -static int mxs_lradc_hw_init(struct mxs_lradc *lradc) +static void mxs_lradc_hw_init(struct mxs_lradc *lradc) { /* The ADC always uses DELAY CHANNEL 0. */ const u32 adc_cfg = (1 << (LRADC_DELAY_TRIGGER_DELAYS_OFFSET + 0)) | (LRADC_DELAY_TIMER_PER << LRADC_DELAY_DELAY_OFFSET); - int ret = stmp_reset_block(lradc->base); - - if (ret) - return ret; - /* Configure DELAY CHANNEL 0 for generic ADC sampling. */ mxs_lradc_reg_wrt(lradc, adc_cfg, LRADC_DELAY(0)); @@ -1495,27 +1481,17 @@ static int mxs_lradc_hw_init(struct mxs_lradc *lradc) mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2)); mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3)); - /* Configure the touchscreen type */ - if (lradc->soc == IMX28_LRADC) { - mxs_lradc_reg_clear(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, - LRADC_CTRL0); - - if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE) - mxs_lradc_reg_set(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE, - LRADC_CTRL0); - } - /* Start internal temperature sensing. */ mxs_lradc_reg_wrt(lradc, 0, LRADC_CTRL2); - - return 0; } static void mxs_lradc_hw_stop(struct mxs_lradc *lradc) { int i; - mxs_lradc_reg_clear(lradc, mxs_lradc_irq_en_mask(lradc), LRADC_CTRL1); + mxs_lradc_reg_clear(lradc, + lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET, + LRADC_CTRL1); for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++) mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(i)); @@ -1708,11 +1684,13 @@ static int mxs_lradc_probe(struct platform_device *pdev) } } - /* Configure the hardware. */ - ret = mxs_lradc_hw_init(lradc); + ret = stmp_reset_block(lradc->base); if (ret) goto err_dev; + /* Configure the hardware. */ + mxs_lradc_hw_init(lradc); + /* Register the touchscreen input device. */ if (touch_ret == 0) { ret = mxs_lradc_ts_register(lradc); @@ -1724,13 +1702,11 @@ static int mxs_lradc_probe(struct platform_device *pdev) ret = iio_device_register(iio); if (ret) { dev_err(dev, "Failed to register IIO device\n"); - goto err_ts; + return ret; } return 0; -err_ts: - mxs_lradc_ts_unregister(lradc); err_ts_register: mxs_lradc_hw_stop(lradc); err_dev: @@ -1748,7 +1724,6 @@ static int mxs_lradc_remove(struct platform_device *pdev) struct mxs_lradc *lradc = iio_priv(iio); iio_device_unregister(iio); - mxs_lradc_ts_unregister(lradc); mxs_lradc_hw_stop(lradc); mxs_lradc_trigger_remove(iio); iio_triggered_buffer_cleanup(iio); diff --git a/drivers/iio/adc/nau7802.c b/drivers/iio/adc/nau7802.c index e525aa6475c4..db9b829ccf0d 100644 --- a/drivers/iio/adc/nau7802.c +++ b/drivers/iio/adc/nau7802.c @@ -79,10 +79,29 @@ static const struct iio_chan_spec nau7802_chan_array[] = { static const u16 nau7802_sample_freq_avail[] = {10, 20, 40, 80, 10, 10, 10, 320}; +static ssize_t nau7802_show_scales(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct nau7802_state *st = iio_priv(dev_to_iio_dev(dev)); + int i, len = 0; + + for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) + len += scnprintf(buf + len, PAGE_SIZE - len, "0.%09d ", + st->scale_avail[i]); + + buf[len-1] = '\n'; + + return len; +} + static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("10 40 80 320"); +static IIO_DEVICE_ATTR(in_voltage_scale_available, S_IRUGO, nau7802_show_scales, + NULL, 0); + static struct attribute *nau7802_attributes[] = { &iio_const_attr_sampling_frequency_available.dev_attr.attr, + &iio_dev_attr_in_voltage_scale_available.dev_attr.attr, NULL }; @@ -414,6 +433,7 @@ 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/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c index 9c311c1e1ac7..85d701291654 100644 --- a/drivers/iio/adc/rockchip_saradc.c +++ b/drivers/iio/adc/rockchip_saradc.c @@ -21,6 +21,8 @@ #include <linux/of_device.h> #include <linux/clk.h> #include <linux/completion.h> +#include <linux/delay.h> +#include <linux/reset.h> #include <linux/regulator/consumer.h> #include <linux/iio/iio.h> @@ -53,6 +55,7 @@ struct rockchip_saradc { struct clk *clk; struct completion completion; struct regulator *vref; + struct reset_control *reset; const struct rockchip_saradc_data *data; u16 last_val; }; @@ -159,6 +162,22 @@ static const struct rockchip_saradc_data rk3066_tsadc_data = { .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"), +}; + +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, +}; + static const struct of_device_id rockchip_saradc_match[] = { { .compatible = "rockchip,saradc", @@ -166,11 +185,24 @@ static const struct of_device_id rockchip_saradc_match[] = { }, { .compatible = "rockchip,rk3066-tsadc", .data = &rk3066_tsadc_data, + }, { + .compatible = "rockchip,rk3399-saradc", + .data = &rk3399_saradc_data, }, {}, }; MODULE_DEVICE_TABLE(of, rockchip_saradc_match); +/** + * Reset SARADC Controller. + */ +static void rockchip_saradc_reset_controller(struct reset_control *reset) +{ + reset_control_assert(reset); + usleep_range(10, 20); + reset_control_deassert(reset); +} + static int rockchip_saradc_probe(struct platform_device *pdev) { struct rockchip_saradc *info = NULL; @@ -199,6 +231,20 @@ static int rockchip_saradc_probe(struct platform_device *pdev) if (IS_ERR(info->regs)) return PTR_ERR(info->regs); + /* + * The reset should be an optional property, as it should work + * with old devicetrees as well + */ + info->reset = devm_reset_control_get(&pdev->dev, "saradc-apb"); + if (IS_ERR(info->reset)) { + ret = PTR_ERR(info->reset); + if (ret != -ENOENT) + return ret; + + dev_dbg(&pdev->dev, "no reset control found\n"); + info->reset = NULL; + } + init_completion(&info->completion); irq = platform_get_irq(pdev, 0); @@ -233,6 +279,9 @@ static int rockchip_saradc_probe(struct platform_device *pdev) return PTR_ERR(info->vref); } + if (info->reset) + rockchip_saradc_reset_controller(info->reset); + /* * Use a default value for the converter clock. * This may become user-configurable in the future. diff --git a/drivers/iio/adc/ti-adc081c.c b/drivers/iio/adc/ti-adc081c.c index ecbc12138d58..319172cf7da8 100644 --- a/drivers/iio/adc/ti-adc081c.c +++ b/drivers/iio/adc/ti-adc081c.c @@ -1,22 +1,41 @@ /* + * TI ADC081C/ADC101C/ADC121C 8/10/12-bit ADC driver + * * Copyright (C) 2012 Avionic Design GmbH + * Copyright (C) 2016 Intel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * 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 + * + * 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 + * bits of value registers are reserved. */ #include <linux/err.h> #include <linux/i2c.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/acpi.h> #include <linux/iio/iio.h> +#include <linux/iio/buffer.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/triggered_buffer.h> #include <linux/regulator/consumer.h> struct adc081c { struct i2c_client *i2c; struct regulator *ref; + + /* 8, 10 or 12 */ + int bits; }; #define REG_CONV_RES 0x00 @@ -34,7 +53,7 @@ static int adc081c_read_raw(struct iio_dev *iio, if (err < 0) return err; - *value = (err >> 4) & 0xff; + *value = (err & 0xFFF) >> (12 - adc->bits); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: @@ -43,7 +62,7 @@ static int adc081c_read_raw(struct iio_dev *iio, return err; *value = err / 1000; - *shift = 8; + *shift = adc->bits; return IIO_VAL_FRACTIONAL_LOG2; @@ -54,10 +73,53 @@ static int adc081c_read_raw(struct iio_dev *iio, return -EINVAL; } -static const struct iio_chan_spec adc081c_channel = { - .type = IIO_VOLTAGE, - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +#define ADCxx1C_CHAN(_bits) { \ + .type = IIO_VOLTAGE, \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .scan_type = { \ + .sign = 'u', \ + .realbits = (_bits), \ + .storagebits = 16, \ + .shift = 12 - (_bits), \ + .endianness = IIO_CPU, \ + }, \ +} + +#define DEFINE_ADCxx1C_CHANNELS(_name, _bits) \ + static const struct iio_chan_spec _name ## _channels[] = { \ + ADCxx1C_CHAN((_bits)), \ + IIO_CHAN_SOFT_TIMESTAMP(1), \ + }; \ + +#define ADC081C_NUM_CHANNELS 2 + +struct adcxx1c_model { + const struct iio_chan_spec* channels; + int bits; +}; + +#define ADCxx1C_MODEL(_name, _bits) \ + { \ + .channels = _name ## _channels, \ + .bits = (_bits), \ + } + +DEFINE_ADCxx1C_CHANNELS(adc081c, 8); +DEFINE_ADCxx1C_CHANNELS(adc101c, 10); +DEFINE_ADCxx1C_CHANNELS(adc121c, 12); + +/* Model ids are indexes in _models array */ +enum adcxx1c_model_id { + ADC081C = 0, + ADC101C = 1, + ADC121C = 2, +}; + +static struct adcxx1c_model adcxx1c_models[] = { + ADCxx1C_MODEL(adc081c, 8), + ADCxx1C_MODEL(adc101c, 10), + ADCxx1C_MODEL(adc121c, 12), }; static const struct iio_info adc081c_info = { @@ -65,22 +127,55 @@ static const struct iio_info adc081c_info = { .driver_module = THIS_MODULE, }; +static irqreturn_t adc081c_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct adc081c *data = iio_priv(indio_dev); + u16 buf[8]; /* 2 bytes data + 6 bytes padding + 8 bytes timestamp */ + int ret; + + ret = i2c_smbus_read_word_swapped(data->i2c, REG_CONV_RES); + if (ret < 0) + goto out; + buf[0] = ret; + iio_push_to_buffers_with_timestamp(indio_dev, buf, + iio_get_time_ns(indio_dev)); +out: + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + static int adc081c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct iio_dev *iio; struct adc081c *adc; + struct adcxx1c_model *model; int err; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) return -EOPNOTSUPP; + if (ACPI_COMPANION(&client->dev)) { + const struct acpi_device_id *ad_id; + + ad_id = acpi_match_device(client->dev.driver->acpi_match_table, + &client->dev); + if (!ad_id) + return -ENODEV; + model = &adcxx1c_models[ad_id->driver_data]; + } else { + model = &adcxx1c_models[id->driver_data]; + } + iio = devm_iio_device_alloc(&client->dev, sizeof(*adc)); if (!iio) return -ENOMEM; adc = iio_priv(iio); adc->i2c = client; + adc->bits = model->bits; adc->ref = devm_regulator_get(&client->dev, "vref"); if (IS_ERR(adc->ref)) @@ -91,22 +186,31 @@ static int adc081c_probe(struct i2c_client *client, 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; - iio->channels = &adc081c_channel; - iio->num_channels = 1; + iio->channels = model->channels; + iio->num_channels = ADC081C_NUM_CHANNELS; + + err = iio_triggered_buffer_setup(iio, NULL, adc081c_trigger_handler, NULL); + if (err < 0) { + dev_err(&client->dev, "iio triggered buffer setup failed\n"); + goto err_regulator_disable; + } err = iio_device_register(iio); if (err < 0) - goto regulator_disable; + goto err_buffer_cleanup; i2c_set_clientdata(client, iio); return 0; -regulator_disable: +err_buffer_cleanup: + iio_triggered_buffer_cleanup(iio); +err_regulator_disable: regulator_disable(adc->ref); return err; @@ -118,13 +222,16 @@ static int adc081c_remove(struct i2c_client *client) struct adc081c *adc = iio_priv(iio); iio_device_unregister(iio); + iio_triggered_buffer_cleanup(iio); regulator_disable(adc->ref); return 0; } static const struct i2c_device_id adc081c_id[] = { - { "adc081c", 0 }, + { "adc081c", ADC081C }, + { "adc101c", ADC101C }, + { "adc121c", ADC121C }, { } }; MODULE_DEVICE_TABLE(i2c, adc081c_id); @@ -132,15 +239,28 @@ MODULE_DEVICE_TABLE(i2c, adc081c_id); #ifdef CONFIG_OF static const struct of_device_id adc081c_of_match[] = { { .compatible = "ti,adc081c" }, + { .compatible = "ti,adc101c" }, + { .compatible = "ti,adc121c" }, { } }; MODULE_DEVICE_TABLE(of, adc081c_of_match); #endif +#ifdef CONFIG_ACPI +static const struct acpi_device_id adc081c_acpi_match[] = { + { "ADC081C", ADC081C }, + { "ADC101C", ADC101C }, + { "ADC121C", ADC121C }, + { } +}; +MODULE_DEVICE_TABLE(acpi, adc081c_acpi_match); +#endif + static struct i2c_driver adc081c_driver = { .driver = { .name = "adc081c", .of_match_table = of_match_ptr(adc081c_of_match), + .acpi_match_table = ACPI_PTR(adc081c_acpi_match), }, .probe = adc081c_probe, .remove = adc081c_remove, @@ -149,5 +269,5 @@ static struct i2c_driver adc081c_driver = { module_i2c_driver(adc081c_driver); MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>"); -MODULE_DESCRIPTION("Texas Instruments ADC081C021/027 driver"); +MODULE_DESCRIPTION("Texas Instruments ADC081C/ADC101C/ADC121C driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/ti-adc0832.c b/drivers/iio/adc/ti-adc0832.c index 0afeac0c9bad..f4ba23effe9a 100644 --- a/drivers/iio/adc/ti-adc0832.c +++ b/drivers/iio/adc/ti-adc0832.c @@ -194,6 +194,7 @@ static int adc0832_probe(struct spi_device *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->info = &adc0832_info; indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/adc/ti-adc128s052.c b/drivers/iio/adc/ti-adc128s052.c index bc58867d6e8d..89dfbd31be5c 100644 --- a/drivers/iio/adc/ti-adc128s052.c +++ b/drivers/iio/adc/ti-adc128s052.c @@ -150,6 +150,7 @@ 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-ads1015.c b/drivers/iio/adc/ti-ads1015.c index 73cbf0b54e54..066abaf80201 100644 --- a/drivers/iio/adc/ti-ads1015.c +++ b/drivers/iio/adc/ti-ads1015.c @@ -55,6 +55,11 @@ #define ADS1015_DEFAULT_DATA_RATE 4 #define ADS1015_DEFAULT_CHAN 0 +enum { + ADS1015, + ADS1115, +}; + enum ads1015_channels { ADS1015_AIN0_AIN1 = 0, ADS1015_AIN0_AIN3, @@ -71,6 +76,10 @@ static const unsigned int ads1015_data_rate[] = { 128, 250, 490, 920, 1600, 2400, 3300, 3300 }; +static const unsigned int ads1115_data_rate[] = { + 8, 16, 32, 64, 128, 250, 475, 860 +}; + static const struct { int scale; int uscale; @@ -101,6 +110,7 @@ static const struct { .shift = 4, \ .endianness = IIO_CPU, \ }, \ + .datasheet_name = "AIN"#_chan, \ } #define ADS1015_V_DIFF_CHAN(_chan, _chan2, _addr) { \ @@ -121,6 +131,45 @@ static const struct { .shift = 4, \ .endianness = IIO_CPU, \ }, \ + .datasheet_name = "AIN"#_chan"-AIN"#_chan2, \ +} + +#define ADS1115_V_CHAN(_chan, _addr) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .address = _addr, \ + .channel = _chan, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = _addr, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_CPU, \ + }, \ + .datasheet_name = "AIN"#_chan, \ +} + +#define ADS1115_V_DIFF_CHAN(_chan, _chan2, _addr) { \ + .type = IIO_VOLTAGE, \ + .differential = 1, \ + .indexed = 1, \ + .address = _addr, \ + .channel = _chan, \ + .channel2 = _chan2, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = _addr, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_CPU, \ + }, \ + .datasheet_name = "AIN"#_chan"-AIN"#_chan2, \ } struct ads1015_data { @@ -131,6 +180,8 @@ struct ads1015_data { */ struct mutex lock; struct ads1015_channel_data channel_data[ADS1015_CHANNELS]; + + unsigned int *data_rate; }; static bool ads1015_is_writeable_reg(struct device *dev, unsigned int reg) @@ -157,6 +208,18 @@ static const struct iio_chan_spec ads1015_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(ADS1015_TIMESTAMP), }; +static const struct iio_chan_spec ads1115_channels[] = { + ADS1115_V_DIFF_CHAN(0, 1, ADS1015_AIN0_AIN1), + ADS1115_V_DIFF_CHAN(0, 3, ADS1015_AIN0_AIN3), + ADS1115_V_DIFF_CHAN(1, 3, ADS1015_AIN1_AIN3), + ADS1115_V_DIFF_CHAN(2, 3, ADS1015_AIN2_AIN3), + ADS1115_V_CHAN(0, ADS1015_AIN0), + ADS1115_V_CHAN(1, ADS1015_AIN1), + ADS1115_V_CHAN(2, ADS1015_AIN2), + ADS1115_V_CHAN(3, ADS1015_AIN3), + IIO_CHAN_SOFT_TIMESTAMP(ADS1015_TIMESTAMP), +}; + static int ads1015_set_power_state(struct ads1015_data *data, bool on) { int ret; @@ -196,7 +259,7 @@ int ads1015_get_adc_result(struct ads1015_data *data, int chan, int *val) return ret; if (change) { - conv_time = DIV_ROUND_UP(USEC_PER_SEC, ads1015_data_rate[dr]); + conv_time = DIV_ROUND_UP(USEC_PER_SEC, data->data_rate[dr]); usleep_range(conv_time, conv_time + 1); } @@ -225,7 +288,8 @@ static irqreturn_t ads1015_trigger_handler(int irq, void *p) buf[0] = res; mutex_unlock(&data->lock); - iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns()); + iio_push_to_buffers_with_timestamp(indio_dev, buf, + iio_get_time_ns(indio_dev)); err: iio_trigger_notify_done(indio_dev->trig); @@ -263,7 +327,7 @@ static int ads1015_set_data_rate(struct ads1015_data *data, int chan, int rate) int i, ret, rindex = -1; for (i = 0; i < ARRAY_SIZE(ads1015_data_rate); i++) - if (ads1015_data_rate[i] == rate) { + if (data->data_rate[i] == rate) { rindex = i; break; } @@ -291,7 +355,9 @@ static int ads1015_read_raw(struct iio_dev *indio_dev, mutex_lock(&indio_dev->mlock); mutex_lock(&data->lock); switch (mask) { - case IIO_CHAN_INFO_RAW: + case IIO_CHAN_INFO_RAW: { + int shift = chan->scan_type.shift; + if (iio_buffer_enabled(indio_dev)) { ret = -EBUSY; break; @@ -307,8 +373,7 @@ static int ads1015_read_raw(struct iio_dev *indio_dev, break; } - /* 12 bit res, D0 is bit 4 in conversion register */ - *val = sign_extend32(*val >> 4, 11); + *val = sign_extend32(*val >> shift, 15 - shift); ret = ads1015_set_power_state(data, false); if (ret < 0) @@ -316,6 +381,7 @@ static int ads1015_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT; break; + } case IIO_CHAN_INFO_SCALE: idx = data->channel_data[chan->address].pga; *val = ads1015_scale[idx].scale; @@ -324,7 +390,7 @@ static int ads1015_read_raw(struct iio_dev *indio_dev, break; case IIO_CHAN_INFO_SAMP_FREQ: idx = data->channel_data[chan->address].data_rate; - *val = ads1015_data_rate[idx]; + *val = data->data_rate[idx]; ret = IIO_VAL_INT; break; default: @@ -380,12 +446,15 @@ static const struct iio_buffer_setup_ops ads1015_buffer_setup_ops = { }; static IIO_CONST_ATTR(scale_available, "3 2 1 0.5 0.25 0.125"); -static IIO_CONST_ATTR(sampling_frequency_available, - "128 250 490 920 1600 2400 3300"); + +static IIO_CONST_ATTR_NAMED(ads1015_sampling_frequency_available, + sampling_frequency_available, "128 250 490 920 1600 2400 3300"); +static IIO_CONST_ATTR_NAMED(ads1115_sampling_frequency_available, + sampling_frequency_available, "8 16 32 64 128 250 475 860"); static struct attribute *ads1015_attributes[] = { &iio_const_attr_scale_available.dev_attr.attr, - &iio_const_attr_sampling_frequency_available.dev_attr.attr, + &iio_const_attr_ads1015_sampling_frequency_available.dev_attr.attr, NULL, }; @@ -393,17 +462,35 @@ static const struct attribute_group ads1015_attribute_group = { .attrs = ads1015_attributes, }; -static const struct iio_info ads1015_info = { +static struct attribute *ads1115_attributes[] = { + &iio_const_attr_scale_available.dev_attr.attr, + &iio_const_attr_ads1115_sampling_frequency_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ads1115_attribute_group = { + .attrs = ads1115_attributes, +}; + +static struct iio_info ads1015_info = { .driver_module = THIS_MODULE, .read_raw = ads1015_read_raw, .write_raw = ads1015_write_raw, - .attrs = &ads1015_attribute_group, + .attrs = &ads1015_attribute_group, +}; + +static struct iio_info ads1115_info = { + .driver_module = THIS_MODULE, + .read_raw = ads1015_read_raw, + .write_raw = ads1015_write_raw, + .attrs = &ads1115_attribute_group, }; #ifdef CONFIG_OF static int ads1015_get_channels_config_of(struct i2c_client *client) { - struct ads1015_data *data = i2c_get_clientdata(client); + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct ads1015_data *data = iio_priv(indio_dev); struct device_node *node; if (!client->dev.of_node || @@ -500,12 +587,25 @@ static int ads1015_probe(struct i2c_client *client, mutex_init(&data->lock); indio_dev->dev.parent = &client->dev; - indio_dev->info = &ads1015_info; + indio_dev->dev.of_node = client->dev.of_node; indio_dev->name = ADS1015_DRV_NAME; - indio_dev->channels = ads1015_channels; - indio_dev->num_channels = ARRAY_SIZE(ads1015_channels); indio_dev->modes = INDIO_DIRECT_MODE; + switch (id->driver_data) { + case ADS1015: + indio_dev->channels = ads1015_channels; + indio_dev->num_channels = ARRAY_SIZE(ads1015_channels); + indio_dev->info = &ads1015_info; + data->data_rate = (unsigned int *) &ads1015_data_rate; + break; + case ADS1115: + indio_dev->channels = ads1115_channels; + indio_dev->num_channels = ARRAY_SIZE(ads1115_channels); + indio_dev->info = &ads1115_info; + data->data_rate = (unsigned int *) &ads1115_data_rate; + break; + } + /* we need to keep this ABI the same as used by hwmon ADS1015 driver */ ads1015_get_channels_config(client); @@ -590,7 +690,8 @@ static const struct dev_pm_ops ads1015_pm_ops = { }; static const struct i2c_device_id ads1015_id[] = { - {"ads1015", 0}, + {"ads1015", ADS1015}, + {"ads1115", ADS1115}, {} }; MODULE_DEVICE_TABLE(i2c, ads1015_id); diff --git a/drivers/iio/adc/ti-ads8688.c b/drivers/iio/adc/ti-ads8688.c index 03e907028cb6..c400439900af 100644 --- a/drivers/iio/adc/ti-ads8688.c +++ b/drivers/iio/adc/ti-ads8688.c @@ -421,6 +421,7 @@ static int ads8688_probe(struct spi_device *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_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index c1e05532d437..c3cfacca2541 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -32,6 +32,7 @@ struct tiadc_device { struct ti_tscadc_dev *mfd_tscadc; + struct mutex fifo1_lock; /* to protect fifo access */ int channels; u8 channel_line[8]; u8 channel_step[8]; @@ -326,8 +327,7 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels) int i; indio_dev->num_channels = channels; - chan_array = kcalloc(channels, - sizeof(struct iio_chan_spec), GFP_KERNEL); + chan_array = kcalloc(channels, sizeof(*chan_array), GFP_KERNEL); if (chan_array == NULL) return -ENOMEM; @@ -360,6 +360,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { struct tiadc_device *adc_dev = iio_priv(indio_dev); + int ret = IIO_VAL_INT; int i, map_val; unsigned int fifo1count, read, stepid; bool found = false; @@ -373,13 +374,14 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, if (!step_en) return -EINVAL; + mutex_lock(&adc_dev->fifo1_lock); fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); while (fifo1count--) tiadc_readl(adc_dev, REG_FIFO1); am335x_tsc_se_set_once(adc_dev->mfd_tscadc, step_en); - timeout = jiffies + usecs_to_jiffies + timeout = jiffies + msecs_to_jiffies (IDLE_TIMEOUT * adc_dev->channels); /* Wait for Fifo threshold interrupt */ while (1) { @@ -389,7 +391,8 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, if (time_after(jiffies, timeout)) { am335x_tsc_se_adc_done(adc_dev->mfd_tscadc); - return -EAGAIN; + ret = -EAGAIN; + goto err_unlock; } } map_val = adc_dev->channel_step[chan->scan_index]; @@ -415,8 +418,11 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, am335x_tsc_se_adc_done(adc_dev->mfd_tscadc); if (found == false) - return -EBUSY; - return IIO_VAL_INT; + ret = -EBUSY; + +err_unlock: + mutex_unlock(&adc_dev->fifo1_lock); + return ret; } static const struct iio_info tiadc_info = { @@ -467,8 +473,7 @@ static int tiadc_probe(struct platform_device *pdev) return -EINVAL; } - indio_dev = devm_iio_device_alloc(&pdev->dev, - sizeof(struct tiadc_device)); + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*indio_dev)); if (indio_dev == NULL) { dev_err(&pdev->dev, "failed to allocate iio device\n"); return -ENOMEM; @@ -485,6 +490,7 @@ static int tiadc_probe(struct platform_device *pdev) tiadc_step_config(indio_dev); tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD); + mutex_init(&adc_dev->fifo1_lock); err = tiadc_channel_init(indio_dev, adc_dev->channels); if (err < 0) @@ -531,8 +537,7 @@ static int tiadc_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int tiadc_suspend(struct device *dev) +static int __maybe_unused tiadc_suspend(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct tiadc_device *adc_dev = iio_priv(indio_dev); @@ -550,7 +555,7 @@ static int tiadc_suspend(struct device *dev) return 0; } -static int tiadc_resume(struct device *dev) +static int __maybe_unused tiadc_resume(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct tiadc_device *adc_dev = iio_priv(indio_dev); @@ -567,14 +572,7 @@ static int tiadc_resume(struct device *dev) return 0; } -static const struct dev_pm_ops tiadc_pm_ops = { - .suspend = tiadc_suspend, - .resume = tiadc_resume, -}; -#define TIADC_PM_OPS (&tiadc_pm_ops) -#else -#define TIADC_PM_OPS NULL -#endif +static SIMPLE_DEV_PM_OPS(tiadc_pm_ops, tiadc_suspend, tiadc_resume); static const struct of_device_id ti_adc_dt_ids[] = { { .compatible = "ti,am3359-adc", }, @@ -585,7 +583,7 @@ MODULE_DEVICE_TABLE(of, ti_adc_dt_ids); static struct platform_driver tiadc_driver = { .driver = { .name = "TI-am335x-adc", - .pm = TIADC_PM_OPS, + .pm = &tiadc_pm_ops, .of_match_table = ti_adc_dt_ids, }, .probe = tiadc_probe, diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c index b10f629cc44b..228a003adeed 100644 --- a/drivers/iio/adc/vf610_adc.c +++ b/drivers/iio/adc/vf610_adc.c @@ -594,7 +594,8 @@ static irqreturn_t vf610_adc_isr(int irq, void *dev_id) if (iio_buffer_enabled(indio_dev)) { info->buffer[0] = info->value; iio_push_to_buffers_with_timestamp(indio_dev, - info->buffer, iio_get_time_ns()); + info->buffer, + iio_get_time_ns(indio_dev)); iio_trigger_notify_done(indio_dev->trig); } else complete(&info->completion); @@ -714,19 +715,19 @@ static int vf610_write_raw(struct iio_dev *indio_dev, int i; switch (mask) { - case IIO_CHAN_INFO_SAMP_FREQ: - for (i = 0; - i < ARRAY_SIZE(info->sample_freq_avail); - i++) - if (val == info->sample_freq_avail[i]) { - info->adc_feature.sample_rate = i; - vf610_adc_sample_set(info); - return 0; - } - break; + case IIO_CHAN_INFO_SAMP_FREQ: + for (i = 0; + i < ARRAY_SIZE(info->sample_freq_avail); + i++) + if (val == info->sample_freq_avail[i]) { + info->adc_feature.sample_rate = i; + vf610_adc_sample_set(info); + return 0; + } + break; - default: - break; + default: + break; } return -EINVAL; diff --git a/drivers/iio/adc/xilinx-xadc-events.c b/drivers/iio/adc/xilinx-xadc-events.c index edcf3aabd70d..6d5c2a6f4e6e 100644 --- a/drivers/iio/adc/xilinx-xadc-events.c +++ b/drivers/iio/adc/xilinx-xadc-events.c @@ -46,7 +46,7 @@ static void xadc_handle_event(struct iio_dev *indio_dev, unsigned int event) iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(chan->type, chan->channel, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), - iio_get_time_ns()); + iio_get_time_ns(indio_dev)); } else { /* * For other channels we don't know whether it is a upper or @@ -56,7 +56,7 @@ static void xadc_handle_event(struct iio_dev *indio_dev, unsigned int event) iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(chan->type, chan->channel, IIO_EV_TYPE_THRESH, IIO_EV_DIR_EITHER), - iio_get_time_ns()); + iio_get_time_ns(indio_dev)); } } |