diff options
Diffstat (limited to 'drivers/iio/adc')
40 files changed, 4581 insertions, 518 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 401f47b51d83..57625653fcb6 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -158,6 +158,7 @@ config AT91_SAMA5D2_ADC tristate "Atmel AT91 SAMA5D2 ADC" depends on ARCH_AT91 || COMPILE_TEST depends on HAS_IOMEM + select IIO_TRIGGERED_BUFFER help Say yes here to build support for Atmel SAMA5D2 ADC which is available on SAMA5D2 SoC family. @@ -239,6 +240,15 @@ config DA9150_GPADC To compile this driver as a module, choose M here: the module will be called berlin2-adc. +config DLN2_ADC + tristate "Diolan DLN-2 ADC driver support" + depends on MFD_DLN2 + help + Say yes here to build support for Diolan DLN-2 ADC. + + This driver can also be built as a module. If so, the module will be + called adc_dln2. + config ENVELOPE_DETECTOR tristate "Envelope detector using a DAC and a comparator" depends on OF @@ -249,6 +259,17 @@ config ENVELOPE_DETECTOR To compile this driver as a module, choose M here: the module will be called envelope-detector. +config EP93XX_ADC + tristate "Cirrus Logic EP93XX ADC driver" + depends on ARCH_EP93XX + help + Driver for the ADC module on the EP93XX series of SoC from Cirrus Logic. + It's recommended to switch on CONFIG_HIGH_RES_TIMERS option, in this + case driver will reduce its CPU usage by 90% in some use cases. + + To compile this driver as a module, choose M here: the module will be + called ep93xx_adc. + config EXYNOS_ADC tristate "Exynos ADC driver support" depends on ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || (OF && COMPILE_TEST) @@ -322,7 +343,7 @@ config INA2XX_ADC This driver is mutually exclusive with the HWMON version. config IMX7D_ADC - tristate "IMX7D ADC driver" + tristate "Freescale IMX7D ADC driver" depends on ARCH_MXC || COMPILE_TEST depends on HAS_IOMEM help @@ -362,6 +383,16 @@ config LPC32XX_ADC activate only one via device tree selection. Provides direct access via sysfs. +config LTC2471 + tristate "Linear Technology LTC2471 and LTC2473 ADC driver" + depends on I2C + help + Say yes here to build support for Linear Technology LTC2471 and + LTC2473 16-bit I2C ADC. + + This driver can also be built as a module. If so, the module will + be called ltc2471. + config LTC2485 tristate "Linear Technology LTC2485 ADC driver" depends on I2C @@ -679,6 +710,18 @@ config TI_ADC0832 This driver can also be built as a module. If so, the module will be called ti-adc0832. +config TI_ADC084S021 + tristate "Texas Instruments ADC084S021" + depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + If you say yes here you get support for Texas Instruments ADC084S021 + chips. + + This driver can also be built as a module. If so, the module will be + called ti-adc084s021. + config TI_ADC12138 tristate "Texas Instruments ADC12130/ADC12132/ADC12138" depends on SPI @@ -691,6 +734,18 @@ config TI_ADC12138 This driver can also be built as a module. If so, the module will be called ti-adc12138. +config TI_ADC108S102 + tristate "Texas Instruments ADC108S102 and ADC128S102 driver" + depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes here to build support for Texas Instruments ADC108S102 and + ADC128S102 ADC. + + To compile this driver as a module, choose M here: the module will + be called ti-adc108s102. + config TI_ADC128S052 tristate "Texas Instruments ADC128S052/ADC122S021/ADC124S021" depends on SPI diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 9339bec4babe..9874e05f52d7 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -24,7 +24,9 @@ obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o obj-$(CONFIG_CPCAP_ADC) += cpcap-adc.o obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o +obj-$(CONFIG_DLN2_ADC) += dln2-adc.o obj-$(CONFIG_ENVELOPE_DETECTOR) += envelope-detector.o +obj-$(CONFIG_EP93XX_ADC) += ep93xx_adc.o obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o obj-$(CONFIG_HI8435) += hi8435.o @@ -34,6 +36,7 @@ obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o +obj-$(CONFIG_LTC2471) += ltc2471.o obj-$(CONFIG_LTC2485) += ltc2485.o obj-$(CONFIG_LTC2497) += ltc2497.o obj-$(CONFIG_MAX1027) += max1027.o @@ -62,7 +65,9 @@ obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o obj-$(CONFIG_STM32_ADC) += stm32-adc.o obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o +obj-$(CONFIG_TI_ADC084S021) += ti-adc084s021.o obj-$(CONFIG_TI_ADC12138) += ti-adc12138.o +obj-$(CONFIG_TI_ADC108S102) += ti-adc108s102.o obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o obj-$(CONFIG_TI_ADC161S626) += ti-adc161s626.o obj-$(CONFIG_TI_ADS1015) += ti-ads1015.o diff --git a/drivers/iio/adc/ad7766.c b/drivers/iio/adc/ad7766.c index 75cca42b6e70..ce45037295d8 100644 --- a/drivers/iio/adc/ad7766.c +++ b/drivers/iio/adc/ad7766.c @@ -103,8 +103,7 @@ static int ad7766_preenable(struct iio_dev *indio_dev) return ret; } - if (ad7766->pd_gpio) - gpiod_set_value(ad7766->pd_gpio, 0); + gpiod_set_value(ad7766->pd_gpio, 0); return 0; } @@ -113,8 +112,7 @@ static int ad7766_postdisable(struct iio_dev *indio_dev) { struct ad7766 *ad7766 = iio_priv(indio_dev); - if (ad7766->pd_gpio) - gpiod_set_value(ad7766->pd_gpio, 1); + gpiod_set_value(ad7766->pd_gpio, 1); /* * The PD pin is synchronous to the clock, so give it some time to diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c index 1817ebf5ad84..34e353c43ac8 100644 --- a/drivers/iio/adc/ad7791.c +++ b/drivers/iio/adc/ad7791.c @@ -272,11 +272,9 @@ static ssize_t ad7791_write_frequency(struct device *dev, struct ad7791_state *st = iio_priv(indio_dev); int i, ret; - 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; + i = sysfs_match_string(ad7791_sample_freq_avail, buf); + if (i < 0) + return i; ret = iio_device_claim_direct_mode(indio_dev); if (ret) diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c index e6706a09e100..47c3d7f32900 100644 --- a/drivers/iio/adc/ad7793.c +++ b/drivers/iio/adc/ad7793.c @@ -257,7 +257,7 @@ static int ad7793_setup(struct iio_dev *indio_dev, unsigned int vref_mv) { struct ad7793_state *st = iio_priv(indio_dev); - int i, ret = -1; + int i, ret; unsigned long long scale_uv; u32 id; @@ -266,7 +266,7 @@ static int ad7793_setup(struct iio_dev *indio_dev, return ret; /* reset the serial interface */ - ret = spi_write(st->sd.spi, (u8 *)&ret, sizeof(ret)); + ret = ad_sd_reset(&st->sd, 32); if (ret < 0) goto out; usleep_range(500, 2000); /* Wait for at least 500us */ diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c index d10bd0c97233..22c4c17cd996 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -177,6 +177,34 @@ out: } EXPORT_SYMBOL_GPL(ad_sd_read_reg); +/** + * ad_sd_reset() - Reset the serial interface + * + * @sigma_delta: The sigma delta device + * @reset_length: Number of SCLKs with DIN = 1 + * + * Returns 0 on success, an error code otherwise. + **/ +int ad_sd_reset(struct ad_sigma_delta *sigma_delta, + unsigned int reset_length) +{ + uint8_t *buf; + unsigned int size; + int ret; + + size = DIV_ROUND_UP(reset_length, 8); + buf = kcalloc(size, sizeof(*buf), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + memset(buf, 0xff, size); + ret = spi_write(sigma_delta->spi, buf, size); + kfree(buf); + + return ret; +} +EXPORT_SYMBOL_GPL(ad_sd_reset); + static int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta, unsigned int mode, unsigned int channel) { diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c index 62670cbfa2bb..c02b23d675cb 100644 --- a/drivers/iio/adc/aspeed_adc.c +++ b/drivers/iio/adc/aspeed_adc.c @@ -22,6 +22,7 @@ #include <linux/iio/iio.h> #include <linux/iio/driver.h> +#include <linux/iopoll.h> #define ASPEED_RESOLUTION_BITS 10 #define ASPEED_CLOCKS_PER_SAMPLE 12 @@ -38,11 +39,17 @@ #define ASPEED_ENGINE_ENABLE BIT(0) +#define ASPEED_ADC_CTRL_INIT_RDY BIT(8) + +#define ASPEED_ADC_INIT_POLLING_TIME 500 +#define ASPEED_ADC_INIT_TIMEOUT 500000 + struct aspeed_adc_model_data { const char *model_name; unsigned int min_sampling_rate; // Hz unsigned int max_sampling_rate; // Hz unsigned int vref_voltage; // mV + bool wait_init_sequence; }; struct aspeed_adc_data { @@ -211,8 +218,29 @@ static int aspeed_adc_probe(struct platform_device *pdev) goto scaler_error; } + model_data = of_device_get_match_data(&pdev->dev); + + if (model_data->wait_init_sequence) { + /* Enable engine in normal mode. */ + writel(ASPEED_OPERATION_MODE_NORMAL | ASPEED_ENGINE_ENABLE, + data->base + ASPEED_REG_ENGINE_CONTROL); + + /* Wait for initial sequence complete. */ + ret = readl_poll_timeout(data->base + ASPEED_REG_ENGINE_CONTROL, + adc_engine_control_reg_val, + adc_engine_control_reg_val & + ASPEED_ADC_CTRL_INIT_RDY, + ASPEED_ADC_INIT_POLLING_TIME, + ASPEED_ADC_INIT_TIMEOUT); + if (ret) + goto scaler_error; + } + /* Start all channels in normal mode. */ - clk_prepare_enable(data->clk_scaler->clk); + ret = clk_prepare_enable(data->clk_scaler->clk); + if (ret) + goto clk_enable_error; + adc_engine_control_reg_val = GENMASK(31, 16) | ASPEED_OPERATION_MODE_NORMAL | ASPEED_ENGINE_ENABLE; writel(adc_engine_control_reg_val, @@ -236,6 +264,7 @@ iio_register_error: writel(ASPEED_OPERATION_MODE_POWER_DOWN, data->base + ASPEED_REG_ENGINE_CONTROL); clk_disable_unprepare(data->clk_scaler->clk); +clk_enable_error: clk_hw_unregister_divider(data->clk_scaler); scaler_error: @@ -270,6 +299,7 @@ static const struct aspeed_adc_model_data ast2500_model_data = { .vref_voltage = 1800, // mV .min_sampling_rate = 1, .max_sampling_rate = 1000000, + .wait_init_sequence = true, }; static const struct of_device_id aspeed_adc_matches[] = { diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index e10dca3ed74b..bc5b38e3a147 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -25,6 +25,11 @@ #include <linux/wait.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> +#include <linux/iio/buffer.h> +#include <linux/iio/trigger.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/triggered_buffer.h> +#include <linux/pinctrl/consumer.h> #include <linux/regulator/consumer.h> /* Control Register */ @@ -132,6 +137,17 @@ #define AT91_SAMA5D2_PRESSR 0xbc /* Trigger Register */ #define AT91_SAMA5D2_TRGR 0xc0 +/* Mask for TRGMOD field of TRGR register */ +#define AT91_SAMA5D2_TRGR_TRGMOD_MASK GENMASK(2, 0) +/* No trigger, only software trigger can start conversions */ +#define AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER 0 +/* Trigger Mode external trigger rising edge */ +#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE 1 +/* Trigger Mode external trigger falling edge */ +#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL 2 +/* Trigger Mode external trigger any edge */ +#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY 3 + /* Correction Select Register */ #define AT91_SAMA5D2_COSR 0xd0 /* Correction Value Register */ @@ -145,14 +161,29 @@ /* Version Register */ #define AT91_SAMA5D2_VERSION 0xfc +#define AT91_SAMA5D2_HW_TRIG_CNT 3 +#define AT91_SAMA5D2_SINGLE_CHAN_CNT 12 +#define AT91_SAMA5D2_DIFF_CHAN_CNT 6 + +/* + * Maximum number of bytes to hold conversion from all channels + * plus the timestamp + */ +#define AT91_BUFFER_MAX_BYTES ((AT91_SAMA5D2_SINGLE_CHAN_CNT + \ + AT91_SAMA5D2_DIFF_CHAN_CNT) * 2 + 8) + +#define AT91_BUFFER_MAX_HWORDS (AT91_BUFFER_MAX_BYTES / 2) + #define AT91_SAMA5D2_CHAN_SINGLE(num, addr) \ { \ .type = IIO_VOLTAGE, \ .channel = num, \ .address = addr, \ + .scan_index = num, \ .scan_type = { \ .sign = 'u', \ .realbits = 12, \ + .storagebits = 16, \ }, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ @@ -168,9 +199,11 @@ .channel = num, \ .channel2 = num2, \ .address = addr, \ + .scan_index = num + AT91_SAMA5D2_SINGLE_CHAN_CNT, \ .scan_type = { \ .sign = 's', \ .realbits = 12, \ + .storagebits = 16, \ }, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ @@ -188,6 +221,12 @@ struct at91_adc_soc_info { unsigned max_sample_rate; }; +struct at91_adc_trigger { + char *name; + unsigned int trgmod_value; + unsigned int edge_type; +}; + struct at91_adc_state { void __iomem *base; int irq; @@ -195,11 +234,14 @@ struct at91_adc_state { struct regulator *reg; struct regulator *vref; int vref_uv; + struct iio_trigger *trig; + const struct at91_adc_trigger *selected_trig; const struct iio_chan_spec *chan; bool conversion_done; u32 conversion_value; struct at91_adc_soc_info soc_info; wait_queue_head_t wq_data_available; + u16 buffer[AT91_BUFFER_MAX_HWORDS]; /* * lock to prevent concurrent 'single conversion' requests through * sysfs. @@ -207,6 +249,24 @@ struct at91_adc_state { struct mutex lock; }; +static const struct at91_adc_trigger at91_adc_trigger_list[] = { + { + .name = "external_rising", + .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE, + .edge_type = IRQ_TYPE_EDGE_RISING, + }, + { + .name = "external_falling", + .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL, + .edge_type = IRQ_TYPE_EDGE_FALLING, + }, + { + .name = "external_any", + .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY, + .edge_type = IRQ_TYPE_EDGE_BOTH, + }, +}; + static const struct iio_chan_spec at91_adc_channels[] = { AT91_SAMA5D2_CHAN_SINGLE(0, 0x50), AT91_SAMA5D2_CHAN_SINGLE(1, 0x54), @@ -226,12 +286,132 @@ static const struct iio_chan_spec at91_adc_channels[] = { AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68), AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70), AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78), + IIO_CHAN_SOFT_TIMESTAMP(AT91_SAMA5D2_SINGLE_CHAN_CNT + + AT91_SAMA5D2_DIFF_CHAN_CNT + 1), +}; + +static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state) +{ + struct iio_dev *indio = iio_trigger_get_drvdata(trig); + struct at91_adc_state *st = iio_priv(indio); + u32 status = at91_adc_readl(st, AT91_SAMA5D2_TRGR); + u8 bit; + + /* clear TRGMOD */ + status &= ~AT91_SAMA5D2_TRGR_TRGMOD_MASK; + + if (state) + status |= st->selected_trig->trgmod_value; + + /* set/unset hw trigger */ + at91_adc_writel(st, AT91_SAMA5D2_TRGR, status); + + for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) { + struct iio_chan_spec const *chan = indio->channels + bit; + + if (state) { + at91_adc_writel(st, AT91_SAMA5D2_CHER, + BIT(chan->channel)); + at91_adc_writel(st, AT91_SAMA5D2_IER, + BIT(chan->channel)); + } else { + at91_adc_writel(st, AT91_SAMA5D2_IDR, + BIT(chan->channel)); + at91_adc_writel(st, AT91_SAMA5D2_CHDR, + BIT(chan->channel)); + } + } + + return 0; +} + +static int at91_adc_reenable_trigger(struct iio_trigger *trig) +{ + struct iio_dev *indio = iio_trigger_get_drvdata(trig); + struct at91_adc_state *st = iio_priv(indio); + + enable_irq(st->irq); + + /* Needed to ACK the DRDY interruption */ + at91_adc_readl(st, AT91_SAMA5D2_LCDR); + return 0; +} + +static const struct iio_trigger_ops at91_adc_trigger_ops = { + .owner = THIS_MODULE, + .set_trigger_state = &at91_adc_configure_trigger, + .try_reenable = &at91_adc_reenable_trigger, }; +static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio, + char *trigger_name) +{ + struct iio_trigger *trig; + int ret; + + trig = devm_iio_trigger_alloc(&indio->dev, "%s-dev%d-%s", indio->name, + indio->id, trigger_name); + if (!trig) + return NULL; + + trig->dev.parent = indio->dev.parent; + iio_trigger_set_drvdata(trig, indio); + trig->ops = &at91_adc_trigger_ops; + + ret = devm_iio_trigger_register(&indio->dev, trig); + if (ret) + return ERR_PTR(ret); + + return trig; +} + +static int at91_adc_trigger_init(struct iio_dev *indio) +{ + struct at91_adc_state *st = iio_priv(indio); + + st->trig = at91_adc_allocate_trigger(indio, st->selected_trig->name); + if (IS_ERR(st->trig)) { + dev_err(&indio->dev, + "could not allocate trigger\n"); + return PTR_ERR(st->trig); + } + + return 0; +} + +static irqreturn_t at91_adc_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio = pf->indio_dev; + struct at91_adc_state *st = iio_priv(indio); + int i = 0; + u8 bit; + + for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) { + struct iio_chan_spec const *chan = indio->channels + bit; + + st->buffer[i] = at91_adc_readl(st, chan->address); + i++; + } + + iio_push_to_buffers_with_timestamp(indio, st->buffer, pf->timestamp); + + iio_trigger_notify_done(indio->trig); + + return IRQ_HANDLED; +} + +static int at91_adc_buffer_init(struct iio_dev *indio) +{ + return devm_iio_triggered_buffer_setup(&indio->dev, indio, + &iio_pollfunc_store_time, + &at91_adc_trigger_handler, NULL); +} + static unsigned at91_adc_startup_time(unsigned startup_time_min, unsigned adc_clk_khz) { - const unsigned startup_lookup[] = { + static const unsigned int startup_lookup[] = { 0, 8, 16, 24, 64, 80, 96, 112, 512, 576, 640, 704, @@ -293,14 +473,18 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private) u32 status = at91_adc_readl(st, AT91_SAMA5D2_ISR); u32 imr = at91_adc_readl(st, AT91_SAMA5D2_IMR); - if (status & imr) { + if (!(status & imr)) + return IRQ_NONE; + + if (iio_buffer_enabled(indio)) { + disable_irq_nosync(irq); + iio_trigger_poll(indio->trig); + } else { st->conversion_value = at91_adc_readl(st, st->chan->address); st->conversion_done = true; wake_up_interruptible(&st->wq_data_available); - return IRQ_HANDLED; } - - return IRQ_NONE; + return IRQ_HANDLED; } static int at91_adc_read_raw(struct iio_dev *indio_dev, @@ -313,6 +497,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: + /* we cannot use software trigger if hw trigger enabled */ + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + mutex_lock(&st->lock); st->chan = chan; @@ -344,6 +533,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev, at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel)); mutex_unlock(&st->lock); + + iio_device_release_direct_mode(indio_dev); return ret; case IIO_CHAN_INFO_SCALE: @@ -386,12 +577,27 @@ static const struct iio_info at91_adc_info = { .driver_module = THIS_MODULE, }; +static void at91_adc_hw_init(struct at91_adc_state *st) +{ + 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); +} + static int at91_adc_probe(struct platform_device *pdev) { struct iio_dev *indio_dev; struct at91_adc_state *st; struct resource *res; - int ret; + int ret, i; + u32 edge_type; indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st)); if (!indio_dev) @@ -432,6 +638,27 @@ static int at91_adc_probe(struct platform_device *pdev) return ret; } + ret = of_property_read_u32(pdev->dev.of_node, + "atmel,trigger-edge-type", &edge_type); + if (ret) { + dev_err(&pdev->dev, + "invalid or missing value for atmel,trigger-edge-type\n"); + return ret; + } + + st->selected_trig = NULL; + + for (i = 0; i < AT91_SAMA5D2_HW_TRIG_CNT; i++) + if (at91_adc_trigger_list[i].edge_type == edge_type) { + st->selected_trig = &at91_adc_trigger_list[i]; + break; + } + + if (!st->selected_trig) { + dev_err(&pdev->dev, "invalid external trigger edge value\n"); + return -EINVAL; + } + init_waitqueue_head(&st->wq_data_available); mutex_init(&st->lock); @@ -482,16 +709,7 @@ static int at91_adc_probe(struct platform_device *pdev) goto vref_disable; } - 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); + at91_adc_hw_init(st); ret = clk_prepare_enable(st->per_clk); if (ret) @@ -499,10 +717,25 @@ static int at91_adc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, indio_dev); + ret = at91_adc_buffer_init(indio_dev); + if (ret < 0) { + dev_err(&pdev->dev, "couldn't initialize the buffer.\n"); + goto per_clk_disable_unprepare; + } + + ret = at91_adc_trigger_init(indio_dev); + if (ret < 0) { + dev_err(&pdev->dev, "couldn't setup the triggers.\n"); + goto per_clk_disable_unprepare; + } + ret = iio_device_register(indio_dev); if (ret < 0) goto per_clk_disable_unprepare; + dev_info(&pdev->dev, "setting up trigger as %s\n", + st->selected_trig->name); + dev_info(&pdev->dev, "version: %x\n", readl_relaxed(st->base + AT91_SAMA5D2_VERSION)); @@ -532,6 +765,69 @@ static int at91_adc_remove(struct platform_device *pdev) return 0; } +static __maybe_unused int at91_adc_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = + platform_get_drvdata(to_platform_device(dev)); + struct at91_adc_state *st = iio_priv(indio_dev); + + /* + * Do a sofware reset of the ADC before we go to suspend. + * this will ensure that all pins are free from being muxed by the ADC + * and can be used by for other devices. + * Otherwise, ADC will hog them and we can't go to suspend mode. + */ + at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST); + + clk_disable_unprepare(st->per_clk); + regulator_disable(st->vref); + regulator_disable(st->reg); + + return pinctrl_pm_select_sleep_state(dev); +} + +static __maybe_unused int at91_adc_resume(struct device *dev) +{ + struct iio_dev *indio_dev = + platform_get_drvdata(to_platform_device(dev)); + struct at91_adc_state *st = iio_priv(indio_dev); + int ret; + + ret = pinctrl_pm_select_default_state(dev); + if (ret) + goto resume_failed; + + ret = regulator_enable(st->reg); + if (ret) + goto resume_failed; + + ret = regulator_enable(st->vref); + if (ret) + goto reg_disable_resume; + + ret = clk_prepare_enable(st->per_clk); + if (ret) + goto vref_disable_resume; + + at91_adc_hw_init(st); + + /* reconfiguring trigger hardware state */ + if (iio_buffer_enabled(indio_dev)) + at91_adc_configure_trigger(st->trig, true); + + return 0; + +vref_disable_resume: + regulator_disable(st->vref); +reg_disable_resume: + regulator_disable(st->reg); +resume_failed: + dev_err(&indio_dev->dev, "failed to resume\n"); + return ret; +} + +static SIMPLE_DEV_PM_OPS(at91_adc_pm_ops, at91_adc_suspend, at91_adc_resume); + static const struct of_device_id at91_adc_dt_match[] = { { .compatible = "atmel,sama5d2-adc", @@ -547,6 +843,7 @@ static struct platform_driver at91_adc_driver = { .driver = { .name = "at91-sama5d2_adc", .of_match_table = at91_adc_dt_match, + .pm = &at91_adc_pm_ops, }, }; module_platform_driver(at91_adc_driver) diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 34b928cefeed..15109728cae7 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -799,7 +799,7 @@ static u32 calc_startup_ticks_9x5(u32 startup_time, u32 adc_clk_khz) * For sama5d3x and at91sam9x5, the formula changes to: * Startup Time = <lookup_table_value> / ADC Clock */ - const int startup_lookup[] = { + static const int startup_lookup[] = { 0, 8, 16, 24, 64, 80, 96, 112, 512, 576, 640, 704, diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c index 64799ad7ebad..462a99c13e7a 100644 --- a/drivers/iio/adc/axp288_adc.c +++ b/drivers/iio/adc/axp288_adc.c @@ -28,6 +28,8 @@ #include <linux/iio/driver.h> #define AXP288_ADC_EN_MASK 0xF1 +#define AXP288_ADC_TS_PIN_GPADC 0xF2 +#define AXP288_ADC_TS_PIN_ON 0xF3 enum axp288_adc_id { AXP288_ADC_TS, @@ -121,6 +123,26 @@ static int axp288_adc_read_channel(int *val, unsigned long address, return IIO_VAL_INT; } +static int axp288_adc_set_ts(struct regmap *regmap, unsigned int mode, + unsigned long address) +{ + int ret; + + /* channels other than GPADC do not need to switch TS pin */ + if (address != AXP288_GP_ADC_H) + return 0; + + ret = regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, mode); + if (ret) + return ret; + + /* When switching to the GPADC pin give things some time to settle */ + if (mode == AXP288_ADC_TS_PIN_GPADC) + usleep_range(6000, 10000); + + return 0; +} + static int axp288_adc_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -131,7 +153,16 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev, mutex_lock(&indio_dev->mlock); switch (mask) { case IIO_CHAN_INFO_RAW: + if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_GPADC, + chan->address)) { + dev_err(&indio_dev->dev, "GPADC mode\n"); + ret = -EINVAL; + break; + } ret = axp288_adc_read_channel(val, chan->address, info->regmap); + if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_ON, + chan->address)) + dev_err(&indio_dev->dev, "TS pin restore\n"); break; default: ret = -EINVAL; @@ -141,6 +172,15 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev, return ret; } +static int axp288_adc_set_state(struct regmap *regmap) +{ + /* ADC should be always enabled for internal FG to function */ + if (regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON)) + return -EIO; + + return regmap_write(regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK); +} + static const struct iio_info axp288_adc_iio_info = { .read_raw = &axp288_adc_read_raw, .driver_module = THIS_MODULE, @@ -169,7 +209,7 @@ static int axp288_adc_probe(struct platform_device *pdev) * Set ADC to enabled state at all time, including system suspend. * otherwise internal fuel gauge functionality may be affected. */ - ret = regmap_write(info->regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK); + ret = axp288_adc_set_state(axp20x->regmap); if (ret) { dev_err(&pdev->dev, "unable to enable ADC device\n"); return ret; diff --git a/drivers/iio/adc/cpcap-adc.c b/drivers/iio/adc/cpcap-adc.c index 62d37f8725b8..6e419d5a7c14 100644 --- a/drivers/iio/adc/cpcap-adc.c +++ b/drivers/iio/adc/cpcap-adc.c @@ -52,6 +52,10 @@ #define CPCAP_BIT_RAND0 BIT(1) /* Set with CAL_MODE */ #define CPCAP_BIT_ADEN BIT(0) /* Currently unused */ +#define CPCAP_REG_ADCC1_DEFAULTS (CPCAP_BIT_ADEN_AUTO_CLR | \ + CPCAP_BIT_ADC_CLK_SEL0 | \ + CPCAP_BIT_RAND1) + /* Register CPCAP_REG_ADCC2 bits */ #define CPCAP_BIT_CAL_FACTOR_ENABLE BIT(15) /* Currently unused */ #define CPCAP_BIT_BATDETB_EN BIT(14) /* Currently unused */ @@ -62,7 +66,7 @@ #define CPCAP_BIT_ADC_PS_FACTOR0 BIT(9) #define CPCAP_BIT_AD4_SELECT BIT(8) /* Currently unused */ #define CPCAP_BIT_ADC_BUSY BIT(7) /* Currently unused */ -#define CPCAP_BIT_THERMBIAS_EN BIT(6) /* Currently unused */ +#define CPCAP_BIT_THERMBIAS_EN BIT(6) /* Bias for AD0_BATTDETB */ #define CPCAP_BIT_ADTRIG_DIS BIT(5) /* Disable interrupt */ #define CPCAP_BIT_LIADC BIT(4) /* Currently unused */ #define CPCAP_BIT_TS_REFEN BIT(3) /* Currently unused */ @@ -70,6 +74,12 @@ #define CPCAP_BIT_TS_M1 BIT(1) /* Currently unused */ #define CPCAP_BIT_TS_M0 BIT(0) /* Currently unused */ +#define CPCAP_REG_ADCC2_DEFAULTS (CPCAP_BIT_AD4_SELECT | \ + CPCAP_BIT_ADTRIG_DIS | \ + CPCAP_BIT_LIADC | \ + CPCAP_BIT_TS_M2 | \ + CPCAP_BIT_TS_M1) + #define CPCAP_MAX_TEMP_LVL 27 #define CPCAP_FOUR_POINT_TWO_ADC 801 #define ST_ADC_CAL_CHRGI_HIGH_THRESHOLD 530 @@ -78,7 +88,7 @@ #define ST_ADC_CAL_BATTI_LOW_THRESHOLD 494 #define ST_ADC_CALIBRATE_DIFF_THRESHOLD 3 -#define CPCAP_ADC_MAX_RETRIES 5 /* Calibration and quirk */ +#define CPCAP_ADC_MAX_RETRIES 5 /* Calibration */ /** * struct cpcap_adc_ato - timing settings for cpcap adc @@ -124,10 +134,10 @@ struct cpcap_adc { */ enum cpcap_adc_channel { /* Bank0 channels */ - CPCAP_ADC_AD0_BATTDETB, /* Battery detection */ + CPCAP_ADC_AD0, /* Battery temperature */ CPCAP_ADC_BATTP, /* Battery voltage */ CPCAP_ADC_VBUS, /* USB VBUS voltage */ - CPCAP_ADC_AD3, /* Battery temperature when charging */ + CPCAP_ADC_AD3, /* Die temperature when charging */ CPCAP_ADC_BPLUS_AD4, /* Another battery or system voltage */ CPCAP_ADC_CHG_ISENSE, /* Calibrated charge current */ CPCAP_ADC_BATTI, /* Calibrated system current */ @@ -217,7 +227,7 @@ struct cpcap_adc_request { /* Phasing table for channels. Note that channels 16 & 17 use BATTP and BATTI */ static const struct cpcap_adc_phasing_tbl bank_phasing[] = { /* Bank0 */ - [CPCAP_ADC_AD0_BATTDETB] = {0, 0x80, 0x80, 0, 1023}, + [CPCAP_ADC_AD0] = {0, 0x80, 0x80, 0, 1023}, [CPCAP_ADC_BATTP] = {0, 0x80, 0x80, 0, 1023}, [CPCAP_ADC_VBUS] = {0, 0x80, 0x80, 0, 1023}, [CPCAP_ADC_AD3] = {0, 0x80, 0x80, 0, 1023}, @@ -243,7 +253,7 @@ static const struct cpcap_adc_phasing_tbl bank_phasing[] = { */ static struct cpcap_adc_conversion_tbl bank_conversion[] = { /* Bank0 */ - [CPCAP_ADC_AD0_BATTDETB] = { + [CPCAP_ADC_AD0] = { IIO_CHAN_INFO_PROCESSED, 0, 0, 0, 1, 1, }, [CPCAP_ADC_BATTP] = { @@ -541,6 +551,15 @@ static void cpcap_adc_setup_bank(struct cpcap_adc *ddata, return; switch (req->channel) { + case CPCAP_ADC_AD0: + value2 |= CPCAP_BIT_THERMBIAS_EN; + error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, + CPCAP_BIT_THERMBIAS_EN, + value2); + if (error) + return; + usleep_range(800, 1000); + break; case CPCAP_ADC_AD8 ... CPCAP_ADC_TSY2_AD15: value1 |= CPCAP_BIT_AD_SEL1; break; @@ -583,7 +602,8 @@ static void cpcap_adc_setup_bank(struct cpcap_adc *ddata, error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, CPCAP_BIT_ATOX_PS_FACTOR | CPCAP_BIT_ADC_PS_FACTOR1 | - CPCAP_BIT_ADC_PS_FACTOR0, + CPCAP_BIT_ADC_PS_FACTOR0 | + CPCAP_BIT_THERMBIAS_EN, value2); if (error) return; @@ -614,27 +634,6 @@ static void cpcap_adc_setup_bank(struct cpcap_adc *ddata, } } -/* - * Occasionally the ADC does not seem to start and there will be no - * interrupt. Let's re-init interrupt to prevent the ADC from hanging - * for the next request. It is unclear why this happens, but the next - * request will usually work after doing this. - */ -static void cpcap_adc_quirk_reset_lost_irq(struct cpcap_adc *ddata) -{ - int error; - - dev_info(ddata->dev, "lost ADC irq, attempting to reinit\n"); - disable_irq(ddata->irq); - error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, - CPCAP_BIT_ADTRIG_DIS, - CPCAP_BIT_ADTRIG_DIS); - if (error) - dev_warn(ddata->dev, "%s reset failed: %i\n", - __func__, error); - enable_irq(ddata->irq); -} - static int cpcap_adc_start_bank(struct cpcap_adc *ddata, struct cpcap_adc_request *req) { @@ -652,7 +651,6 @@ static int cpcap_adc_start_bank(struct cpcap_adc *ddata, return 0; if (error == 0) { - cpcap_adc_quirk_reset_lost_irq(ddata); error = -ETIMEDOUT; continue; } @@ -664,6 +662,21 @@ static int cpcap_adc_start_bank(struct cpcap_adc *ddata, return error; } +static int cpcap_adc_stop_bank(struct cpcap_adc *ddata) +{ + int error; + + error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC1, + 0xffff, + CPCAP_REG_ADCC1_DEFAULTS); + if (error) + return error; + + return regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2, + 0xffff, + CPCAP_REG_ADCC2_DEFAULTS); +} + static void cpcap_adc_phase(struct cpcap_adc_request *req) { const struct cpcap_adc_conversion_tbl *conv_tbl = req->conv_tbl; @@ -758,7 +771,7 @@ static void cpcap_adc_convert(struct cpcap_adc_request *req) return; /* Temperatures use a lookup table instead of conversion table */ - if ((req->channel == CPCAP_ADC_AD0_BATTDETB) || + if ((req->channel == CPCAP_ADC_AD0) || (req->channel == CPCAP_ADC_AD3)) { req->result = cpcap_adc_table_to_millicelcius(req->result); @@ -820,7 +833,7 @@ static int cpcap_adc_init_request(struct cpcap_adc_request *req, req->conv_tbl = bank_conversion; switch (channel) { - case CPCAP_ADC_AD0_BATTDETB ... CPCAP_ADC_USB_ID: + case CPCAP_ADC_AD0 ... CPCAP_ADC_USB_ID: req->bank_index = channel; break; case CPCAP_ADC_AD8 ... CPCAP_ADC_TSY2_AD15: @@ -839,6 +852,22 @@ static int cpcap_adc_init_request(struct cpcap_adc_request *req, return 0; } +static int cpcap_adc_read_st_die_temp(struct cpcap_adc *ddata, + int addr, int *val) +{ + int error; + + error = regmap_read(ddata->reg, addr, val); + if (error) + return error; + + *val -= 282; + *val *= 114; + *val += 25000; + + return 0; +} + static int cpcap_adc_read(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -860,6 +889,9 @@ static int cpcap_adc_read(struct iio_dev *indio_dev, error = regmap_read(ddata->reg, chan->address, val); if (error) goto err_unlock; + error = cpcap_adc_stop_bank(ddata); + if (error) + goto err_unlock; mutex_unlock(&ddata->lock); break; case IIO_CHAN_INFO_PROCESSED: @@ -867,7 +899,19 @@ static int cpcap_adc_read(struct iio_dev *indio_dev, error = cpcap_adc_start_bank(ddata, &req); if (error) goto err_unlock; - error = cpcap_adc_read_bank_scaled(ddata, &req); + if ((ddata->vendor == CPCAP_VENDOR_ST) && + (chan->channel == CPCAP_ADC_AD3)) { + error = cpcap_adc_read_st_die_temp(ddata, + chan->address, + &req.result); + if (error) + goto err_unlock; + } else { + error = cpcap_adc_read_bank_scaled(ddata, &req); + if (error) + goto err_unlock; + } + error = cpcap_adc_stop_bank(ddata); if (error) goto err_unlock; mutex_unlock(&ddata->lock); diff --git a/drivers/iio/adc/dln2-adc.c b/drivers/iio/adc/dln2-adc.c new file mode 100644 index 000000000000..ab8d6aed5085 --- /dev/null +++ b/drivers/iio/adc/dln2-adc.c @@ -0,0 +1,722 @@ +/* + * Driver for the Diolan DLN-2 USB-ADC adapter + * + * Copyright (c) 2017 Jack Andersen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/types.h> +#include <linux/platform_device.h> +#include <linux/mfd/dln2.h> + +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/iio/trigger.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/triggered_buffer.h> +#include <linux/iio/buffer.h> +#include <linux/iio/kfifo_buf.h> + +#define DLN2_ADC_MOD_NAME "dln2-adc" + +#define DLN2_ADC_ID 0x06 + +#define DLN2_ADC_GET_CHANNEL_COUNT DLN2_CMD(0x01, DLN2_ADC_ID) +#define DLN2_ADC_ENABLE DLN2_CMD(0x02, DLN2_ADC_ID) +#define DLN2_ADC_DISABLE DLN2_CMD(0x03, DLN2_ADC_ID) +#define DLN2_ADC_CHANNEL_ENABLE DLN2_CMD(0x05, DLN2_ADC_ID) +#define DLN2_ADC_CHANNEL_DISABLE DLN2_CMD(0x06, DLN2_ADC_ID) +#define DLN2_ADC_SET_RESOLUTION DLN2_CMD(0x08, DLN2_ADC_ID) +#define DLN2_ADC_CHANNEL_GET_VAL DLN2_CMD(0x0A, DLN2_ADC_ID) +#define DLN2_ADC_CHANNEL_GET_ALL_VAL DLN2_CMD(0x0B, DLN2_ADC_ID) +#define DLN2_ADC_CHANNEL_SET_CFG DLN2_CMD(0x0C, DLN2_ADC_ID) +#define DLN2_ADC_CHANNEL_GET_CFG DLN2_CMD(0x0D, DLN2_ADC_ID) +#define DLN2_ADC_CONDITION_MET_EV DLN2_CMD(0x10, DLN2_ADC_ID) + +#define DLN2_ADC_EVENT_NONE 0 +#define DLN2_ADC_EVENT_BELOW 1 +#define DLN2_ADC_EVENT_LEVEL_ABOVE 2 +#define DLN2_ADC_EVENT_OUTSIDE 3 +#define DLN2_ADC_EVENT_INSIDE 4 +#define DLN2_ADC_EVENT_ALWAYS 5 + +#define DLN2_ADC_MAX_CHANNELS 8 +#define DLN2_ADC_DATA_BITS 10 + +/* + * Plays similar role to iio_demux_table in subsystem core; except allocated + * in a fixed 8-element array. + */ +struct dln2_adc_demux_table { + unsigned int from; + unsigned int to; + unsigned int length; +}; + +struct dln2_adc { + struct platform_device *pdev; + struct iio_chan_spec iio_channels[DLN2_ADC_MAX_CHANNELS + 1]; + int port, trigger_chan; + struct iio_trigger *trig; + struct mutex mutex; + /* Cached sample period in milliseconds */ + unsigned int sample_period; + /* Demux table */ + unsigned int demux_count; + struct dln2_adc_demux_table demux[DLN2_ADC_MAX_CHANNELS]; + /* Precomputed timestamp padding offset and length */ + unsigned int ts_pad_offset, ts_pad_length; +}; + +struct dln2_adc_port_chan { + u8 port; + u8 chan; +}; + +struct dln2_adc_get_all_vals { + __le16 channel_mask; + __le16 values[DLN2_ADC_MAX_CHANNELS]; +}; + +static void dln2_adc_add_demux(struct dln2_adc *dln2, + unsigned int in_loc, unsigned int out_loc, + unsigned int length) +{ + struct dln2_adc_demux_table *p = dln2->demux_count ? + &dln2->demux[dln2->demux_count - 1] : NULL; + + if (p && p->from + p->length == in_loc && + p->to + p->length == out_loc) { + p->length += length; + } else if (dln2->demux_count < DLN2_ADC_MAX_CHANNELS) { + p = &dln2->demux[dln2->demux_count++]; + p->from = in_loc; + p->to = out_loc; + p->length = length; + } +} + +static void dln2_adc_update_demux(struct dln2_adc *dln2) +{ + int in_ind = -1, out_ind; + unsigned int in_loc = 0, out_loc = 0; + struct iio_dev *indio_dev = platform_get_drvdata(dln2->pdev); + + /* Clear out any old demux */ + dln2->demux_count = 0; + + /* Optimize all 8-channels case */ + if (indio_dev->masklength && + (*indio_dev->active_scan_mask & 0xff) == 0xff) { + dln2_adc_add_demux(dln2, 0, 0, 16); + dln2->ts_pad_offset = 0; + dln2->ts_pad_length = 0; + return; + } + + /* Build demux table from fixed 8-channels to active_scan_mask */ + for_each_set_bit(out_ind, + indio_dev->active_scan_mask, + indio_dev->masklength) { + /* Handle timestamp separately */ + if (out_ind == DLN2_ADC_MAX_CHANNELS) + break; + for (++in_ind; in_ind != out_ind; ++in_ind) + in_loc += 2; + dln2_adc_add_demux(dln2, in_loc, out_loc, 2); + out_loc += 2; + in_loc += 2; + } + + if (indio_dev->scan_timestamp) { + size_t ts_offset = indio_dev->scan_bytes / sizeof(int64_t) - 1; + + dln2->ts_pad_offset = out_loc; + dln2->ts_pad_length = ts_offset * sizeof(int64_t) - out_loc; + } else { + dln2->ts_pad_offset = 0; + dln2->ts_pad_length = 0; + } +} + +static int dln2_adc_get_chan_count(struct dln2_adc *dln2) +{ + int ret; + u8 port = dln2->port; + u8 count; + int olen = sizeof(count); + + ret = dln2_transfer(dln2->pdev, DLN2_ADC_GET_CHANNEL_COUNT, + &port, sizeof(port), &count, &olen); + if (ret < 0) { + dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__); + return ret; + } + if (olen < sizeof(count)) + return -EPROTO; + + return count; +} + +static int dln2_adc_set_port_resolution(struct dln2_adc *dln2) +{ + int ret; + struct dln2_adc_port_chan port_chan = { + .port = dln2->port, + .chan = DLN2_ADC_DATA_BITS, + }; + + ret = dln2_transfer_tx(dln2->pdev, DLN2_ADC_SET_RESOLUTION, + &port_chan, sizeof(port_chan)); + if (ret < 0) + dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__); + + return ret; +} + +static int dln2_adc_set_chan_enabled(struct dln2_adc *dln2, + int channel, bool enable) +{ + int ret; + struct dln2_adc_port_chan port_chan = { + .port = dln2->port, + .chan = channel, + }; + u16 cmd = enable ? DLN2_ADC_CHANNEL_ENABLE : DLN2_ADC_CHANNEL_DISABLE; + + ret = dln2_transfer_tx(dln2->pdev, cmd, &port_chan, sizeof(port_chan)); + if (ret < 0) + dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__); + + return ret; +} + +static int dln2_adc_set_port_enabled(struct dln2_adc *dln2, bool enable, + u16 *conflict_out) +{ + int ret; + u8 port = dln2->port; + __le16 conflict; + int olen = sizeof(conflict); + u16 cmd = enable ? DLN2_ADC_ENABLE : DLN2_ADC_DISABLE; + + if (conflict_out) + *conflict_out = 0; + + ret = dln2_transfer(dln2->pdev, cmd, &port, sizeof(port), + &conflict, &olen); + if (ret < 0) { + dev_dbg(&dln2->pdev->dev, "Problem in %s(%d)\n", + __func__, (int)enable); + if (conflict_out && enable && olen >= sizeof(conflict)) + *conflict_out = le16_to_cpu(conflict); + return ret; + } + if (enable && olen < sizeof(conflict)) + return -EPROTO; + + return ret; +} + +static int dln2_adc_set_chan_period(struct dln2_adc *dln2, + unsigned int channel, unsigned int period) +{ + int ret; + struct { + struct dln2_adc_port_chan port_chan; + __u8 type; + __le16 period; + __le16 low; + __le16 high; + } __packed set_cfg = { + .port_chan.port = dln2->port, + .port_chan.chan = channel, + .type = period ? DLN2_ADC_EVENT_ALWAYS : DLN2_ADC_EVENT_NONE, + .period = cpu_to_le16(period) + }; + + ret = dln2_transfer_tx(dln2->pdev, DLN2_ADC_CHANNEL_SET_CFG, + &set_cfg, sizeof(set_cfg)); + if (ret < 0) + dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__); + + return ret; +} + +static int dln2_adc_read(struct dln2_adc *dln2, unsigned int channel) +{ + int ret, i; + struct iio_dev *indio_dev = platform_get_drvdata(dln2->pdev); + u16 conflict; + __le16 value; + int olen = sizeof(value); + struct dln2_adc_port_chan port_chan = { + .port = dln2->port, + .chan = channel, + }; + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret < 0) + return ret; + + ret = dln2_adc_set_chan_enabled(dln2, channel, true); + if (ret < 0) + goto release_direct; + + ret = dln2_adc_set_port_enabled(dln2, true, &conflict); + if (ret < 0) { + if (conflict) { + dev_err(&dln2->pdev->dev, + "ADC pins conflict with mask %04X\n", + (int)conflict); + ret = -EBUSY; + } + goto disable_chan; + } + + /* + * Call GET_VAL twice due to initial zero-return immediately after + * enabling channel. + */ + for (i = 0; i < 2; ++i) { + ret = dln2_transfer(dln2->pdev, DLN2_ADC_CHANNEL_GET_VAL, + &port_chan, sizeof(port_chan), + &value, &olen); + if (ret < 0) { + dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__); + goto disable_port; + } + if (olen < sizeof(value)) { + ret = -EPROTO; + goto disable_port; + } + } + + ret = le16_to_cpu(value); + +disable_port: + dln2_adc_set_port_enabled(dln2, false, NULL); +disable_chan: + dln2_adc_set_chan_enabled(dln2, channel, false); +release_direct: + iio_device_release_direct_mode(indio_dev); + + return ret; +} + +static int dln2_adc_read_all(struct dln2_adc *dln2, + struct dln2_adc_get_all_vals *get_all_vals) +{ + int ret; + __u8 port = dln2->port; + int olen = sizeof(*get_all_vals); + + ret = dln2_transfer(dln2->pdev, DLN2_ADC_CHANNEL_GET_ALL_VAL, + &port, sizeof(port), get_all_vals, &olen); + if (ret < 0) { + dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__); + return ret; + } + if (olen < sizeof(*get_all_vals)) + return -EPROTO; + + return ret; +} + +static int dln2_adc_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + int ret; + unsigned int microhertz; + struct dln2_adc *dln2 = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&dln2->mutex); + ret = dln2_adc_read(dln2, chan->channel); + mutex_unlock(&dln2->mutex); + + if (ret < 0) + return ret; + + *val = ret; + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + /* + * Voltage reference is fixed at 3.3v + * 3.3 / (1 << 10) * 1000000000 + */ + *val = 0; + *val2 = 3222656; + return IIO_VAL_INT_PLUS_NANO; + + case IIO_CHAN_INFO_SAMP_FREQ: + if (dln2->sample_period) { + microhertz = 1000000000 / dln2->sample_period; + *val = microhertz / 1000000; + *val2 = microhertz % 1000000; + } else { + *val = 0; + *val2 = 0; + } + + return IIO_VAL_INT_PLUS_MICRO; + + default: + return -EINVAL; + } +} + +static int dln2_adc_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + int ret; + unsigned int microhertz; + struct dln2_adc *dln2 = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + microhertz = 1000000 * val + val2; + + mutex_lock(&dln2->mutex); + + dln2->sample_period = + microhertz ? 1000000000 / microhertz : UINT_MAX; + if (dln2->sample_period > 65535) { + dln2->sample_period = 65535; + dev_warn(&dln2->pdev->dev, + "clamping period to 65535ms\n"); + } + + /* + * The first requested channel is arbitrated as a shared + * trigger source, so only one event is registered with the + * DLN. The event handler will then read all enabled channel + * values using DLN2_ADC_CHANNEL_GET_ALL_VAL to maintain + * synchronization between ADC readings. + */ + if (dln2->trigger_chan != -1) + ret = dln2_adc_set_chan_period(dln2, + dln2->trigger_chan, dln2->sample_period); + else + ret = 0; + + mutex_unlock(&dln2->mutex); + + return ret; + + default: + return -EINVAL; + } +} + +static int dln2_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct dln2_adc *dln2 = iio_priv(indio_dev); + int chan_count = indio_dev->num_channels - 1; + int ret, i, j; + + mutex_lock(&dln2->mutex); + + for (i = 0; i < chan_count; ++i) { + ret = dln2_adc_set_chan_enabled(dln2, i, + test_bit(i, scan_mask)); + if (ret < 0) { + for (j = 0; j < i; ++j) + dln2_adc_set_chan_enabled(dln2, j, false); + mutex_unlock(&dln2->mutex); + dev_err(&dln2->pdev->dev, + "Unable to enable ADC channel %d\n", i); + return -EBUSY; + } + } + + dln2_adc_update_demux(dln2); + + mutex_unlock(&dln2->mutex); + + return 0; +} + +#define DLN2_ADC_CHAN(lval, idx) { \ + lval.type = IIO_VOLTAGE; \ + lval.channel = idx; \ + lval.indexed = 1; \ + lval.info_mask_separate = BIT(IIO_CHAN_INFO_RAW); \ + lval.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ); \ + lval.scan_index = idx; \ + lval.scan_type.sign = 'u'; \ + lval.scan_type.realbits = DLN2_ADC_DATA_BITS; \ + lval.scan_type.storagebits = 16; \ + lval.scan_type.endianness = IIO_LE; \ +} + +/* Assignment version of IIO_CHAN_SOFT_TIMESTAMP */ +#define IIO_CHAN_SOFT_TIMESTAMP_ASSIGN(lval, _si) { \ + lval.type = IIO_TIMESTAMP; \ + lval.channel = -1; \ + lval.scan_index = _si; \ + lval.scan_type.sign = 's'; \ + lval.scan_type.realbits = 64; \ + lval.scan_type.storagebits = 64; \ +} + +static const struct iio_info dln2_adc_info = { + .read_raw = dln2_adc_read_raw, + .write_raw = dln2_adc_write_raw, + .update_scan_mode = dln2_update_scan_mode, + .driver_module = THIS_MODULE, +}; + +static irqreturn_t dln2_adc_trigger_h(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct { + __le16 values[DLN2_ADC_MAX_CHANNELS]; + int64_t timestamp_space; + } data; + struct dln2_adc_get_all_vals dev_data; + struct dln2_adc *dln2 = iio_priv(indio_dev); + const struct dln2_adc_demux_table *t; + int ret, i; + + mutex_lock(&dln2->mutex); + ret = dln2_adc_read_all(dln2, &dev_data); + mutex_unlock(&dln2->mutex); + if (ret < 0) + goto done; + + /* Demux operation */ + for (i = 0; i < dln2->demux_count; ++i) { + t = &dln2->demux[i]; + memcpy((void *)data.values + t->to, + (void *)dev_data.values + t->from, t->length); + } + + /* Zero padding space between values and timestamp */ + if (dln2->ts_pad_length) + memset((void *)data.values + dln2->ts_pad_offset, + 0, dln2->ts_pad_length); + + iio_push_to_buffers_with_timestamp(indio_dev, &data, + iio_get_time_ns(indio_dev)); + +done: + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + +static int dln2_adc_triggered_buffer_postenable(struct iio_dev *indio_dev) +{ + int ret; + struct dln2_adc *dln2 = iio_priv(indio_dev); + u16 conflict; + unsigned int trigger_chan; + + mutex_lock(&dln2->mutex); + + /* Enable ADC */ + ret = dln2_adc_set_port_enabled(dln2, true, &conflict); + if (ret < 0) { + mutex_unlock(&dln2->mutex); + dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__); + if (conflict) { + dev_err(&dln2->pdev->dev, + "ADC pins conflict with mask %04X\n", + (int)conflict); + ret = -EBUSY; + } + return ret; + } + + /* Assign trigger channel based on first enabled channel */ + trigger_chan = find_first_bit(indio_dev->active_scan_mask, + indio_dev->masklength); + if (trigger_chan < DLN2_ADC_MAX_CHANNELS) { + dln2->trigger_chan = trigger_chan; + ret = dln2_adc_set_chan_period(dln2, dln2->trigger_chan, + dln2->sample_period); + mutex_unlock(&dln2->mutex); + if (ret < 0) { + dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__); + return ret; + } + } else { + dln2->trigger_chan = -1; + mutex_unlock(&dln2->mutex); + } + + return iio_triggered_buffer_postenable(indio_dev); +} + +static int dln2_adc_triggered_buffer_predisable(struct iio_dev *indio_dev) +{ + int ret; + struct dln2_adc *dln2 = iio_priv(indio_dev); + + mutex_lock(&dln2->mutex); + + /* Disable trigger channel */ + if (dln2->trigger_chan != -1) { + dln2_adc_set_chan_period(dln2, dln2->trigger_chan, 0); + dln2->trigger_chan = -1; + } + + /* Disable ADC */ + ret = dln2_adc_set_port_enabled(dln2, false, NULL); + + mutex_unlock(&dln2->mutex); + if (ret < 0) { + dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__); + return ret; + } + + return iio_triggered_buffer_predisable(indio_dev); +} + +static const struct iio_buffer_setup_ops dln2_adc_buffer_setup_ops = { + .postenable = dln2_adc_triggered_buffer_postenable, + .predisable = dln2_adc_triggered_buffer_predisable, +}; + +static void dln2_adc_event(struct platform_device *pdev, u16 echo, + const void *data, int len) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct dln2_adc *dln2 = iio_priv(indio_dev); + + /* Called via URB completion handler */ + iio_trigger_poll(dln2->trig); +} + +static const struct iio_trigger_ops dln2_adc_trigger_ops = { + .owner = THIS_MODULE, +}; + +static int dln2_adc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct dln2_adc *dln2; + struct dln2_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct iio_dev *indio_dev; + int i, ret, chans; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*dln2)); + if (!indio_dev) { + dev_err(dev, "failed allocating iio device\n"); + return -ENOMEM; + } + + dln2 = iio_priv(indio_dev); + dln2->pdev = pdev; + dln2->port = pdata->port; + dln2->trigger_chan = -1; + mutex_init(&dln2->mutex); + + platform_set_drvdata(pdev, indio_dev); + + ret = dln2_adc_set_port_resolution(dln2); + if (ret < 0) { + dev_err(dev, "failed to set ADC resolution to 10 bits\n"); + return ret; + } + + chans = dln2_adc_get_chan_count(dln2); + if (chans < 0) { + dev_err(dev, "failed to get channel count: %d\n", chans); + return chans; + } + if (chans > DLN2_ADC_MAX_CHANNELS) { + chans = DLN2_ADC_MAX_CHANNELS; + dev_warn(dev, "clamping channels to %d\n", + DLN2_ADC_MAX_CHANNELS); + } + + for (i = 0; i < chans; ++i) + DLN2_ADC_CHAN(dln2->iio_channels[i], i) + IIO_CHAN_SOFT_TIMESTAMP_ASSIGN(dln2->iio_channels[i], i); + + indio_dev->name = DLN2_ADC_MOD_NAME; + indio_dev->dev.parent = dev; + indio_dev->info = &dln2_adc_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = dln2->iio_channels; + indio_dev->num_channels = chans + 1; + indio_dev->setup_ops = &dln2_adc_buffer_setup_ops; + + dln2->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", + indio_dev->name, indio_dev->id); + if (!dln2->trig) { + dev_err(dev, "failed to allocate trigger\n"); + return -ENOMEM; + } + dln2->trig->ops = &dln2_adc_trigger_ops; + iio_trigger_set_drvdata(dln2->trig, dln2); + devm_iio_trigger_register(dev, dln2->trig); + iio_trigger_set_immutable(indio_dev, dln2->trig); + + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, + dln2_adc_trigger_h, + &dln2_adc_buffer_setup_ops); + if (ret) { + dev_err(dev, "failed to allocate triggered buffer: %d\n", ret); + return ret; + } + + ret = dln2_register_event_cb(pdev, DLN2_ADC_CONDITION_MET_EV, + dln2_adc_event); + if (ret) { + dev_err(dev, "failed to setup DLN2 periodic event: %d\n", ret); + return ret; + } + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(dev, "failed to register iio device: %d\n", ret); + goto unregister_event; + } + + return ret; + +unregister_event: + dln2_unregister_event_cb(pdev, DLN2_ADC_CONDITION_MET_EV); + + return ret; +} + +static int dln2_adc_remove(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + + iio_device_unregister(indio_dev); + dln2_unregister_event_cb(pdev, DLN2_ADC_CONDITION_MET_EV); + return 0; +} + +static struct platform_driver dln2_adc_driver = { + .driver.name = DLN2_ADC_MOD_NAME, + .probe = dln2_adc_probe, + .remove = dln2_adc_remove, +}; + +module_platform_driver(dln2_adc_driver); + +MODULE_AUTHOR("Jack Andersen <jackoalan@gmail.com"); +MODULE_DESCRIPTION("Driver for the Diolan DLN2 ADC interface"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:dln2-adc"); diff --git a/drivers/iio/adc/ep93xx_adc.c b/drivers/iio/adc/ep93xx_adc.c new file mode 100644 index 000000000000..a179ac476c6d --- /dev/null +++ b/drivers/iio/adc/ep93xx_adc.c @@ -0,0 +1,255 @@ +/* + * Driver for ADC module on the Cirrus Logic EP93xx series of SoCs + * + * Copyright (C) 2015 Alexander Sverdlin + * + * 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 driver uses polling to get the conversion status. According to EP93xx + * datasheets, reading ADCResult register starts the conversion, but user is also + * responsible for ensuring that delay between adjacent conversion triggers is + * long enough so that maximum allowed conversion rate is not exceeded. This + * basically renders IRQ mode unusable. + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/iio/iio.h> +#include <linux/io.h> +#include <linux/irqflags.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/platform_device.h> + +/* + * This code could benefit from real HR Timers, but jiffy granularity would + * lower ADC conversion rate down to CONFIG_HZ, so we fallback to busy wait + * in such case. + * + * HR Timers-based version loads CPU only up to 10% during back to back ADC + * conversion, while busy wait-based version consumes whole CPU power. + */ +#ifdef CONFIG_HIGH_RES_TIMERS +#define ep93xx_adc_delay(usmin, usmax) usleep_range(usmin, usmax) +#else +#define ep93xx_adc_delay(usmin, usmax) udelay(usmin) +#endif + +#define EP93XX_ADC_RESULT 0x08 +#define EP93XX_ADC_SDR BIT(31) +#define EP93XX_ADC_SWITCH 0x18 +#define EP93XX_ADC_SW_LOCK 0x20 + +struct ep93xx_adc_priv { + struct clk *clk; + void __iomem *base; + int lastch; + struct mutex lock; +}; + +#define EP93XX_ADC_CH(index, dname, swcfg) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = index, \ + .address = swcfg, \ + .datasheet_name = dname, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_OFFSET), \ +} + +/* + * Numbering scheme for channels 0..4 is defined in EP9301 and EP9302 datasheets. + * EP9307, EP9312 and EP9312 have 3 channels more (total 8), but the numbering is + * not defined. So the last three are numbered randomly, let's say. + */ +static const struct iio_chan_spec ep93xx_adc_channels[8] = { + EP93XX_ADC_CH(0, "YM", 0x608), + EP93XX_ADC_CH(1, "SXP", 0x680), + EP93XX_ADC_CH(2, "SXM", 0x640), + EP93XX_ADC_CH(3, "SYP", 0x620), + EP93XX_ADC_CH(4, "SYM", 0x610), + EP93XX_ADC_CH(5, "XP", 0x601), + EP93XX_ADC_CH(6, "XM", 0x602), + EP93XX_ADC_CH(7, "YP", 0x604), +}; + +static int ep93xx_read_raw(struct iio_dev *iiodev, + struct iio_chan_spec const *channel, int *value, + int *shift, long mask) +{ + struct ep93xx_adc_priv *priv = iio_priv(iiodev); + unsigned long timeout; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&priv->lock); + if (priv->lastch != channel->channel) { + priv->lastch = channel->channel; + /* + * Switch register is software-locked, unlocking must be + * immediately followed by write + */ + local_irq_disable(); + writel_relaxed(0xAA, priv->base + EP93XX_ADC_SW_LOCK); + writel_relaxed(channel->address, + priv->base + EP93XX_ADC_SWITCH); + local_irq_enable(); + /* + * Settling delay depends on module clock and could be + * 2ms or 500us + */ + ep93xx_adc_delay(2000, 2000); + } + /* Start the conversion, eventually discarding old result */ + readl_relaxed(priv->base + EP93XX_ADC_RESULT); + /* Ensure maximum conversion rate is not exceeded */ + ep93xx_adc_delay(DIV_ROUND_UP(1000000, 925), + DIV_ROUND_UP(1000000, 925)); + /* At this point conversion must be completed, but anyway... */ + ret = IIO_VAL_INT; + timeout = jiffies + msecs_to_jiffies(1) + 1; + while (1) { + u32 t; + + t = readl_relaxed(priv->base + EP93XX_ADC_RESULT); + if (t & EP93XX_ADC_SDR) { + *value = sign_extend32(t, 15); + break; + } + + if (time_after(jiffies, timeout)) { + dev_err(&iiodev->dev, "Conversion timeout\n"); + ret = -ETIMEDOUT; + break; + } + + cpu_relax(); + } + mutex_unlock(&priv->lock); + return ret; + + case IIO_CHAN_INFO_OFFSET: + /* According to datasheet, range is -25000..25000 */ + *value = 25000; + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + /* Typical supply voltage is 3.3v */ + *value = (1ULL << 32) * 3300 / 50000; + *shift = 32; + return IIO_VAL_FRACTIONAL_LOG2; + } + + return -EINVAL; +} + +static const struct iio_info ep93xx_adc_info = { + .driver_module = THIS_MODULE, + .read_raw = ep93xx_read_raw, +}; + +static int ep93xx_adc_probe(struct platform_device *pdev) +{ + int ret; + struct iio_dev *iiodev; + struct ep93xx_adc_priv *priv; + struct clk *pclk; + struct resource *res; + + iiodev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv)); + if (!iiodev) + return -ENOMEM; + priv = iio_priv(iiodev); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "Cannot obtain memory resource\n"); + return -ENXIO; + } + priv->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(priv->base)) { + dev_err(&pdev->dev, "Cannot map memory resource\n"); + return PTR_ERR(priv->base); + } + + iiodev->dev.parent = &pdev->dev; + iiodev->name = dev_name(&pdev->dev); + iiodev->modes = INDIO_DIRECT_MODE; + iiodev->info = &ep93xx_adc_info; + iiodev->num_channels = ARRAY_SIZE(ep93xx_adc_channels); + iiodev->channels = ep93xx_adc_channels; + + priv->lastch = -1; + mutex_init(&priv->lock); + + platform_set_drvdata(pdev, iiodev); + + priv->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(priv->clk)) { + dev_err(&pdev->dev, "Cannot obtain clock\n"); + return PTR_ERR(priv->clk); + } + + pclk = clk_get_parent(priv->clk); + if (!pclk) { + dev_warn(&pdev->dev, "Cannot obtain parent clock\n"); + } else { + /* + * This is actually a place for improvement: + * EP93xx ADC supports two clock divisors -- 4 and 16, + * resulting in conversion rates 3750 and 925 samples per second + * with 500us or 2ms settling time respectively. + * One might find this interesting enough to be configurable. + */ + ret = clk_set_rate(priv->clk, clk_get_rate(pclk) / 16); + if (ret) + dev_warn(&pdev->dev, "Cannot set clock rate\n"); + /* + * We can tolerate rate setting failure because the module should + * work in any case. + */ + } + + ret = clk_enable(priv->clk); + if (ret) { + dev_err(&pdev->dev, "Cannot enable clock\n"); + return ret; + } + + ret = iio_device_register(iiodev); + if (ret) + clk_disable(priv->clk); + + return ret; +} + +static int ep93xx_adc_remove(struct platform_device *pdev) +{ + struct iio_dev *iiodev = platform_get_drvdata(pdev); + struct ep93xx_adc_priv *priv = iio_priv(iiodev); + + iio_device_unregister(iiodev); + clk_disable(priv->clk); + + return 0; +} + +static struct platform_driver ep93xx_adc_driver = { + .driver = { + .name = "ep93xx-adc", + }, + .probe = ep93xx_adc_probe, + .remove = ep93xx_adc_remove, +}; +module_platform_driver(ep93xx_adc_driver); + +MODULE_AUTHOR("Alexander Sverdlin <alexander.sverdlin@gmail.com>"); +MODULE_DESCRIPTION("Cirrus Logic EP93XX ADC driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:ep93xx-adc"); diff --git a/drivers/iio/adc/hi8435.c b/drivers/iio/adc/hi8435.c index 678e8c7ea763..adf7dc712937 100644 --- a/drivers/iio/adc/hi8435.c +++ b/drivers/iio/adc/hi8435.c @@ -105,6 +105,26 @@ static int hi8435_writew(struct hi8435_priv *priv, u8 reg, u16 val) return spi_write(priv->spi, priv->reg_buffer, 3); } +static int hi8435_read_raw(struct iio_dev *idev, + const struct iio_chan_spec *chan, + int *val, int *val2, long mask) +{ + struct hi8435_priv *priv = iio_priv(idev); + u32 tmp; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = hi8435_readl(priv, HI8435_SO31_0_REG, &tmp); + if (ret < 0) + return ret; + *val = !!(tmp & BIT(chan->channel)); + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + static int hi8435_read_event_config(struct iio_dev *idev, const struct iio_chan_spec *chan, enum iio_event_type type, @@ -121,10 +141,21 @@ static int hi8435_write_event_config(struct iio_dev *idev, enum iio_event_direction dir, int state) { struct hi8435_priv *priv = iio_priv(idev); + int ret; + u32 tmp; + + if (state) { + ret = hi8435_readl(priv, HI8435_SO31_0_REG, &tmp); + if (ret < 0) + return ret; + if (tmp & BIT(chan->channel)) + priv->event_prev_val |= BIT(chan->channel); + else + priv->event_prev_val &= ~BIT(chan->channel); - priv->event_scan_mask &= ~BIT(chan->channel); - if (state) priv->event_scan_mask |= BIT(chan->channel); + } else + priv->event_scan_mask &= ~BIT(chan->channel); return 0; } @@ -325,6 +356,7 @@ static const struct iio_enum hi8435_sensing_mode = { static const struct iio_chan_spec_ext_info hi8435_ext_info[] = { IIO_ENUM("sensing_mode", IIO_SEPARATE, &hi8435_sensing_mode), + IIO_ENUM_AVAILABLE("sensing_mode", &hi8435_sensing_mode), {}, }; @@ -333,6 +365,7 @@ static const struct iio_chan_spec_ext_info hi8435_ext_info[] = { .type = IIO_VOLTAGE, \ .indexed = 1, \ .channel = num, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .event_spec = hi8435_events, \ .num_event_specs = ARRAY_SIZE(hi8435_events), \ .ext_info = hi8435_ext_info, \ @@ -376,11 +409,12 @@ static const struct iio_chan_spec hi8435_channels[] = { static const struct iio_info hi8435_info = { .driver_module = THIS_MODULE, - .read_event_config = &hi8435_read_event_config, + .read_raw = hi8435_read_raw, + .read_event_config = hi8435_read_event_config, .write_event_config = hi8435_write_event_config, - .read_event_value = &hi8435_read_event_value, - .write_event_value = &hi8435_write_event_value, - .debugfs_reg_access = &hi8435_debugfs_reg_access, + .read_event_value = hi8435_read_event_value, + .write_event_value = hi8435_write_event_value, + .debugfs_reg_access = hi8435_debugfs_reg_access, }; static void hi8435_iio_push_event(struct iio_dev *idev, unsigned int val) diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index db9838230257..f387b972e4f4 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -42,13 +42,15 @@ #define INA2XX_CURRENT 0x04 /* readonly */ #define INA2XX_CALIBRATION 0x05 -#define INA226_ALERT_MASK GENMASK(2, 1) -#define INA266_CVRF BIT(3) +#define INA226_MASK_ENABLE 0x06 +#define INA226_CVRF BIT(3) +#define INA219_CNVR BIT(1) #define INA2XX_MAX_REGISTERS 8 /* settings - depend on use case */ #define INA219_CONFIG_DEFAULT 0x399F /* PGA=8 */ +#define INA219_DEFAULT_IT 532 #define INA226_CONFIG_DEFAULT 0x4327 #define INA226_DEFAULT_AVG 4 #define INA226_DEFAULT_IT 1110 @@ -56,19 +58,24 @@ #define INA2XX_RSHUNT_DEFAULT 10000 /* - * bit mask for reading the averaging setting in the configuration register + * bit masks for reading the settings in the configuration register * FIXME: use regmap_fields. */ #define INA2XX_MODE_MASK GENMASK(3, 0) +/* Averaging for VBus/VShunt/Power */ #define INA226_AVG_MASK GENMASK(11, 9) #define INA226_SHIFT_AVG(val) ((val) << 9) /* Integration time for VBus */ +#define INA219_ITB_MASK GENMASK(10, 7) +#define INA219_SHIFT_ITB(val) ((val) << 7) #define INA226_ITB_MASK GENMASK(8, 6) #define INA226_SHIFT_ITB(val) ((val) << 6) /* Integration time for VShunt */ +#define INA219_ITS_MASK GENMASK(6, 3) +#define INA219_SHIFT_ITS(val) ((val) << 3) #define INA226_ITS_MASK GENMASK(5, 3) #define INA226_SHIFT_ITS(val) ((val) << 3) @@ -108,6 +115,7 @@ struct ina2xx_config { int bus_voltage_shift; int bus_voltage_lsb; /* uV */ int power_lsb; /* uW */ + enum ina2xx_ids chip_id; }; struct ina2xx_chip_info { @@ -130,6 +138,7 @@ static const struct ina2xx_config ina2xx_config[] = { .bus_voltage_shift = 3, .bus_voltage_lsb = 4000, .power_lsb = 20000, + .chip_id = ina219, }, [ina226] = { .config_default = INA226_CONFIG_DEFAULT, @@ -138,6 +147,7 @@ static const struct ina2xx_config ina2xx_config[] = { .bus_voltage_shift = 0, .bus_voltage_lsb = 1250, .power_lsb = 25000, + .chip_id = ina226, }, }; @@ -283,6 +293,66 @@ static int ina226_set_int_time_vshunt(struct ina2xx_chip_info *chip, return 0; } +/* Conversion times in uS. */ +static const int ina219_conv_time_tab_subsample[] = { 84, 148, 276, 532 }; +static const int ina219_conv_time_tab_average[] = { 532, 1060, 2130, 4260, + 8510, 17020, 34050, 68100}; + +static int ina219_lookup_int_time(unsigned int *val_us, int *bits) +{ + if (*val_us > 68100 || *val_us < 84) + return -EINVAL; + + if (*val_us <= 532) { + *bits = find_closest(*val_us, ina219_conv_time_tab_subsample, + ARRAY_SIZE(ina219_conv_time_tab_subsample)); + *val_us = ina219_conv_time_tab_subsample[*bits]; + } else { + *bits = find_closest(*val_us, ina219_conv_time_tab_average, + ARRAY_SIZE(ina219_conv_time_tab_average)); + *val_us = ina219_conv_time_tab_average[*bits]; + *bits |= 0x8; + } + + return 0; +} + +static int ina219_set_int_time_vbus(struct ina2xx_chip_info *chip, + unsigned int val_us, unsigned int *config) +{ + int bits, ret; + unsigned int val_us_best = val_us; + + ret = ina219_lookup_int_time(&val_us_best, &bits); + if (ret) + return ret; + + chip->int_time_vbus = val_us_best; + + *config &= ~INA219_ITB_MASK; + *config |= INA219_SHIFT_ITB(bits) & INA219_ITB_MASK; + + return 0; +} + +static int ina219_set_int_time_vshunt(struct ina2xx_chip_info *chip, + unsigned int val_us, unsigned int *config) +{ + int bits, ret; + unsigned int val_us_best = val_us; + + ret = ina219_lookup_int_time(&val_us_best, &bits); + if (ret) + return ret; + + chip->int_time_vshunt = val_us_best; + + *config &= ~INA219_ITS_MASK; + *config |= INA219_SHIFT_ITS(bits) & INA219_ITS_MASK; + + return 0; +} + static int ina2xx_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) @@ -308,10 +378,21 @@ static int ina2xx_write_raw(struct iio_dev *indio_dev, break; case IIO_CHAN_INFO_INT_TIME: - if (chan->address == INA2XX_SHUNT_VOLTAGE) - ret = ina226_set_int_time_vshunt(chip, val2, &tmp); - else - ret = ina226_set_int_time_vbus(chip, val2, &tmp); + if (chip->config->chip_id == ina226) { + if (chan->address == INA2XX_SHUNT_VOLTAGE) + ret = ina226_set_int_time_vshunt(chip, val2, + &tmp); + else + ret = ina226_set_int_time_vbus(chip, val2, + &tmp); + } else { + if (chan->address == INA2XX_SHUNT_VOLTAGE) + ret = ina219_set_int_time_vshunt(chip, val2, + &tmp); + else + ret = ina219_set_int_time_vbus(chip, val2, + &tmp); + } break; default: @@ -412,13 +493,30 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev, return len; } -#define INA2XX_CHAN(_type, _index, _address) { \ +#define INA219_CHAN(_type, _index, _address) { \ + .type = (_type), \ + .address = (_address), \ + .indexed = 1, \ + .channel = (_index), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = (_index), \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_CPU, \ + } \ +} + +#define INA226_CHAN(_type, _index, _address) { \ .type = (_type), \ .address = (_address), \ .indexed = 1, \ .channel = (_index), \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) \ - | BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ .scan_index = (_index), \ @@ -434,7 +532,7 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev, * Sampling Freq is a consequence of the integration times of * the Voltage channels. */ -#define INA2XX_CHAN_VOLTAGE(_index, _address) { \ +#define INA219_CHAN_VOLTAGE(_index, _address) { \ .type = IIO_VOLTAGE, \ .address = (_address), \ .indexed = 1, \ @@ -442,6 +540,7 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_INT_TIME), \ + .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .scan_index = (_index), \ .scan_type = { \ .sign = 'u', \ @@ -451,11 +550,39 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev, } \ } -static const struct iio_chan_spec ina2xx_channels[] = { - INA2XX_CHAN_VOLTAGE(0, INA2XX_SHUNT_VOLTAGE), - INA2XX_CHAN_VOLTAGE(1, INA2XX_BUS_VOLTAGE), - INA2XX_CHAN(IIO_POWER, 2, INA2XX_POWER), - INA2XX_CHAN(IIO_CURRENT, 3, INA2XX_CURRENT), +#define INA226_CHAN_VOLTAGE(_index, _address) { \ + .type = IIO_VOLTAGE, \ + .address = (_address), \ + .indexed = 1, \ + .channel = (_index), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_INT_TIME), \ + .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ + .scan_index = (_index), \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_LE, \ + } \ +} + + +static const struct iio_chan_spec ina226_channels[] = { + INA226_CHAN_VOLTAGE(0, INA2XX_SHUNT_VOLTAGE), + INA226_CHAN_VOLTAGE(1, INA2XX_BUS_VOLTAGE), + INA226_CHAN(IIO_POWER, 2, INA2XX_POWER), + INA226_CHAN(IIO_CURRENT, 3, INA2XX_CURRENT), + IIO_CHAN_SOFT_TIMESTAMP(4), +}; + +static const struct iio_chan_spec ina219_channels[] = { + INA219_CHAN_VOLTAGE(0, INA2XX_SHUNT_VOLTAGE), + INA219_CHAN_VOLTAGE(1, INA2XX_BUS_VOLTAGE), + INA219_CHAN(IIO_POWER, 2, INA2XX_POWER), + INA219_CHAN(IIO_CURRENT, 3, INA2XX_CURRENT), IIO_CHAN_SOFT_TIMESTAMP(4), }; @@ -466,6 +593,7 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev) int bit, ret, i = 0; s64 time_a, time_b; unsigned int alert; + int cnvr_need_clear = 0; time_a = iio_get_time_ns(indio_dev); @@ -477,22 +605,30 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev) * we check the ConVersionReadyFlag. * On hardware that supports using the ALERT pin to toggle a * GPIO a triggered buffer could be used instead. - * For now, we pay for that extra read of the ALERT register + * For now, we do an extra read of the MASK_ENABLE register (INA226) + * resp. the BUS_VOLTAGE register (INA219). */ if (!chip->allow_async_readout) do { - ret = regmap_read(chip->regmap, INA226_ALERT_MASK, - &alert); + if (chip->config->chip_id == ina226) { + ret = regmap_read(chip->regmap, + INA226_MASK_ENABLE, &alert); + alert &= INA226_CVRF; + } else { + ret = regmap_read(chip->regmap, + INA2XX_BUS_VOLTAGE, &alert); + alert &= INA219_CNVR; + cnvr_need_clear = alert; + } + if (ret < 0) return ret; - alert &= INA266_CVRF; } while (!alert); /* - * Single register reads: bulk_read will not work with ina226 - * as there is no auto-increment of the address register for - * data length longer than 16bits. + * Single register reads: bulk_read will not work with ina226/219 + * as there is no auto-increment of the register pointer. */ for_each_set_bit(bit, indio_dev->active_scan_mask, indio_dev->masklength) { @@ -504,6 +640,18 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev) return ret; data[i++] = val; + + if (INA2XX_SHUNT_VOLTAGE + bit == INA2XX_POWER) + cnvr_need_clear = 0; + } + + /* Dummy read on INA219 power register to clear CNVR flag */ + if (cnvr_need_clear && chip->config->chip_id == ina219) { + unsigned int val; + + ret = regmap_read(chip->regmap, INA2XX_POWER, &val); + if (ret < 0) + return ret; } time_b = iio_get_time_ns(indio_dev); @@ -518,7 +666,7 @@ static int ina2xx_capture_thread(void *data) { struct iio_dev *indio_dev = data; struct ina2xx_chip_info *chip = iio_priv(indio_dev); - unsigned int sampling_us = SAMPLING_PERIOD(chip); + int sampling_us = SAMPLING_PERIOD(chip); int buffer_us; /* @@ -590,7 +738,14 @@ static int ina2xx_debug_reg(struct iio_dev *indio_dev, } /* Possible integration times for vshunt and vbus */ -static IIO_CONST_ATTR_INT_TIME_AVAIL("0.000140 0.000204 0.000332 0.000588 0.001100 0.002116 0.004156 0.008244"); +static IIO_CONST_ATTR_NAMED(ina219_integration_time_available, + integration_time_available, + "0.000084 0.000148 0.000276 0.000532 0.001060 0.002130 0.004260 0.008510 0.017020 0.034050 0.068100"); + +static IIO_CONST_ATTR_NAMED(ina226_integration_time_available, + integration_time_available, + "0.000140 0.000204 0.000332 0.000588 0.001100 0.002116 0.004156 0.008244"); + static IIO_DEVICE_ATTR(in_allow_async_readout, S_IRUGO | S_IWUSR, ina2xx_allow_async_readout_show, @@ -600,20 +755,39 @@ static IIO_DEVICE_ATTR(in_shunt_resistor, S_IRUGO | S_IWUSR, ina2xx_shunt_resistor_show, ina2xx_shunt_resistor_store, 0); -static struct attribute *ina2xx_attributes[] = { +static struct attribute *ina219_attributes[] = { + &iio_dev_attr_in_allow_async_readout.dev_attr.attr, + &iio_const_attr_ina219_integration_time_available.dev_attr.attr, + &iio_dev_attr_in_shunt_resistor.dev_attr.attr, + NULL, +}; + +static struct attribute *ina226_attributes[] = { &iio_dev_attr_in_allow_async_readout.dev_attr.attr, - &iio_const_attr_integration_time_available.dev_attr.attr, + &iio_const_attr_ina226_integration_time_available.dev_attr.attr, &iio_dev_attr_in_shunt_resistor.dev_attr.attr, NULL, }; -static const struct attribute_group ina2xx_attribute_group = { - .attrs = ina2xx_attributes, +static const struct attribute_group ina219_attribute_group = { + .attrs = ina219_attributes, +}; + +static const struct attribute_group ina226_attribute_group = { + .attrs = ina226_attributes, +}; + +static const struct iio_info ina219_info = { + .driver_module = THIS_MODULE, + .attrs = &ina219_attribute_group, + .read_raw = ina2xx_read_raw, + .write_raw = ina2xx_write_raw, + .debugfs_reg_access = ina2xx_debug_reg, }; -static const struct iio_info ina2xx_info = { +static const struct iio_info ina226_info = { .driver_module = THIS_MODULE, - .attrs = &ina2xx_attribute_group, + .attrs = &ina226_attribute_group, .read_raw = ina2xx_read_raw, .write_raw = ina2xx_write_raw, .debugfs_reg_access = ina2xx_debug_reg, @@ -684,6 +858,10 @@ static int ina2xx_probe(struct i2c_client *client, ina226_set_average(chip, INA226_DEFAULT_AVG, &val); ina226_set_int_time_vbus(chip, INA226_DEFAULT_IT, &val); ina226_set_int_time_vshunt(chip, INA226_DEFAULT_IT, &val); + } else { + chip->avg = 1; + ina219_set_int_time_vbus(chip, INA219_DEFAULT_IT, &val); + ina219_set_int_time_vshunt(chip, INA219_DEFAULT_IT, &val); } ret = ina2xx_init(chip, val); @@ -695,10 +873,16 @@ 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); + if (id->driver_data == ina226) { + indio_dev->channels = ina226_channels; + indio_dev->num_channels = ARRAY_SIZE(ina226_channels); + indio_dev->info = &ina226_info; + } else { + indio_dev->channels = ina219_channels; + indio_dev->num_channels = ARRAY_SIZE(ina219_channels); + indio_dev->info = &ina219_info; + } indio_dev->name = id->name; - indio_dev->info = &ina2xx_info; indio_dev->setup_ops = &ina2xx_setup_ops; buffer = devm_iio_kfifo_allocate(&indio_dev->dev); diff --git a/drivers/iio/adc/lpc32xx_adc.c b/drivers/iio/adc/lpc32xx_adc.c index 0de709b4288b..6a5b9a9bc662 100644 --- a/drivers/iio/adc/lpc32xx_adc.c +++ b/drivers/iio/adc/lpc32xx_adc.c @@ -76,10 +76,14 @@ static int lpc32xx_read_raw(struct iio_dev *indio_dev, long mask) { struct lpc32xx_adc_state *st = iio_priv(indio_dev); - + int ret; if (mask == IIO_CHAN_INFO_RAW) { mutex_lock(&indio_dev->mlock); - clk_prepare_enable(st->clk); + ret = clk_prepare_enable(st->clk); + if (ret) { + mutex_unlock(&indio_dev->mlock); + return ret; + } /* Measurement setup */ __raw_writel(LPC32XXAD_INTERNAL | (chan->address) | LPC32XXAD_REFp | LPC32XXAD_REFm, diff --git a/drivers/iio/adc/ltc2471.c b/drivers/iio/adc/ltc2471.c new file mode 100644 index 000000000000..29b7ed60cdb0 --- /dev/null +++ b/drivers/iio/adc/ltc2471.c @@ -0,0 +1,160 @@ +/* + * Driver for Linear Technology LTC2471 and LTC2473 voltage monitors + * The LTC2473 is identical to the 2471, but reports a differential signal. + * + * Copyright (C) 2017 Topic Embedded Products + * Author: Mike Looijmans <mike.looijmans@topic.nl> + * + * License: GPLv2 + */ + +#include <linux/err.h> +#include <linux/i2c.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> + +enum ltc2471_chips { + ltc2471, + ltc2473, +}; + +struct ltc2471_data { + struct i2c_client *client; +}; + +/* Reference voltage is 1.25V */ +#define LTC2471_VREF 1250 + +/* Read two bytes from the I2C bus to obtain the ADC result */ +static int ltc2471_get_value(struct i2c_client *client) +{ + int ret; + __be16 buf; + + ret = i2c_master_recv(client, (char *)&buf, sizeof(buf)); + if (ret < 0) + return ret; + if (ret != sizeof(buf)) + return -EIO; + + /* MSB first */ + return be16_to_cpu(buf); +} + +static int ltc2471_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long info) +{ + struct ltc2471_data *data = iio_priv(indio_dev); + int ret; + + switch (info) { + case IIO_CHAN_INFO_RAW: + ret = ltc2471_get_value(data->client); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + if (chan->differential) + /* Output ranges from -VREF to +VREF */ + *val = 2 * LTC2471_VREF; + else + /* Output ranges from 0 to VREF */ + *val = LTC2471_VREF; + *val2 = 16; /* 16 data bits */ + return IIO_VAL_FRACTIONAL_LOG2; + + case IIO_CHAN_INFO_OFFSET: + /* Only differential chip has this property */ + *val = -LTC2471_VREF; + return IIO_VAL_INT; + + default: + return -EINVAL; + } +} + +static const struct iio_chan_spec ltc2471_channel[] = { + { + .type = IIO_VOLTAGE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + }, +}; + +static const struct iio_chan_spec ltc2473_channel[] = { + { + .type = IIO_VOLTAGE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET), + .differential = 1, + }, +}; + +static const struct iio_info ltc2471_info = { + .read_raw = ltc2471_read_raw, + .driver_module = THIS_MODULE, +}; + +static int ltc2471_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct iio_dev *indio_dev; + struct ltc2471_data *data; + int ret; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -EOPNOTSUPP; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + data->client = client; + + indio_dev->dev.parent = &client->dev; + indio_dev->name = id->name; + indio_dev->info = <c2471_info; + indio_dev->modes = INDIO_DIRECT_MODE; + if (id->driver_data == ltc2473) + indio_dev->channels = ltc2473_channel; + else + indio_dev->channels = ltc2471_channel; + indio_dev->num_channels = 1; + + /* Trigger once to start conversion and check if chip is there */ + ret = ltc2471_get_value(client); + if (ret < 0) { + dev_err(&client->dev, "Cannot read from device.\n"); + return ret; + } + + return devm_iio_device_register(&client->dev, indio_dev); +} + +static const struct i2c_device_id ltc2471_i2c_id[] = { + { "ltc2471", ltc2471 }, + { "ltc2473", ltc2473 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, ltc2471_i2c_id); + +static struct i2c_driver ltc2471_i2c_driver = { + .driver = { + .name = "ltc2471", + }, + .probe = ltc2471_i2c_probe, + .id_table = ltc2471_i2c_id, +}; + +module_i2c_driver(ltc2471_i2c_driver); + +MODULE_DESCRIPTION("LTC2471/LTC2473 ADC driver"); +MODULE_AUTHOR("Topic Embedded Products"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/ltc2497.c b/drivers/iio/adc/ltc2497.c index 2691b10023f5..5bf8011dcde9 100644 --- a/drivers/iio/adc/ltc2497.c +++ b/drivers/iio/adc/ltc2497.c @@ -11,6 +11,7 @@ #include <linux/delay.h> #include <linux/i2c.h> #include <linux/iio/iio.h> +#include <linux/iio/driver.h> #include <linux/iio/sysfs.h> #include <linux/module.h> #include <linux/of.h> @@ -127,13 +128,14 @@ static int ltc2497_read_raw(struct iio_dev *indio_dev, } } -#define LTC2497_CHAN(_chan, _addr) { \ +#define LTC2497_CHAN(_chan, _addr, _ds_name) { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ .channel = (_chan), \ .address = (_addr | (_chan / 2) | ((_chan & 1) ? LTC2497_SIGN : 0)), \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .datasheet_name = (_ds_name), \ } #define LTC2497_CHAN_DIFF(_chan, _addr) { \ @@ -148,22 +150,22 @@ static int ltc2497_read_raw(struct iio_dev *indio_dev, } static const struct iio_chan_spec ltc2497_channel[] = { - LTC2497_CHAN(0, LTC2497_SGL), - LTC2497_CHAN(1, LTC2497_SGL), - LTC2497_CHAN(2, LTC2497_SGL), - LTC2497_CHAN(3, LTC2497_SGL), - LTC2497_CHAN(4, LTC2497_SGL), - LTC2497_CHAN(5, LTC2497_SGL), - LTC2497_CHAN(6, LTC2497_SGL), - LTC2497_CHAN(7, LTC2497_SGL), - LTC2497_CHAN(8, LTC2497_SGL), - LTC2497_CHAN(9, LTC2497_SGL), - LTC2497_CHAN(10, LTC2497_SGL), - LTC2497_CHAN(11, LTC2497_SGL), - LTC2497_CHAN(12, LTC2497_SGL), - LTC2497_CHAN(13, LTC2497_SGL), - LTC2497_CHAN(14, LTC2497_SGL), - LTC2497_CHAN(15, LTC2497_SGL), + LTC2497_CHAN(0, LTC2497_SGL, "CH0"), + LTC2497_CHAN(1, LTC2497_SGL, "CH1"), + LTC2497_CHAN(2, LTC2497_SGL, "CH2"), + LTC2497_CHAN(3, LTC2497_SGL, "CH3"), + LTC2497_CHAN(4, LTC2497_SGL, "CH4"), + LTC2497_CHAN(5, LTC2497_SGL, "CH5"), + LTC2497_CHAN(6, LTC2497_SGL, "CH6"), + LTC2497_CHAN(7, LTC2497_SGL, "CH7"), + LTC2497_CHAN(8, LTC2497_SGL, "CH8"), + LTC2497_CHAN(9, LTC2497_SGL, "CH9"), + LTC2497_CHAN(10, LTC2497_SGL, "CH10"), + LTC2497_CHAN(11, LTC2497_SGL, "CH11"), + LTC2497_CHAN(12, LTC2497_SGL, "CH12"), + LTC2497_CHAN(13, LTC2497_SGL, "CH13"), + LTC2497_CHAN(14, LTC2497_SGL, "CH14"), + LTC2497_CHAN(15, LTC2497_SGL, "CH15"), LTC2497_CHAN_DIFF(0, LTC2497_DIFF), LTC2497_CHAN_DIFF(1, LTC2497_DIFF), LTC2497_CHAN_DIFF(2, LTC2497_DIFF), @@ -192,6 +194,7 @@ static int ltc2497_probe(struct i2c_client *client, { struct iio_dev *indio_dev; struct ltc2497_st *st; + struct iio_map *plat_data; int ret; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | @@ -221,19 +224,31 @@ static int ltc2497_probe(struct i2c_client *client, if (ret < 0) return ret; + if (client->dev.platform_data) { + plat_data = ((struct iio_map *)client->dev.platform_data); + ret = iio_map_array_register(indio_dev, plat_data); + if (ret) { + dev_err(&indio_dev->dev, "iio map err: %d\n", ret); + goto err_regulator_disable; + } + } + ret = i2c_smbus_write_byte(st->client, LTC2497_CONFIG_DEFAULT); if (ret < 0) - goto err_regulator_disable; + goto err_array_unregister; st->addr_prev = LTC2497_CONFIG_DEFAULT; st->time_prev = ktime_get(); ret = iio_device_register(indio_dev); if (ret < 0) - goto err_regulator_disable; + goto err_array_unregister; return 0; +err_array_unregister: + iio_map_array_unregister(indio_dev); + err_regulator_disable: regulator_disable(st->ref); @@ -245,6 +260,7 @@ static int ltc2497_remove(struct i2c_client *client) struct iio_dev *indio_dev = i2c_get_clientdata(client); struct ltc2497_st *st = iio_priv(indio_dev); + iio_map_array_unregister(indio_dev); iio_device_unregister(indio_dev); regulator_disable(st->ref); diff --git a/drivers/iio/adc/max9611.c b/drivers/iio/adc/max9611.c index b0526e4b9530..b1dd17cbce58 100644 --- a/drivers/iio/adc/max9611.c +++ b/drivers/iio/adc/max9611.c @@ -549,8 +549,8 @@ static int max9611_probe(struct i2c_client *client, ret = of_property_read_u32(of_node, shunt_res_prop, &of_shunt); if (ret) { dev_err(&client->dev, - "Missing %s property for %s node\n", - shunt_res_prop, of_node->full_name); + "Missing %s property for %pOF node\n", + shunt_res_prop, of_node); return ret; } max9611->shunt_resistor_uohm = of_shunt; diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c index 634717ae12f3..071dd23a33d9 100644 --- a/drivers/iio/adc/mcp320x.c +++ b/drivers/iio/adc/mcp320x.c @@ -17,6 +17,8 @@ * MCP3204 * MCP3208 * ------------ + * 13 bit converter + * MCP3301 * * Datasheet can be found here: * http://ww1.microchip.com/downloads/en/DeviceDoc/21293C.pdf mcp3001 @@ -96,7 +98,7 @@ static int mcp320x_channel_to_tx_data(int device_index, } static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel, - bool differential, int device_index) + bool differential, int device_index, int *val) { int ret; @@ -117,19 +119,25 @@ static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel, switch (device_index) { case mcp3001: - return (adc->rx_buf[0] << 5 | adc->rx_buf[1] >> 3); + *val = (adc->rx_buf[0] << 5 | adc->rx_buf[1] >> 3); + return 0; case mcp3002: case mcp3004: case mcp3008: - return (adc->rx_buf[0] << 2 | adc->rx_buf[1] >> 6); + *val = (adc->rx_buf[0] << 2 | adc->rx_buf[1] >> 6); + return 0; case mcp3201: - return (adc->rx_buf[0] << 7 | adc->rx_buf[1] >> 1); + *val = (adc->rx_buf[0] << 7 | adc->rx_buf[1] >> 1); + return 0; case mcp3202: case mcp3204: case mcp3208: - return (adc->rx_buf[0] << 4 | adc->rx_buf[1] >> 4); + *val = (adc->rx_buf[0] << 4 | adc->rx_buf[1] >> 4); + return 0; case mcp3301: - return sign_extend32((adc->rx_buf[0] & 0x1f) << 8 | adc->rx_buf[1], 12); + *val = sign_extend32((adc->rx_buf[0] & 0x1f) << 8 + | adc->rx_buf[1], 12); + return 0; default: return -EINVAL; } @@ -150,12 +158,10 @@ static int mcp320x_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: ret = mcp320x_adc_conversion(adc, channel->address, - channel->differential, device_index); - + channel->differential, device_index, val); if (ret < 0) goto out; - *val = ret; ret = IIO_VAL_INT; break; @@ -312,6 +318,7 @@ static int mcp320x_probe(struct spi_device *spi) indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &mcp320x_info; + spi_set_drvdata(spi, indio_dev); chip_info = &mcp320x_chip_infos[spi_get_device_id(spi)->driver_data]; indio_dev->channels = chip_info->channels; diff --git a/drivers/iio/adc/mcp3422.c b/drivers/iio/adc/mcp3422.c index 254135e07792..63de705086ed 100644 --- a/drivers/iio/adc/mcp3422.c +++ b/drivers/iio/adc/mcp3422.c @@ -379,10 +379,12 @@ static int mcp3422_probe(struct i2c_client *client, /* meaningful default configuration */ config = (MCP3422_CONT_SAMPLING - | MCP3422_CHANNEL_VALUE(1) + | MCP3422_CHANNEL_VALUE(0) | MCP3422_PGA_VALUE(MCP3422_PGA_1) | MCP3422_SAMPLE_RATE_VALUE(MCP3422_SRATE_240)); - mcp3422_update_config(adc, config); + err = mcp3422_update_config(adc, config); + if (err < 0) + return err; err = devm_iio_device_register(&client->dev, indio_dev); if (err < 0) diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index 6066bbfc42fe..2e8dbb89c8c9 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -220,6 +220,7 @@ enum meson_sar_adc_chan7_mux_sel { }; struct meson_sar_adc_data { + bool has_bl30_integration; unsigned int resolution; const char *name; }; @@ -437,19 +438,24 @@ static int meson_sar_adc_lock(struct iio_dev *indio_dev) mutex_lock(&indio_dev->mlock); - /* prevent BL30 from using the SAR ADC while we are using it */ - regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, - MESON_SAR_ADC_DELAY_KERNEL_BUSY, - MESON_SAR_ADC_DELAY_KERNEL_BUSY); - - /* wait until BL30 releases it's lock (so we can use the SAR ADC) */ - do { - udelay(1); - regmap_read(priv->regmap, MESON_SAR_ADC_DELAY, &val); - } while (val & MESON_SAR_ADC_DELAY_BL30_BUSY && timeout--); - - if (timeout < 0) - return -ETIMEDOUT; + if (priv->data->has_bl30_integration) { + /* prevent BL30 from using the SAR ADC while we are using it */ + regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, + MESON_SAR_ADC_DELAY_KERNEL_BUSY, + MESON_SAR_ADC_DELAY_KERNEL_BUSY); + + /* + * wait until BL30 releases it's lock (so we can use the SAR + * ADC) + */ + do { + udelay(1); + regmap_read(priv->regmap, MESON_SAR_ADC_DELAY, &val); + } while (val & MESON_SAR_ADC_DELAY_BL30_BUSY && timeout--); + + if (timeout < 0) + return -ETIMEDOUT; + } return 0; } @@ -458,9 +464,10 @@ static void meson_sar_adc_unlock(struct iio_dev *indio_dev) { struct meson_sar_adc_priv *priv = iio_priv(indio_dev); - /* allow BL30 to use the SAR ADC again */ - regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, - MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0); + if (priv->data->has_bl30_integration) + /* allow BL30 to use the SAR ADC again */ + regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, + MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0); mutex_unlock(&indio_dev->mlock); } @@ -565,8 +572,8 @@ static int meson_sar_adc_clk_init(struct iio_dev *indio_dev, struct clk_init_data init; const char *clk_parents[1]; - init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%s#adc_div", - of_node_full_name(indio_dev->dev.of_node)); + init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%pOF#adc_div", + indio_dev->dev.of_node); init.flags = 0; init.ops = &clk_divider_ops; clk_parents[0] = __clk_get_name(priv->clkin); @@ -584,8 +591,8 @@ static int meson_sar_adc_clk_init(struct iio_dev *indio_dev, if (WARN_ON(IS_ERR(priv->adc_div_clk))) return PTR_ERR(priv->adc_div_clk); - init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%s#adc_en", - of_node_full_name(indio_dev->dev.of_node)); + init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%pOF#adc_en", + indio_dev->dev.of_node); init.flags = CLK_SET_RATE_PARENT; init.ops = &clk_gate_ops; clk_parents[0] = __clk_get_name(priv->adc_div_clk); @@ -614,14 +621,16 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev) */ meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT); - /* - * leave sampling delay and the input clocks as configured by BL30 to - * make sure BL30 gets the values it expects when reading the - * temperature sensor. - */ - regmap_read(priv->regmap, MESON_SAR_ADC_REG3, ®val); - if (regval & MESON_SAR_ADC_REG3_BL30_INITIALIZED) - return 0; + if (priv->data->has_bl30_integration) { + /* + * leave sampling delay and the input clocks as configured by + * BL30 to make sure BL30 gets the values it expects when + * reading the temperature sensor. + */ + regmap_read(priv->regmap, MESON_SAR_ADC_REG3, ®val); + if (regval & MESON_SAR_ADC_REG3_BL30_INITIALIZED) + return 0; + } meson_sar_adc_stop_sample_engine(indio_dev); @@ -834,23 +843,46 @@ static const struct iio_info meson_sar_adc_iio_info = { .driver_module = THIS_MODULE, }; -struct meson_sar_adc_data meson_sar_adc_gxbb_data = { +static const struct meson_sar_adc_data meson_sar_adc_meson8_data = { + .has_bl30_integration = false, + .resolution = 10, + .name = "meson-meson8-saradc", +}; + +static const struct meson_sar_adc_data meson_sar_adc_meson8b_data = { + .has_bl30_integration = false, + .resolution = 10, + .name = "meson-meson8b-saradc", +}; + +static const struct meson_sar_adc_data meson_sar_adc_gxbb_data = { + .has_bl30_integration = true, .resolution = 10, .name = "meson-gxbb-saradc", }; -struct meson_sar_adc_data meson_sar_adc_gxl_data = { +static const struct meson_sar_adc_data meson_sar_adc_gxl_data = { + .has_bl30_integration = true, .resolution = 12, .name = "meson-gxl-saradc", }; -struct meson_sar_adc_data meson_sar_adc_gxm_data = { +static const struct meson_sar_adc_data meson_sar_adc_gxm_data = { + .has_bl30_integration = true, .resolution = 12, .name = "meson-gxm-saradc", }; static const struct of_device_id meson_sar_adc_of_match[] = { { + .compatible = "amlogic,meson8-saradc", + .data = &meson_sar_adc_meson8_data, + }, + { + .compatible = "amlogic,meson8b-saradc", + .data = &meson_sar_adc_meson8b_data, + }, + { .compatible = "amlogic,meson-gxbb-saradc", .data = &meson_sar_adc_gxbb_data, }, { @@ -883,6 +915,11 @@ static int meson_sar_adc_probe(struct platform_device *pdev) init_completion(&priv->done); match = of_match_device(meson_sar_adc_of_match, &pdev->dev); + if (!match) { + dev_err(&pdev->dev, "failed to match device\n"); + return -ENODEV; + } + priv->data = match->data; indio_dev->name = priv->data->name; diff --git a/drivers/iio/adc/mt6577_auxadc.c b/drivers/iio/adc/mt6577_auxadc.c index 2d104c828041..414cf44bf19d 100644 --- a/drivers/iio/adc/mt6577_auxadc.c +++ b/drivers/iio/adc/mt6577_auxadc.c @@ -184,6 +184,37 @@ static const struct iio_info mt6577_auxadc_info = { .read_raw = &mt6577_auxadc_read_raw, }; +static int __maybe_unused mt6577_auxadc_resume(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev); + int ret; + + ret = clk_prepare_enable(adc_dev->adc_clk); + if (ret) { + pr_err("failed to enable auxadc clock\n"); + return ret; + } + + mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC, + MT6577_AUXADC_PDN_EN, 0); + mdelay(MT6577_AUXADC_POWER_READY_MS); + + return 0; +} + +static int __maybe_unused mt6577_auxadc_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev); + + mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC, + 0, MT6577_AUXADC_PDN_EN); + clk_disable_unprepare(adc_dev->adc_clk); + + return 0; +} + static int mt6577_auxadc_probe(struct platform_device *pdev) { struct mt6577_auxadc_device *adc_dev; @@ -269,8 +300,13 @@ static int mt6577_auxadc_remove(struct platform_device *pdev) return 0; } +static SIMPLE_DEV_PM_OPS(mt6577_auxadc_pm_ops, + mt6577_auxadc_suspend, + mt6577_auxadc_resume); + static const struct of_device_id mt6577_auxadc_of_match[] = { { .compatible = "mediatek,mt2701-auxadc", }, + { .compatible = "mediatek,mt7622-auxadc", }, { .compatible = "mediatek,mt8173-auxadc", }, { } }; @@ -280,6 +316,7 @@ static struct platform_driver mt6577_auxadc_driver = { .driver = { .name = "mt6577-auxadc", .of_match_table = mt6577_auxadc_of_match, + .pm = &mt6577_auxadc_pm_ops, }, .probe = mt6577_auxadc_probe, .remove = mt6577_auxadc_remove, diff --git a/drivers/iio/adc/mxs-lradc-adc.c b/drivers/iio/adc/mxs-lradc-adc.c index 6888167ca1e6..d32b34638c2f 100644 --- a/drivers/iio/adc/mxs-lradc-adc.c +++ b/drivers/iio/adc/mxs-lradc-adc.c @@ -48,7 +48,7 @@ #define VREF_MV_BASE 1850 -const char *mx23_lradc_adc_irq_names[] = { +static const char *mx23_lradc_adc_irq_names[] = { "mxs-lradc-channel0", "mxs-lradc-channel1", "mxs-lradc-channel2", @@ -57,7 +57,7 @@ const char *mx23_lradc_adc_irq_names[] = { "mxs-lradc-channel5", }; -const char *mx28_lradc_adc_irq_names[] = { +static const char *mx28_lradc_adc_irq_names[] = { "mxs-lradc-thresh0", "mxs-lradc-thresh1", "mxs-lradc-channel0", @@ -344,20 +344,20 @@ static ssize_t mxs_lradc_adc_show_scale_avail(struct device *dev, IIO_DEVICE_ATTR(in_voltage##ch##_scale_available, 0444,\ mxs_lradc_adc_show_scale_avail, NULL, ch) -SHOW_SCALE_AVAILABLE_ATTR(0); -SHOW_SCALE_AVAILABLE_ATTR(1); -SHOW_SCALE_AVAILABLE_ATTR(2); -SHOW_SCALE_AVAILABLE_ATTR(3); -SHOW_SCALE_AVAILABLE_ATTR(4); -SHOW_SCALE_AVAILABLE_ATTR(5); -SHOW_SCALE_AVAILABLE_ATTR(6); -SHOW_SCALE_AVAILABLE_ATTR(7); -SHOW_SCALE_AVAILABLE_ATTR(10); -SHOW_SCALE_AVAILABLE_ATTR(11); -SHOW_SCALE_AVAILABLE_ATTR(12); -SHOW_SCALE_AVAILABLE_ATTR(13); -SHOW_SCALE_AVAILABLE_ATTR(14); -SHOW_SCALE_AVAILABLE_ATTR(15); +static SHOW_SCALE_AVAILABLE_ATTR(0); +static SHOW_SCALE_AVAILABLE_ATTR(1); +static SHOW_SCALE_AVAILABLE_ATTR(2); +static SHOW_SCALE_AVAILABLE_ATTR(3); +static SHOW_SCALE_AVAILABLE_ATTR(4); +static SHOW_SCALE_AVAILABLE_ATTR(5); +static SHOW_SCALE_AVAILABLE_ATTR(6); +static SHOW_SCALE_AVAILABLE_ATTR(7); +static SHOW_SCALE_AVAILABLE_ATTR(10); +static SHOW_SCALE_AVAILABLE_ATTR(11); +static SHOW_SCALE_AVAILABLE_ATTR(12); +static SHOW_SCALE_AVAILABLE_ATTR(13); +static SHOW_SCALE_AVAILABLE_ATTR(14); +static SHOW_SCALE_AVAILABLE_ATTR(15); static struct attribute *mxs_lradc_adc_attributes[] = { &iio_dev_attr_in_voltage0_scale_available.dev_attr.attr, diff --git a/drivers/iio/adc/rcar-gyroadc.c b/drivers/iio/adc/rcar-gyroadc.c index 018ed360e717..27a318164619 100644 --- a/drivers/iio/adc/rcar-gyroadc.c +++ b/drivers/iio/adc/rcar-gyroadc.c @@ -73,7 +73,7 @@ enum rcar_gyroadc_model { struct rcar_gyroadc { struct device *dev; void __iomem *regs; - struct clk *iclk; + struct clk *clk; struct regulator *vref[8]; unsigned int num_channels; enum rcar_gyroadc_model model; @@ -83,7 +83,7 @@ struct rcar_gyroadc { static void rcar_gyroadc_hw_init(struct rcar_gyroadc *priv) { - const unsigned long clk_mhz = clk_get_rate(priv->iclk) / 1000000; + const unsigned long clk_mhz = clk_get_rate(priv->clk) / 1000000; const unsigned long clk_mul = (priv->mode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) ? 10 : 5; unsigned long clk_len = clk_mhz * clk_mul; @@ -510,9 +510,9 @@ static int rcar_gyroadc_probe(struct platform_device *pdev) if (IS_ERR(priv->regs)) return PTR_ERR(priv->regs); - priv->iclk = devm_clk_get(dev, "if"); - if (IS_ERR(priv->iclk)) { - ret = PTR_ERR(priv->iclk); + priv->clk = devm_clk_get(dev, "fck"); + if (IS_ERR(priv->clk)) { + ret = PTR_ERR(priv->clk); if (ret != -EPROBE_DEFER) dev_err(dev, "Failed to get IF clock (ret=%i)\n", ret); return ret; @@ -536,7 +536,7 @@ static int rcar_gyroadc_probe(struct platform_device *pdev) indio_dev->info = &rcar_gyroadc_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; - ret = clk_prepare_enable(priv->iclk); + ret = clk_prepare_enable(priv->clk); if (ret) { dev_err(dev, "Could not prepare or enable the IF clock.\n"); goto err_clk_if_enable; @@ -565,7 +565,7 @@ err_iio_device_register: pm_runtime_put_sync(dev); pm_runtime_disable(dev); pm_runtime_set_suspended(dev); - clk_disable_unprepare(priv->iclk); + clk_disable_unprepare(priv->clk); err_clk_if_enable: rcar_gyroadc_deinit_supplies(indio_dev); @@ -584,7 +584,7 @@ static int rcar_gyroadc_remove(struct platform_device *pdev) pm_runtime_put_sync(dev); pm_runtime_disable(dev); pm_runtime_set_suspended(dev); - clk_disable_unprepare(priv->iclk); + clk_disable_unprepare(priv->clk); rcar_gyroadc_deinit_supplies(indio_dev); return 0; diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c index ae6d3324f518..5f612d694b33 100644 --- a/drivers/iio/adc/rockchip_saradc.c +++ b/drivers/iio/adc/rockchip_saradc.c @@ -224,6 +224,11 @@ static int rockchip_saradc_probe(struct platform_device *pdev) info = iio_priv(indio_dev); match = of_match_device(rockchip_saradc_match, &pdev->dev); + if (!match) { + dev_err(&pdev->dev, "failed to match device\n"); + return -ENODEV; + } + info->data = match->data; mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -235,7 +240,8 @@ static int rockchip_saradc_probe(struct platform_device *pdev) * 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"); + info->reset = devm_reset_control_get_exclusive(&pdev->dev, + "saradc-apb"); if (IS_ERR(info->reset)) { ret = PTR_ERR(info->reset); if (ret != -ENOENT) diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c index 22b7c9321e78..804198eb0eef 100644 --- a/drivers/iio/adc/stm32-adc-core.c +++ b/drivers/iio/adc/stm32-adc-core.c @@ -49,19 +49,66 @@ /* STM32 F4 maximum analog clock rate (from datasheet) */ #define STM32F4_ADC_MAX_CLK_RATE 36000000 +/* STM32H7 - common registers for all ADC instances */ +#define STM32H7_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00) +#define STM32H7_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x08) + +/* STM32H7_ADC_CSR - bit fields */ +#define STM32H7_EOC_SLV BIT(18) +#define STM32H7_EOC_MST BIT(2) + +/* STM32H7_ADC_CCR - bit fields */ +#define STM32H7_PRESC_SHIFT 18 +#define STM32H7_PRESC_MASK GENMASK(21, 18) +#define STM32H7_CKMODE_SHIFT 16 +#define STM32H7_CKMODE_MASK GENMASK(17, 16) + +/* STM32 H7 maximum analog clock rate (from datasheet) */ +#define STM32H7_ADC_MAX_CLK_RATE 36000000 + +/** + * stm32_adc_common_regs - stm32 common registers, compatible dependent data + * @csr: common status register offset + * @eoc1: adc1 end of conversion flag in @csr + * @eoc2: adc2 end of conversion flag in @csr + * @eoc3: adc3 end of conversion flag in @csr + */ +struct stm32_adc_common_regs { + u32 csr; + u32 eoc1_msk; + u32 eoc2_msk; + u32 eoc3_msk; +}; + +struct stm32_adc_priv; + +/** + * stm32_adc_priv_cfg - stm32 core compatible configuration data + * @regs: common registers for all instances + * @clk_sel: clock selection routine + */ +struct stm32_adc_priv_cfg { + const struct stm32_adc_common_regs *regs; + int (*clk_sel)(struct platform_device *, struct stm32_adc_priv *); +}; + /** * struct stm32_adc_priv - stm32 ADC core private data * @irq: irq for ADC block * @domain: irq domain reference * @aclk: clock reference for the analog circuitry + * @bclk: bus clock common for all ADCs, depends on part used * @vref: regulator reference + * @cfg: compatible configuration data * @common: common data for all ADC instances */ struct stm32_adc_priv { int irq; struct irq_domain *domain; struct clk *aclk; + struct clk *bclk; struct regulator *vref; + const struct stm32_adc_priv_cfg *cfg; struct stm32_adc_common common; }; @@ -85,25 +132,154 @@ static int stm32f4_adc_clk_sel(struct platform_device *pdev, u32 val; int i; + /* stm32f4 has one clk input for analog (mandatory), enforce it here */ + if (!priv->aclk) { + dev_err(&pdev->dev, "No 'adc' clock found\n"); + return -ENOENT; + } + rate = clk_get_rate(priv->aclk); for (i = 0; i < ARRAY_SIZE(stm32f4_pclk_div); i++) { if ((rate / stm32f4_pclk_div[i]) <= STM32F4_ADC_MAX_CLK_RATE) break; } - if (i >= ARRAY_SIZE(stm32f4_pclk_div)) + if (i >= ARRAY_SIZE(stm32f4_pclk_div)) { + dev_err(&pdev->dev, "adc clk selection failed\n"); return -EINVAL; + } + priv->common.rate = rate / stm32f4_pclk_div[i]; val = readl_relaxed(priv->common.base + STM32F4_ADC_CCR); val &= ~STM32F4_ADC_ADCPRE_MASK; val |= i << STM32F4_ADC_ADCPRE_SHIFT; writel_relaxed(val, priv->common.base + STM32F4_ADC_CCR); dev_dbg(&pdev->dev, "Using analog clock source at %ld kHz\n", - rate / (stm32f4_pclk_div[i] * 1000)); + priv->common.rate / 1000); return 0; } +/** + * struct stm32h7_adc_ck_spec - specification for stm32h7 adc clock + * @ckmode: ADC clock mode, Async or sync with prescaler. + * @presc: prescaler bitfield for async clock mode + * @div: prescaler division ratio + */ +struct stm32h7_adc_ck_spec { + u32 ckmode; + u32 presc; + int div; +}; + +static const struct stm32h7_adc_ck_spec stm32h7_adc_ckmodes_spec[] = { + /* 00: CK_ADC[1..3]: Asynchronous clock modes */ + { 0, 0, 1 }, + { 0, 1, 2 }, + { 0, 2, 4 }, + { 0, 3, 6 }, + { 0, 4, 8 }, + { 0, 5, 10 }, + { 0, 6, 12 }, + { 0, 7, 16 }, + { 0, 8, 32 }, + { 0, 9, 64 }, + { 0, 10, 128 }, + { 0, 11, 256 }, + /* HCLK used: Synchronous clock modes (1, 2 or 4 prescaler) */ + { 1, 0, 1 }, + { 2, 0, 2 }, + { 3, 0, 4 }, +}; + +static int stm32h7_adc_clk_sel(struct platform_device *pdev, + struct stm32_adc_priv *priv) +{ + u32 ckmode, presc, val; + unsigned long rate; + int i, div; + + /* stm32h7 bus clock is common for all ADC instances (mandatory) */ + if (!priv->bclk) { + dev_err(&pdev->dev, "No 'bus' clock found\n"); + return -ENOENT; + } + + /* + * stm32h7 can use either 'bus' or 'adc' clock for analog circuitry. + * So, choice is to have bus clock mandatory and adc clock optional. + * If optional 'adc' clock has been found, then try to use it first. + */ + if (priv->aclk) { + /* + * Asynchronous clock modes (e.g. ckmode == 0) + * From spec: PLL output musn't exceed max rate + */ + rate = clk_get_rate(priv->aclk); + + for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) { + ckmode = stm32h7_adc_ckmodes_spec[i].ckmode; + presc = stm32h7_adc_ckmodes_spec[i].presc; + div = stm32h7_adc_ckmodes_spec[i].div; + + if (ckmode) + continue; + + if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE) + goto out; + } + } + + /* Synchronous clock modes (e.g. ckmode is 1, 2 or 3) */ + rate = clk_get_rate(priv->bclk); + + for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) { + ckmode = stm32h7_adc_ckmodes_spec[i].ckmode; + presc = stm32h7_adc_ckmodes_spec[i].presc; + div = stm32h7_adc_ckmodes_spec[i].div; + + if (!ckmode) + continue; + + if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE) + goto out; + } + + dev_err(&pdev->dev, "adc clk selection failed\n"); + return -EINVAL; + +out: + /* rate used later by each ADC instance to control BOOST mode */ + priv->common.rate = rate / div; + + /* Set common clock mode and prescaler */ + val = readl_relaxed(priv->common.base + STM32H7_ADC_CCR); + val &= ~(STM32H7_CKMODE_MASK | STM32H7_PRESC_MASK); + val |= ckmode << STM32H7_CKMODE_SHIFT; + val |= presc << STM32H7_PRESC_SHIFT; + writel_relaxed(val, priv->common.base + STM32H7_ADC_CCR); + + dev_dbg(&pdev->dev, "Using %s clock/%d source at %ld kHz\n", + ckmode ? "bus" : "adc", div, priv->common.rate / 1000); + + return 0; +} + +/* STM32F4 common registers definitions */ +static const struct stm32_adc_common_regs stm32f4_adc_common_regs = { + .csr = STM32F4_ADC_CSR, + .eoc1_msk = STM32F4_EOC1, + .eoc2_msk = STM32F4_EOC2, + .eoc3_msk = STM32F4_EOC3, +}; + +/* STM32H7 common registers definitions */ +static const struct stm32_adc_common_regs stm32h7_adc_common_regs = { + .csr = STM32H7_ADC_CSR, + .eoc1_msk = STM32H7_EOC_MST, + .eoc2_msk = STM32H7_EOC_SLV, +}; + /* ADC common interrupt for all instances */ static void stm32_adc_irq_handler(struct irq_desc *desc) { @@ -112,15 +288,15 @@ static void stm32_adc_irq_handler(struct irq_desc *desc) u32 status; chained_irq_enter(chip, desc); - status = readl_relaxed(priv->common.base + STM32F4_ADC_CSR); + status = readl_relaxed(priv->common.base + priv->cfg->regs->csr); - if (status & STM32F4_EOC1) + if (status & priv->cfg->regs->eoc1_msk) generic_handle_irq(irq_find_mapping(priv->domain, 0)); - if (status & STM32F4_EOC2) + if (status & priv->cfg->regs->eoc2_msk) generic_handle_irq(irq_find_mapping(priv->domain, 1)); - if (status & STM32F4_EOC3) + if (status & priv->cfg->regs->eoc3_msk) generic_handle_irq(irq_find_mapping(priv->domain, 2)); chained_irq_exit(chip, desc); @@ -186,6 +362,7 @@ static void stm32_adc_irq_remove(struct platform_device *pdev, static int stm32_adc_probe(struct platform_device *pdev) { struct stm32_adc_priv *priv; + struct device *dev = &pdev->dev; struct device_node *np = pdev->dev.of_node; struct resource *res; int ret; @@ -197,6 +374,9 @@ static int stm32_adc_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; + priv->cfg = (const struct stm32_adc_priv_cfg *) + of_match_device(dev->driver->of_match_table, dev)->data; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->common.base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(priv->common.base)) @@ -227,25 +407,48 @@ static int stm32_adc_probe(struct platform_device *pdev) priv->aclk = devm_clk_get(&pdev->dev, "adc"); if (IS_ERR(priv->aclk)) { ret = PTR_ERR(priv->aclk); - dev_err(&pdev->dev, "Can't get 'adc' clock\n"); - goto err_regulator_disable; + if (ret == -ENOENT) { + priv->aclk = NULL; + } else { + dev_err(&pdev->dev, "Can't get 'adc' clock\n"); + goto err_regulator_disable; + } } - ret = clk_prepare_enable(priv->aclk); - if (ret < 0) { - dev_err(&pdev->dev, "adc clk enable failed\n"); - goto err_regulator_disable; + if (priv->aclk) { + ret = clk_prepare_enable(priv->aclk); + if (ret < 0) { + dev_err(&pdev->dev, "adc clk enable failed\n"); + goto err_regulator_disable; + } } - ret = stm32f4_adc_clk_sel(pdev, priv); - if (ret < 0) { - dev_err(&pdev->dev, "adc clk selection failed\n"); - goto err_clk_disable; + priv->bclk = devm_clk_get(&pdev->dev, "bus"); + if (IS_ERR(priv->bclk)) { + ret = PTR_ERR(priv->bclk); + if (ret == -ENOENT) { + priv->bclk = NULL; + } else { + dev_err(&pdev->dev, "Can't get 'bus' clock\n"); + goto err_aclk_disable; + } + } + + if (priv->bclk) { + ret = clk_prepare_enable(priv->bclk); + if (ret < 0) { + dev_err(&pdev->dev, "adc clk enable failed\n"); + goto err_aclk_disable; + } } + ret = priv->cfg->clk_sel(pdev, priv); + if (ret < 0) + goto err_bclk_disable; + ret = stm32_adc_irq_probe(pdev, priv); if (ret < 0) - goto err_clk_disable; + goto err_bclk_disable; platform_set_drvdata(pdev, &priv->common); @@ -260,8 +463,13 @@ static int stm32_adc_probe(struct platform_device *pdev) err_irq_remove: stm32_adc_irq_remove(pdev, priv); -err_clk_disable: - clk_disable_unprepare(priv->aclk); +err_bclk_disable: + if (priv->bclk) + clk_disable_unprepare(priv->bclk); + +err_aclk_disable: + if (priv->aclk) + clk_disable_unprepare(priv->aclk); err_regulator_disable: regulator_disable(priv->vref); @@ -276,15 +484,34 @@ static int stm32_adc_remove(struct platform_device *pdev) of_platform_depopulate(&pdev->dev); stm32_adc_irq_remove(pdev, priv); - clk_disable_unprepare(priv->aclk); + if (priv->bclk) + clk_disable_unprepare(priv->bclk); + if (priv->aclk) + clk_disable_unprepare(priv->aclk); regulator_disable(priv->vref); return 0; } +static const struct stm32_adc_priv_cfg stm32f4_adc_priv_cfg = { + .regs = &stm32f4_adc_common_regs, + .clk_sel = stm32f4_adc_clk_sel, +}; + +static const struct stm32_adc_priv_cfg stm32h7_adc_priv_cfg = { + .regs = &stm32h7_adc_common_regs, + .clk_sel = stm32h7_adc_clk_sel, +}; + static const struct of_device_id stm32_adc_of_match[] = { - { .compatible = "st,stm32f4-adc-core" }, - {}, + { + .compatible = "st,stm32f4-adc-core", + .data = (void *)&stm32f4_adc_priv_cfg + }, { + .compatible = "st,stm32h7-adc-core", + .data = (void *)&stm32h7_adc_priv_cfg + }, { + }, }; MODULE_DEVICE_TABLE(of, stm32_adc_of_match); diff --git a/drivers/iio/adc/stm32-adc-core.h b/drivers/iio/adc/stm32-adc-core.h index 2ec7abbfbcaa..250ee958a669 100644 --- a/drivers/iio/adc/stm32-adc-core.h +++ b/drivers/iio/adc/stm32-adc-core.h @@ -43,11 +43,13 @@ * struct stm32_adc_common - stm32 ADC driver common data (for all instances) * @base: control registers base cpu addr * @phys_base: control registers base physical addr + * @rate: clock rate used for analog circuitry * @vref_mv: vref voltage (mv) */ struct stm32_adc_common { void __iomem *base; phys_addr_t phys_base; + unsigned long rate; int vref_mv; }; diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index c28e7ff80e11..4df32cf1650e 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -25,15 +25,18 @@ #include <linux/dmaengine.h> #include <linux/iio/iio.h> #include <linux/iio/buffer.h> +#include <linux/iio/timer/stm32-lptim-trigger.h> #include <linux/iio/timer/stm32-timer-trigger.h> #include <linux/iio/trigger.h> #include <linux/iio/trigger_consumer.h> #include <linux/iio/triggered_buffer.h> #include <linux/interrupt.h> #include <linux/io.h> +#include <linux/iopoll.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/of.h> +#include <linux/of_device.h> #include "stm32-adc-core.h" @@ -76,7 +79,82 @@ #define STM32F4_DMA BIT(8) #define STM32F4_ADON BIT(0) +/* STM32H7 - Registers for each ADC instance */ +#define STM32H7_ADC_ISR 0x00 +#define STM32H7_ADC_IER 0x04 +#define STM32H7_ADC_CR 0x08 +#define STM32H7_ADC_CFGR 0x0C +#define STM32H7_ADC_SMPR1 0x14 +#define STM32H7_ADC_SMPR2 0x18 +#define STM32H7_ADC_PCSEL 0x1C +#define STM32H7_ADC_SQR1 0x30 +#define STM32H7_ADC_SQR2 0x34 +#define STM32H7_ADC_SQR3 0x38 +#define STM32H7_ADC_SQR4 0x3C +#define STM32H7_ADC_DR 0x40 +#define STM32H7_ADC_CALFACT 0xC4 +#define STM32H7_ADC_CALFACT2 0xC8 + +/* STM32H7_ADC_ISR - bit fields */ +#define STM32H7_EOC BIT(2) +#define STM32H7_ADRDY BIT(0) + +/* STM32H7_ADC_IER - bit fields */ +#define STM32H7_EOCIE STM32H7_EOC + +/* STM32H7_ADC_CR - bit fields */ +#define STM32H7_ADCAL BIT(31) +#define STM32H7_ADCALDIF BIT(30) +#define STM32H7_DEEPPWD BIT(29) +#define STM32H7_ADVREGEN BIT(28) +#define STM32H7_LINCALRDYW6 BIT(27) +#define STM32H7_LINCALRDYW5 BIT(26) +#define STM32H7_LINCALRDYW4 BIT(25) +#define STM32H7_LINCALRDYW3 BIT(24) +#define STM32H7_LINCALRDYW2 BIT(23) +#define STM32H7_LINCALRDYW1 BIT(22) +#define STM32H7_ADCALLIN BIT(16) +#define STM32H7_BOOST BIT(8) +#define STM32H7_ADSTP BIT(4) +#define STM32H7_ADSTART BIT(2) +#define STM32H7_ADDIS BIT(1) +#define STM32H7_ADEN BIT(0) + +/* STM32H7_ADC_CFGR bit fields */ +#define STM32H7_EXTEN_SHIFT 10 +#define STM32H7_EXTEN_MASK GENMASK(11, 10) +#define STM32H7_EXTSEL_SHIFT 5 +#define STM32H7_EXTSEL_MASK GENMASK(9, 5) +#define STM32H7_RES_SHIFT 2 +#define STM32H7_RES_MASK GENMASK(4, 2) +#define STM32H7_DMNGT_SHIFT 0 +#define STM32H7_DMNGT_MASK GENMASK(1, 0) + +enum stm32h7_adc_dmngt { + STM32H7_DMNGT_DR_ONLY, /* Regular data in DR only */ + STM32H7_DMNGT_DMA_ONESHOT, /* DMA one shot mode */ + STM32H7_DMNGT_DFSDM, /* DFSDM mode */ + STM32H7_DMNGT_DMA_CIRC, /* DMA circular mode */ +}; + +/* STM32H7_ADC_CALFACT - bit fields */ +#define STM32H7_CALFACT_D_SHIFT 16 +#define STM32H7_CALFACT_D_MASK GENMASK(26, 16) +#define STM32H7_CALFACT_S_SHIFT 0 +#define STM32H7_CALFACT_S_MASK GENMASK(10, 0) + +/* STM32H7_ADC_CALFACT2 - bit fields */ +#define STM32H7_LINCALFACT_SHIFT 0 +#define STM32H7_LINCALFACT_MASK GENMASK(29, 0) + +/* Number of linear calibration shadow registers / LINCALRDYW control bits */ +#define STM32H7_LINCALFACT_NUM 6 + +/* BOOST bit must be set on STM32H7 when ADC clock is above 20MHz */ +#define STM32H7_BOOST_CLKRATE 20000000UL + #define STM32_ADC_MAX_SQ 16 /* SQ1..SQ16 */ +#define STM32_ADC_MAX_SMP 7 /* SMPx range is [0..7] */ #define STM32_ADC_TIMEOUT_US 100000 #define STM32_ADC_TIMEOUT (msecs_to_jiffies(STM32_ADC_TIMEOUT_US / 1000)) @@ -108,6 +186,11 @@ enum stm32_adc_extsel { STM32_EXT13, STM32_EXT14, STM32_EXT15, + STM32_EXT16, + STM32_EXT17, + STM32_EXT18, + STM32_EXT19, + STM32_EXT20, }; /** @@ -121,6 +204,18 @@ struct stm32_adc_trig_info { }; /** + * struct stm32_adc_calib - optional adc calibration data + * @calfact_s: Calibration offset for single ended channels + * @calfact_d: Calibration offset in differential + * @lincalfact: Linearity calibration factor + */ +struct stm32_adc_calib { + u32 calfact_s; + u32 calfact_d; + u32 lincalfact[STM32H7_LINCALFACT_NUM]; +}; + +/** * stm32_adc_regs - stm32 ADC misc registers & bitfield desc * @reg: register offset * @mask: bitfield mask @@ -133,9 +228,62 @@ struct stm32_adc_regs { }; /** + * stm32_adc_regspec - stm32 registers definition, compatible dependent data + * @dr: data register offset + * @ier_eoc: interrupt enable register & eocie bitfield + * @isr_eoc: interrupt status register & eoc bitfield + * @sqr: reference to sequence registers array + * @exten: trigger control register & bitfield + * @extsel: trigger selection register & bitfield + * @res: resolution selection register & bitfield + * @smpr: smpr1 & smpr2 registers offset array + * @smp_bits: smpr1 & smpr2 index and bitfields + */ +struct stm32_adc_regspec { + const u32 dr; + const struct stm32_adc_regs ier_eoc; + const struct stm32_adc_regs isr_eoc; + const struct stm32_adc_regs *sqr; + const struct stm32_adc_regs exten; + const struct stm32_adc_regs extsel; + const struct stm32_adc_regs res; + const u32 smpr[2]; + const struct stm32_adc_regs *smp_bits; +}; + +struct stm32_adc; + +/** + * stm32_adc_cfg - stm32 compatible configuration data + * @regs: registers descriptions + * @adc_info: per instance input channels definitions + * @trigs: external trigger sources + * @clk_required: clock is required + * @selfcalib: optional routine for self-calibration + * @prepare: optional prepare routine (power-up, enable) + * @start_conv: routine to start conversions + * @stop_conv: routine to stop conversions + * @unprepare: optional unprepare routine (disable, power-down) + * @smp_cycles: programmable sampling time (ADC clock cycles) + */ +struct stm32_adc_cfg { + const struct stm32_adc_regspec *regs; + const struct stm32_adc_info *adc_info; + struct stm32_adc_trig_info *trigs; + bool clk_required; + int (*selfcalib)(struct stm32_adc *); + int (*prepare)(struct stm32_adc *); + void (*start_conv)(struct stm32_adc *, bool dma); + void (*stop_conv)(struct stm32_adc *); + void (*unprepare)(struct stm32_adc *); + const unsigned int *smp_cycles; +}; + +/** * struct stm32_adc - private data of each ADC IIO instance * @common: reference to ADC block common data * @offset: ADC instance register offset in ADC block + * @cfg: compatible configuration data * @completion: end of single conversion completion * @buffer: data buffer * @clk: clock for this adc instance @@ -149,10 +297,14 @@ struct stm32_adc_regs { * @rx_buf: dma rx buffer cpu address * @rx_dma_buf: dma rx buffer bus address * @rx_buf_sz: dma rx buffer size + * @pcsel bitmask to preselect channels on some devices + * @smpr_val: sampling time settings (e.g. smpr1 / smpr2) + * @cal: optional calibration data on some devices */ struct stm32_adc { struct stm32_adc_common *common; u32 offset; + const struct stm32_adc_cfg *cfg; struct completion completion; u16 buffer[STM32_ADC_MAX_SQ]; struct clk *clk; @@ -166,6 +318,9 @@ struct stm32_adc { u8 *rx_buf; dma_addr_t rx_dma_buf; unsigned int rx_buf_sz; + u32 pcsel; + u32 smpr_val[2]; + struct stm32_adc_calib cal; }; /** @@ -180,8 +335,26 @@ struct stm32_adc_chan_spec { const char *name; }; -/* Input definitions common for all STM32F4 instances */ -static const struct stm32_adc_chan_spec stm32f4_adc123_channels[] = { +/** + * struct stm32_adc_info - stm32 ADC, per instance config data + * @channels: Reference to stm32 channels spec + * @max_channels: Number of channels + * @resolutions: available resolutions + * @num_res: number of available resolutions + */ +struct stm32_adc_info { + const struct stm32_adc_chan_spec *channels; + int max_channels; + const unsigned int *resolutions; + const unsigned int num_res; +}; + +/* + * Input definitions common for all instances: + * stm32f4 can have up to 16 channels + * stm32h7 can have up to 20 channels + */ +static const struct stm32_adc_chan_spec stm32_adc_channels[] = { { IIO_VOLTAGE, 0, "in0" }, { IIO_VOLTAGE, 1, "in1" }, { IIO_VOLTAGE, 2, "in2" }, @@ -198,6 +371,10 @@ static const struct stm32_adc_chan_spec stm32f4_adc123_channels[] = { { IIO_VOLTAGE, 13, "in13" }, { IIO_VOLTAGE, 14, "in14" }, { IIO_VOLTAGE, 15, "in15" }, + { IIO_VOLTAGE, 16, "in16" }, + { IIO_VOLTAGE, 17, "in17" }, + { IIO_VOLTAGE, 18, "in18" }, + { IIO_VOLTAGE, 19, "in19" }, }; static const unsigned int stm32f4_adc_resolutions[] = { @@ -205,6 +382,25 @@ static const unsigned int stm32f4_adc_resolutions[] = { 12, 10, 8, 6, }; +static const struct stm32_adc_info stm32f4_adc_info = { + .channels = stm32_adc_channels, + .max_channels = 16, + .resolutions = stm32f4_adc_resolutions, + .num_res = ARRAY_SIZE(stm32f4_adc_resolutions), +}; + +static const unsigned int stm32h7_adc_resolutions[] = { + /* sorted values so the index matches RES[2:0] in STM32H7_ADC_CFGR */ + 16, 14, 12, 10, 8, +}; + +static const struct stm32_adc_info stm32h7_adc_info = { + .channels = stm32_adc_channels, + .max_channels = 20, + .resolutions = stm32h7_adc_resolutions, + .num_res = ARRAY_SIZE(stm32h7_adc_resolutions), +}; + /** * stm32f4_sq - describe regular sequence registers * - L: sequence len (register & bit field) @@ -253,6 +449,143 @@ static struct stm32_adc_trig_info stm32f4_adc_trigs[] = { }; /** + * stm32f4_smp_bits[] - describe sampling time register index & bit fields + * Sorted so it can be indexed by channel number. + */ +static const struct stm32_adc_regs stm32f4_smp_bits[] = { + /* STM32F4_ADC_SMPR2: smpr[] index, mask, shift for SMP0 to SMP9 */ + { 1, GENMASK(2, 0), 0 }, + { 1, GENMASK(5, 3), 3 }, + { 1, GENMASK(8, 6), 6 }, + { 1, GENMASK(11, 9), 9 }, + { 1, GENMASK(14, 12), 12 }, + { 1, GENMASK(17, 15), 15 }, + { 1, GENMASK(20, 18), 18 }, + { 1, GENMASK(23, 21), 21 }, + { 1, GENMASK(26, 24), 24 }, + { 1, GENMASK(29, 27), 27 }, + /* STM32F4_ADC_SMPR1, smpr[] index, mask, shift for SMP10 to SMP18 */ + { 0, GENMASK(2, 0), 0 }, + { 0, GENMASK(5, 3), 3 }, + { 0, GENMASK(8, 6), 6 }, + { 0, GENMASK(11, 9), 9 }, + { 0, GENMASK(14, 12), 12 }, + { 0, GENMASK(17, 15), 15 }, + { 0, GENMASK(20, 18), 18 }, + { 0, GENMASK(23, 21), 21 }, + { 0, GENMASK(26, 24), 24 }, +}; + +/* STM32F4 programmable sampling time (ADC clock cycles) */ +static const unsigned int stm32f4_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = { + 3, 15, 28, 56, 84, 112, 144, 480, +}; + +static const struct stm32_adc_regspec stm32f4_adc_regspec = { + .dr = STM32F4_ADC_DR, + .ier_eoc = { STM32F4_ADC_CR1, STM32F4_EOCIE }, + .isr_eoc = { STM32F4_ADC_SR, STM32F4_EOC }, + .sqr = stm32f4_sq, + .exten = { STM32F4_ADC_CR2, STM32F4_EXTEN_MASK, STM32F4_EXTEN_SHIFT }, + .extsel = { STM32F4_ADC_CR2, STM32F4_EXTSEL_MASK, + STM32F4_EXTSEL_SHIFT }, + .res = { STM32F4_ADC_CR1, STM32F4_RES_MASK, STM32F4_RES_SHIFT }, + .smpr = { STM32F4_ADC_SMPR1, STM32F4_ADC_SMPR2 }, + .smp_bits = stm32f4_smp_bits, +}; + +static const struct stm32_adc_regs stm32h7_sq[STM32_ADC_MAX_SQ + 1] = { + /* L: len bit field description to be kept as first element */ + { STM32H7_ADC_SQR1, GENMASK(3, 0), 0 }, + /* SQ1..SQ16 registers & bit fields (reg, mask, shift) */ + { STM32H7_ADC_SQR1, GENMASK(10, 6), 6 }, + { STM32H7_ADC_SQR1, GENMASK(16, 12), 12 }, + { STM32H7_ADC_SQR1, GENMASK(22, 18), 18 }, + { STM32H7_ADC_SQR1, GENMASK(28, 24), 24 }, + { STM32H7_ADC_SQR2, GENMASK(4, 0), 0 }, + { STM32H7_ADC_SQR2, GENMASK(10, 6), 6 }, + { STM32H7_ADC_SQR2, GENMASK(16, 12), 12 }, + { STM32H7_ADC_SQR2, GENMASK(22, 18), 18 }, + { STM32H7_ADC_SQR2, GENMASK(28, 24), 24 }, + { STM32H7_ADC_SQR3, GENMASK(4, 0), 0 }, + { STM32H7_ADC_SQR3, GENMASK(10, 6), 6 }, + { STM32H7_ADC_SQR3, GENMASK(16, 12), 12 }, + { STM32H7_ADC_SQR3, GENMASK(22, 18), 18 }, + { STM32H7_ADC_SQR3, GENMASK(28, 24), 24 }, + { STM32H7_ADC_SQR4, GENMASK(4, 0), 0 }, + { STM32H7_ADC_SQR4, GENMASK(10, 6), 6 }, +}; + +/* STM32H7 external trigger sources for all instances */ +static struct stm32_adc_trig_info stm32h7_adc_trigs[] = { + { TIM1_CH1, STM32_EXT0 }, + { TIM1_CH2, STM32_EXT1 }, + { TIM1_CH3, STM32_EXT2 }, + { TIM2_CH2, STM32_EXT3 }, + { TIM3_TRGO, STM32_EXT4 }, + { TIM4_CH4, STM32_EXT5 }, + { TIM8_TRGO, STM32_EXT7 }, + { TIM8_TRGO2, STM32_EXT8 }, + { TIM1_TRGO, STM32_EXT9 }, + { TIM1_TRGO2, STM32_EXT10 }, + { TIM2_TRGO, STM32_EXT11 }, + { TIM4_TRGO, STM32_EXT12 }, + { TIM6_TRGO, STM32_EXT13 }, + { TIM3_CH4, STM32_EXT15 }, + { LPTIM1_OUT, STM32_EXT18 }, + { LPTIM2_OUT, STM32_EXT19 }, + { LPTIM3_OUT, STM32_EXT20 }, + {}, +}; + +/** + * stm32h7_smp_bits - describe sampling time register index & bit fields + * Sorted so it can be indexed by channel number. + */ +static const struct stm32_adc_regs stm32h7_smp_bits[] = { + /* STM32H7_ADC_SMPR1, smpr[] index, mask, shift for SMP0 to SMP9 */ + { 0, GENMASK(2, 0), 0 }, + { 0, GENMASK(5, 3), 3 }, + { 0, GENMASK(8, 6), 6 }, + { 0, GENMASK(11, 9), 9 }, + { 0, GENMASK(14, 12), 12 }, + { 0, GENMASK(17, 15), 15 }, + { 0, GENMASK(20, 18), 18 }, + { 0, GENMASK(23, 21), 21 }, + { 0, GENMASK(26, 24), 24 }, + { 0, GENMASK(29, 27), 27 }, + /* STM32H7_ADC_SMPR2, smpr[] index, mask, shift for SMP10 to SMP19 */ + { 1, GENMASK(2, 0), 0 }, + { 1, GENMASK(5, 3), 3 }, + { 1, GENMASK(8, 6), 6 }, + { 1, GENMASK(11, 9), 9 }, + { 1, GENMASK(14, 12), 12 }, + { 1, GENMASK(17, 15), 15 }, + { 1, GENMASK(20, 18), 18 }, + { 1, GENMASK(23, 21), 21 }, + { 1, GENMASK(26, 24), 24 }, + { 1, GENMASK(29, 27), 27 }, +}; + +/* STM32H7 programmable sampling time (ADC clock cycles, rounded down) */ +static const unsigned int stm32h7_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = { + 1, 2, 8, 16, 32, 64, 387, 810, +}; + +static const struct stm32_adc_regspec stm32h7_adc_regspec = { + .dr = STM32H7_ADC_DR, + .ier_eoc = { STM32H7_ADC_IER, STM32H7_EOCIE }, + .isr_eoc = { STM32H7_ADC_ISR, STM32H7_EOC }, + .sqr = stm32h7_sq, + .exten = { STM32H7_ADC_CFGR, STM32H7_EXTEN_MASK, STM32H7_EXTEN_SHIFT }, + .extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK, + STM32H7_EXTSEL_SHIFT }, + .res = { STM32H7_ADC_CFGR, STM32H7_RES_MASK, STM32H7_RES_SHIFT }, + .smpr = { STM32H7_ADC_SMPR1, STM32H7_ADC_SMPR2 }, + .smp_bits = stm32h7_smp_bits, +}; + +/** * STM32 ADC registers access routines * @adc: stm32 adc instance * @reg: reg offset in adc instance @@ -265,6 +598,12 @@ static u32 stm32_adc_readl(struct stm32_adc *adc, u32 reg) return readl_relaxed(adc->common->base + adc->offset + reg); } +#define stm32_adc_readl_addr(addr) stm32_adc_readl(adc, addr) + +#define stm32_adc_readl_poll_timeout(reg, val, cond, sleep_us, timeout_us) \ + readx_poll_timeout(stm32_adc_readl_addr, reg, val, \ + cond, sleep_us, timeout_us) + static u16 stm32_adc_readw(struct stm32_adc *adc, u32 reg) { return readw_relaxed(adc->common->base + adc->offset + reg); @@ -299,7 +638,8 @@ static void stm32_adc_clr_bits(struct stm32_adc *adc, u32 reg, u32 bits) */ static void stm32_adc_conv_irq_enable(struct stm32_adc *adc) { - stm32_adc_set_bits(adc, STM32F4_ADC_CR1, STM32F4_EOCIE); + stm32_adc_set_bits(adc, adc->cfg->regs->ier_eoc.reg, + adc->cfg->regs->ier_eoc.mask); }; /** @@ -308,19 +648,22 @@ static void stm32_adc_conv_irq_enable(struct stm32_adc *adc) */ static void stm32_adc_conv_irq_disable(struct stm32_adc *adc) { - stm32_adc_clr_bits(adc, STM32F4_ADC_CR1, STM32F4_EOCIE); + stm32_adc_clr_bits(adc, adc->cfg->regs->ier_eoc.reg, + adc->cfg->regs->ier_eoc.mask); } static void stm32_adc_set_res(struct stm32_adc *adc) { - u32 val = stm32_adc_readl(adc, STM32F4_ADC_CR1); + const struct stm32_adc_regs *res = &adc->cfg->regs->res; + u32 val; - val = (val & ~STM32F4_RES_MASK) | (adc->res << STM32F4_RES_SHIFT); - stm32_adc_writel(adc, STM32F4_ADC_CR1, val); + val = stm32_adc_readl(adc, res->reg); + val = (val & ~res->mask) | (adc->res << res->shift); + stm32_adc_writel(adc, res->reg, val); } /** - * stm32_adc_start_conv() - Start conversions for regular channels. + * stm32f4_adc_start_conv() - Start conversions for regular channels. * @adc: stm32 adc instance * @dma: use dma to transfer conversion result * @@ -329,7 +672,7 @@ static void stm32_adc_set_res(struct stm32_adc *adc) * conversions, in IIO buffer modes. Otherwise, use ADC interrupt with direct * DR read instead (e.g. read_raw, or triggered buffer mode without DMA). */ -static void stm32_adc_start_conv(struct stm32_adc *adc, bool dma) +static void stm32f4_adc_start_conv(struct stm32_adc *adc, bool dma) { stm32_adc_set_bits(adc, STM32F4_ADC_CR1, STM32F4_SCAN); @@ -347,7 +690,7 @@ static void stm32_adc_start_conv(struct stm32_adc *adc, bool dma) stm32_adc_set_bits(adc, STM32F4_ADC_CR2, STM32F4_SWSTART); } -static void stm32_adc_stop_conv(struct stm32_adc *adc) +static void stm32f4_adc_stop_conv(struct stm32_adc *adc) { stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_EXTEN_MASK); stm32_adc_clr_bits(adc, STM32F4_ADC_SR, STM32F4_STRT); @@ -357,12 +700,331 @@ static void stm32_adc_stop_conv(struct stm32_adc *adc) STM32F4_ADON | STM32F4_DMA | STM32F4_DDS); } +static void stm32h7_adc_start_conv(struct stm32_adc *adc, bool dma) +{ + enum stm32h7_adc_dmngt dmngt; + unsigned long flags; + u32 val; + + if (dma) + dmngt = STM32H7_DMNGT_DMA_CIRC; + else + dmngt = STM32H7_DMNGT_DR_ONLY; + + spin_lock_irqsave(&adc->lock, flags); + val = stm32_adc_readl(adc, STM32H7_ADC_CFGR); + val = (val & ~STM32H7_DMNGT_MASK) | (dmngt << STM32H7_DMNGT_SHIFT); + stm32_adc_writel(adc, STM32H7_ADC_CFGR, val); + spin_unlock_irqrestore(&adc->lock, flags); + + stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADSTART); +} + +static void stm32h7_adc_stop_conv(struct stm32_adc *adc) +{ + struct iio_dev *indio_dev = iio_priv_to_dev(adc); + int ret; + u32 val; + + stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADSTP); + + ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val, + !(val & (STM32H7_ADSTART)), + 100, STM32_ADC_TIMEOUT_US); + if (ret) + dev_warn(&indio_dev->dev, "stop failed\n"); + + stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR, STM32H7_DMNGT_MASK); +} + +static void stm32h7_adc_exit_pwr_down(struct stm32_adc *adc) +{ + /* Exit deep power down, then enable ADC voltage regulator */ + stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD); + stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADVREGEN); + + if (adc->common->rate > STM32H7_BOOST_CLKRATE) + stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_BOOST); + + /* Wait for startup time */ + usleep_range(10, 20); +} + +static void stm32h7_adc_enter_pwr_down(struct stm32_adc *adc) +{ + stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_BOOST); + + /* Setting DEEPPWD disables ADC vreg and clears ADVREGEN */ + stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD); +} + +static int stm32h7_adc_enable(struct stm32_adc *adc) +{ + struct iio_dev *indio_dev = iio_priv_to_dev(adc); + int ret; + u32 val; + + /* Clear ADRDY by writing one, then enable ADC */ + stm32_adc_set_bits(adc, STM32H7_ADC_ISR, STM32H7_ADRDY); + stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADEN); + + /* Poll for ADRDY to be set (after adc startup time) */ + ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_ISR, val, + val & STM32H7_ADRDY, + 100, STM32_ADC_TIMEOUT_US); + if (ret) { + stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_ADEN); + dev_err(&indio_dev->dev, "Failed to enable ADC\n"); + } + + return ret; +} + +static void stm32h7_adc_disable(struct stm32_adc *adc) +{ + struct iio_dev *indio_dev = iio_priv_to_dev(adc); + int ret; + u32 val; + + /* Disable ADC and wait until it's effectively disabled */ + stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADDIS); + ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val, + !(val & STM32H7_ADEN), 100, + STM32_ADC_TIMEOUT_US); + if (ret) + dev_warn(&indio_dev->dev, "Failed to disable\n"); +} + +/** + * stm32h7_adc_read_selfcalib() - read calibration shadow regs, save result + * @adc: stm32 adc instance + */ +static int stm32h7_adc_read_selfcalib(struct stm32_adc *adc) +{ + struct iio_dev *indio_dev = iio_priv_to_dev(adc); + int i, ret; + u32 lincalrdyw_mask, val; + + /* Enable adc so LINCALRDYW1..6 bits are writable */ + ret = stm32h7_adc_enable(adc); + if (ret) + return ret; + + /* Read linearity calibration */ + lincalrdyw_mask = STM32H7_LINCALRDYW6; + for (i = STM32H7_LINCALFACT_NUM - 1; i >= 0; i--) { + /* Clear STM32H7_LINCALRDYW[6..1]: transfer calib to CALFACT2 */ + stm32_adc_clr_bits(adc, STM32H7_ADC_CR, lincalrdyw_mask); + + /* Poll: wait calib data to be ready in CALFACT2 register */ + ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val, + !(val & lincalrdyw_mask), + 100, STM32_ADC_TIMEOUT_US); + if (ret) { + dev_err(&indio_dev->dev, "Failed to read calfact\n"); + goto disable; + } + + val = stm32_adc_readl(adc, STM32H7_ADC_CALFACT2); + adc->cal.lincalfact[i] = (val & STM32H7_LINCALFACT_MASK); + adc->cal.lincalfact[i] >>= STM32H7_LINCALFACT_SHIFT; + + lincalrdyw_mask >>= 1; + } + + /* Read offset calibration */ + val = stm32_adc_readl(adc, STM32H7_ADC_CALFACT); + adc->cal.calfact_s = (val & STM32H7_CALFACT_S_MASK); + adc->cal.calfact_s >>= STM32H7_CALFACT_S_SHIFT; + adc->cal.calfact_d = (val & STM32H7_CALFACT_D_MASK); + adc->cal.calfact_d >>= STM32H7_CALFACT_D_SHIFT; + +disable: + stm32h7_adc_disable(adc); + + return ret; +} + +/** + * stm32h7_adc_restore_selfcalib() - Restore saved self-calibration result + * @adc: stm32 adc instance + * Note: ADC must be enabled, with no on-going conversions. + */ +static int stm32h7_adc_restore_selfcalib(struct stm32_adc *adc) +{ + struct iio_dev *indio_dev = iio_priv_to_dev(adc); + int i, ret; + u32 lincalrdyw_mask, val; + + val = (adc->cal.calfact_s << STM32H7_CALFACT_S_SHIFT) | + (adc->cal.calfact_d << STM32H7_CALFACT_D_SHIFT); + stm32_adc_writel(adc, STM32H7_ADC_CALFACT, val); + + lincalrdyw_mask = STM32H7_LINCALRDYW6; + for (i = STM32H7_LINCALFACT_NUM - 1; i >= 0; i--) { + /* + * Write saved calibration data to shadow registers: + * Write CALFACT2, and set LINCALRDYW[6..1] bit to trigger + * data write. Then poll to wait for complete transfer. + */ + val = adc->cal.lincalfact[i] << STM32H7_LINCALFACT_SHIFT; + stm32_adc_writel(adc, STM32H7_ADC_CALFACT2, val); + stm32_adc_set_bits(adc, STM32H7_ADC_CR, lincalrdyw_mask); + ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val, + val & lincalrdyw_mask, + 100, STM32_ADC_TIMEOUT_US); + if (ret) { + dev_err(&indio_dev->dev, "Failed to write calfact\n"); + return ret; + } + + /* + * Read back calibration data, has two effects: + * - It ensures bits LINCALRDYW[6..1] are kept cleared + * for next time calibration needs to be restored. + * - BTW, bit clear triggers a read, then check data has been + * correctly written. + */ + stm32_adc_clr_bits(adc, STM32H7_ADC_CR, lincalrdyw_mask); + ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val, + !(val & lincalrdyw_mask), + 100, STM32_ADC_TIMEOUT_US); + if (ret) { + dev_err(&indio_dev->dev, "Failed to read calfact\n"); + return ret; + } + val = stm32_adc_readl(adc, STM32H7_ADC_CALFACT2); + if (val != adc->cal.lincalfact[i] << STM32H7_LINCALFACT_SHIFT) { + dev_err(&indio_dev->dev, "calfact not consistent\n"); + return -EIO; + } + + lincalrdyw_mask >>= 1; + } + + return 0; +} + +/** + * Fixed timeout value for ADC calibration. + * worst cases: + * - low clock frequency + * - maximum prescalers + * Calibration requires: + * - 131,072 ADC clock cycle for the linear calibration + * - 20 ADC clock cycle for the offset calibration + * + * Set to 100ms for now + */ +#define STM32H7_ADC_CALIB_TIMEOUT_US 100000 + +/** + * stm32h7_adc_selfcalib() - Procedure to calibrate ADC (from power down) + * @adc: stm32 adc instance + * Exit from power down, calibrate ADC, then return to power down. + */ +static int stm32h7_adc_selfcalib(struct stm32_adc *adc) +{ + struct iio_dev *indio_dev = iio_priv_to_dev(adc); + int ret; + u32 val; + + stm32h7_adc_exit_pwr_down(adc); + + /* + * Select calibration mode: + * - Offset calibration for single ended inputs + * - No linearity calibration (do it later, before reading it) + */ + stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_ADCALDIF); + stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_ADCALLIN); + + /* Start calibration, then wait for completion */ + stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADCAL); + ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val, + !(val & STM32H7_ADCAL), 100, + STM32H7_ADC_CALIB_TIMEOUT_US); + if (ret) { + dev_err(&indio_dev->dev, "calibration failed\n"); + goto pwr_dwn; + } + + /* + * Select calibration mode, then start calibration: + * - Offset calibration for differential input + * - Linearity calibration (needs to be done only once for single/diff) + * will run simultaneously with offset calibration. + */ + stm32_adc_set_bits(adc, STM32H7_ADC_CR, + STM32H7_ADCALDIF | STM32H7_ADCALLIN); + stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADCAL); + ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val, + !(val & STM32H7_ADCAL), 100, + STM32H7_ADC_CALIB_TIMEOUT_US); + if (ret) { + dev_err(&indio_dev->dev, "calibration failed\n"); + goto pwr_dwn; + } + + stm32_adc_clr_bits(adc, STM32H7_ADC_CR, + STM32H7_ADCALDIF | STM32H7_ADCALLIN); + + /* Read calibration result for future reference */ + ret = stm32h7_adc_read_selfcalib(adc); + +pwr_dwn: + stm32h7_adc_enter_pwr_down(adc); + + return ret; +} + +/** + * stm32h7_adc_prepare() - Leave power down mode to enable ADC. + * @adc: stm32 adc instance + * Leave power down mode. + * Enable ADC. + * Restore calibration data. + * Pre-select channels that may be used in PCSEL (required by input MUX / IO). + */ +static int stm32h7_adc_prepare(struct stm32_adc *adc) +{ + int ret; + + stm32h7_adc_exit_pwr_down(adc); + + ret = stm32h7_adc_enable(adc); + if (ret) + goto pwr_dwn; + + ret = stm32h7_adc_restore_selfcalib(adc); + if (ret) + goto disable; + + stm32_adc_writel(adc, STM32H7_ADC_PCSEL, adc->pcsel); + + return 0; + +disable: + stm32h7_adc_disable(adc); +pwr_dwn: + stm32h7_adc_enter_pwr_down(adc); + + return ret; +} + +static void stm32h7_adc_unprepare(struct stm32_adc *adc) +{ + stm32h7_adc_disable(adc); + stm32h7_adc_enter_pwr_down(adc); +} + /** * stm32_adc_conf_scan_seq() - Build regular channels scan sequence * @indio_dev: IIO device * @scan_mask: channels to be converted * * Conversion sequence : + * Apply sampling time settings for all channels. * Configure ADC scan sequence based on selected channels in scan_mask. * Add channels to SQR registers, from scan_mask LSB to MSB, then * program sequence len. @@ -371,10 +1033,15 @@ static int stm32_adc_conf_scan_seq(struct iio_dev *indio_dev, const unsigned long *scan_mask) { struct stm32_adc *adc = iio_priv(indio_dev); + const struct stm32_adc_regs *sqr = adc->cfg->regs->sqr; const struct iio_chan_spec *chan; u32 val, bit; int i = 0; + /* Apply sampling time settings */ + stm32_adc_writel(adc, adc->cfg->regs->smpr[0], adc->smpr_val[0]); + stm32_adc_writel(adc, adc->cfg->regs->smpr[1], adc->smpr_val[1]); + for_each_set_bit(bit, scan_mask, indio_dev->masklength) { chan = indio_dev->channels + bit; /* @@ -388,20 +1055,20 @@ static int stm32_adc_conf_scan_seq(struct iio_dev *indio_dev, dev_dbg(&indio_dev->dev, "%s chan %d to SQ%d\n", __func__, chan->channel, i); - val = stm32_adc_readl(adc, stm32f4_sq[i].reg); - val &= ~stm32f4_sq[i].mask; - val |= chan->channel << stm32f4_sq[i].shift; - stm32_adc_writel(adc, stm32f4_sq[i].reg, val); + val = stm32_adc_readl(adc, sqr[i].reg); + val &= ~sqr[i].mask; + val |= chan->channel << sqr[i].shift; + stm32_adc_writel(adc, sqr[i].reg, val); } if (!i) return -EINVAL; /* Sequence len */ - val = stm32_adc_readl(adc, stm32f4_sq[0].reg); - val &= ~stm32f4_sq[0].mask; - val |= ((i - 1) << stm32f4_sq[0].shift); - stm32_adc_writel(adc, stm32f4_sq[0].reg, val); + val = stm32_adc_readl(adc, sqr[0].reg); + val &= ~sqr[0].mask; + val |= ((i - 1) << sqr[0].shift); + stm32_adc_writel(adc, sqr[0].reg, val); return 0; } @@ -412,19 +1079,22 @@ static int stm32_adc_conf_scan_seq(struct iio_dev *indio_dev, * * Returns trigger extsel value, if trig matches, -EINVAL otherwise. */ -static int stm32_adc_get_trig_extsel(struct iio_trigger *trig) +static int stm32_adc_get_trig_extsel(struct iio_dev *indio_dev, + struct iio_trigger *trig) { + struct stm32_adc *adc = iio_priv(indio_dev); int i; /* lookup triggers registered by stm32 timer trigger driver */ - for (i = 0; stm32f4_adc_trigs[i].name; i++) { + for (i = 0; adc->cfg->trigs[i].name; i++) { /** * Checking both stm32 timer trigger type and trig name * should be safe against arbitrary trigger names. */ - if (is_stm32_timer_trigger(trig) && - !strcmp(stm32f4_adc_trigs[i].name, trig->name)) { - return stm32f4_adc_trigs[i].extsel; + if ((is_stm32_timer_trigger(trig) || + is_stm32_lptim_trigger(trig)) && + !strcmp(adc->cfg->trigs[i].name, trig->name)) { + return adc->cfg->trigs[i].extsel; } } @@ -449,7 +1119,7 @@ static int stm32_adc_set_trig(struct iio_dev *indio_dev, int ret; if (trig) { - ret = stm32_adc_get_trig_extsel(trig); + ret = stm32_adc_get_trig_extsel(indio_dev, trig); if (ret < 0) return ret; @@ -459,11 +1129,11 @@ static int stm32_adc_set_trig(struct iio_dev *indio_dev, } spin_lock_irqsave(&adc->lock, flags); - val = stm32_adc_readl(adc, STM32F4_ADC_CR2); - val &= ~(STM32F4_EXTEN_MASK | STM32F4_EXTSEL_MASK); - val |= exten << STM32F4_EXTEN_SHIFT; - val |= extsel << STM32F4_EXTSEL_SHIFT; - stm32_adc_writel(adc, STM32F4_ADC_CR2, val); + val = stm32_adc_readl(adc, adc->cfg->regs->exten.reg); + val &= ~(adc->cfg->regs->exten.mask | adc->cfg->regs->extsel.mask); + val |= exten << adc->cfg->regs->exten.shift; + val |= extsel << adc->cfg->regs->extsel.shift; + stm32_adc_writel(adc, adc->cfg->regs->exten.reg, val); spin_unlock_irqrestore(&adc->lock, flags); return 0; @@ -506,6 +1176,7 @@ static const struct iio_enum stm32_adc_trig_pol = { * @res: conversion result * * The function performs a single conversion on a given channel: + * - Apply sampling time settings * - Program sequencer with one channel (e.g. in SQ1 with len = 1) * - Use SW trigger * - Start conversion, then wait for interrupt completion. @@ -515,6 +1186,7 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev, int *res) { struct stm32_adc *adc = iio_priv(indio_dev); + const struct stm32_adc_regspec *regs = adc->cfg->regs; long timeout; u32 val; int ret; @@ -523,21 +1195,31 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev, adc->bufi = 0; + if (adc->cfg->prepare) { + ret = adc->cfg->prepare(adc); + if (ret) + return ret; + } + + /* Apply sampling time settings */ + stm32_adc_writel(adc, regs->smpr[0], adc->smpr_val[0]); + stm32_adc_writel(adc, regs->smpr[1], adc->smpr_val[1]); + /* Program chan number in regular sequence (SQ1) */ - val = stm32_adc_readl(adc, stm32f4_sq[1].reg); - val &= ~stm32f4_sq[1].mask; - val |= chan->channel << stm32f4_sq[1].shift; - stm32_adc_writel(adc, stm32f4_sq[1].reg, val); + val = stm32_adc_readl(adc, regs->sqr[1].reg); + val &= ~regs->sqr[1].mask; + val |= chan->channel << regs->sqr[1].shift; + stm32_adc_writel(adc, regs->sqr[1].reg, val); /* Set regular sequence len (0 for 1 conversion) */ - stm32_adc_clr_bits(adc, stm32f4_sq[0].reg, stm32f4_sq[0].mask); + stm32_adc_clr_bits(adc, regs->sqr[0].reg, regs->sqr[0].mask); /* Trigger detection disabled (conversion can be launched in SW) */ - stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_EXTEN_MASK); + stm32_adc_clr_bits(adc, regs->exten.reg, regs->exten.mask); stm32_adc_conv_irq_enable(adc); - stm32_adc_start_conv(adc, false); + adc->cfg->start_conv(adc, false); timeout = wait_for_completion_interruptible_timeout( &adc->completion, STM32_ADC_TIMEOUT); @@ -550,10 +1232,13 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev, ret = IIO_VAL_INT; } - stm32_adc_stop_conv(adc); + adc->cfg->stop_conv(adc); stm32_adc_conv_irq_disable(adc); + if (adc->cfg->unprepare) + adc->cfg->unprepare(adc); + return ret; } @@ -590,11 +1275,12 @@ static irqreturn_t stm32_adc_isr(int irq, void *data) { struct stm32_adc *adc = data; struct iio_dev *indio_dev = iio_priv_to_dev(adc); - u32 status = stm32_adc_readl(adc, STM32F4_ADC_SR); + const struct stm32_adc_regspec *regs = adc->cfg->regs; + u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg); - if (status & STM32F4_EOC) { + if (status & regs->isr_eoc.mask) { /* Reading DR also clears EOC status flag */ - adc->buffer[adc->bufi] = stm32_adc_readw(adc, STM32F4_ADC_DR); + adc->buffer[adc->bufi] = stm32_adc_readw(adc, regs->dr); if (iio_buffer_enabled(indio_dev)) { adc->bufi++; if (adc->bufi >= adc->num_conv) { @@ -621,7 +1307,7 @@ static irqreturn_t stm32_adc_isr(int irq, void *data) static int stm32_adc_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig) { - return stm32_adc_get_trig_extsel(trig) < 0 ? -EINVAL : 0; + return stm32_adc_get_trig_extsel(indio_dev, trig) < 0 ? -EINVAL : 0; } static int stm32_adc_set_watermark(struct iio_dev *indio_dev, unsigned int val) @@ -777,10 +1463,16 @@ static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev) struct stm32_adc *adc = iio_priv(indio_dev); int ret; + if (adc->cfg->prepare) { + ret = adc->cfg->prepare(adc); + if (ret) + return ret; + } + ret = stm32_adc_set_trig(indio_dev, indio_dev->trig); if (ret) { dev_err(&indio_dev->dev, "Can't set trigger\n"); - return ret; + goto err_unprepare; } ret = stm32_adc_dma_start(indio_dev); @@ -799,7 +1491,7 @@ static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev) if (!adc->dma_chan) stm32_adc_conv_irq_enable(adc); - stm32_adc_start_conv(adc, !!adc->dma_chan); + adc->cfg->start_conv(adc, !!adc->dma_chan); return 0; @@ -808,6 +1500,9 @@ err_stop_dma: dmaengine_terminate_all(adc->dma_chan); err_clr_trig: stm32_adc_set_trig(indio_dev, NULL); +err_unprepare: + if (adc->cfg->unprepare) + adc->cfg->unprepare(adc); return ret; } @@ -817,7 +1512,7 @@ static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev) struct stm32_adc *adc = iio_priv(indio_dev); int ret; - stm32_adc_stop_conv(adc); + adc->cfg->stop_conv(adc); if (!adc->dma_chan) stm32_adc_conv_irq_disable(adc); @@ -831,6 +1526,9 @@ static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev) if (stm32_adc_set_trig(indio_dev, NULL)) dev_err(&indio_dev->dev, "Can't clear trigger\n"); + if (adc->cfg->unprepare) + adc->cfg->unprepare(adc); + return ret; } @@ -895,12 +1593,12 @@ static int stm32_adc_of_get_resolution(struct iio_dev *indio_dev) u32 res; if (of_property_read_u32(node, "assigned-resolution-bits", &res)) - res = stm32f4_adc_resolutions[0]; + res = adc->cfg->adc_info->resolutions[0]; - for (i = 0; i < ARRAY_SIZE(stm32f4_adc_resolutions); i++) - if (res == stm32f4_adc_resolutions[i]) + for (i = 0; i < adc->cfg->adc_info->num_res; i++) + if (res == adc->cfg->adc_info->resolutions[i]) break; - if (i >= ARRAY_SIZE(stm32f4_adc_resolutions)) { + if (i >= adc->cfg->adc_info->num_res) { dev_err(&indio_dev->dev, "Bad resolution: %u bits\n", res); return -EINVAL; } @@ -911,10 +1609,28 @@ static int stm32_adc_of_get_resolution(struct iio_dev *indio_dev) return 0; } +static void stm32_adc_smpr_init(struct stm32_adc *adc, int channel, u32 smp_ns) +{ + const struct stm32_adc_regs *smpr = &adc->cfg->regs->smp_bits[channel]; + u32 period_ns, shift = smpr->shift, mask = smpr->mask; + unsigned int smp, r = smpr->reg; + + /* Determine sampling time (ADC clock cycles) */ + period_ns = NSEC_PER_SEC / adc->common->rate; + for (smp = 0; smp <= STM32_ADC_MAX_SMP; smp++) + if ((period_ns * adc->cfg->smp_cycles[smp]) >= smp_ns) + break; + if (smp > STM32_ADC_MAX_SMP) + smp = STM32_ADC_MAX_SMP; + + /* pre-build sampling time registers (e.g. smpr1, smpr2) */ + adc->smpr_val[r] = (adc->smpr_val[r] & ~mask) | (smp << shift); +} + static void stm32_adc_chan_init_one(struct iio_dev *indio_dev, struct iio_chan_spec *chan, const struct stm32_adc_chan_spec *channel, - int scan_index) + int scan_index, u32 smp) { struct stm32_adc *adc = iio_priv(indio_dev); @@ -926,40 +1642,65 @@ static void stm32_adc_chan_init_one(struct iio_dev *indio_dev, chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); chan->scan_type.sign = 'u'; - chan->scan_type.realbits = stm32f4_adc_resolutions[adc->res]; + chan->scan_type.realbits = adc->cfg->adc_info->resolutions[adc->res]; chan->scan_type.storagebits = 16; chan->ext_info = stm32_adc_ext_info; + + /* Prepare sampling time settings */ + stm32_adc_smpr_init(adc, chan->channel, smp); + + /* pre-build selected channels mask */ + adc->pcsel |= BIT(chan->channel); } static int stm32_adc_chan_of_init(struct iio_dev *indio_dev) { struct device_node *node = indio_dev->dev.of_node; + struct stm32_adc *adc = iio_priv(indio_dev); + const struct stm32_adc_info *adc_info = adc->cfg->adc_info; struct property *prop; const __be32 *cur; struct iio_chan_spec *channels; - int scan_index = 0, num_channels; - u32 val; + int scan_index = 0, num_channels, ret; + u32 val, smp = 0; num_channels = of_property_count_u32_elems(node, "st,adc-channels"); if (num_channels < 0 || - num_channels >= ARRAY_SIZE(stm32f4_adc123_channels)) { + num_channels > adc_info->max_channels) { dev_err(&indio_dev->dev, "Bad st,adc-channels?\n"); return num_channels < 0 ? num_channels : -EINVAL; } + /* Optional sample time is provided either for each, or all channels */ + ret = of_property_count_u32_elems(node, "st,min-sample-time-nsecs"); + if (ret > 1 && ret != num_channels) { + dev_err(&indio_dev->dev, "Invalid st,min-sample-time-nsecs\n"); + return -EINVAL; + } + channels = devm_kcalloc(&indio_dev->dev, num_channels, sizeof(struct iio_chan_spec), GFP_KERNEL); if (!channels) return -ENOMEM; of_property_for_each_u32(node, "st,adc-channels", prop, cur, val) { - if (val >= ARRAY_SIZE(stm32f4_adc123_channels)) { + if (val >= adc_info->max_channels) { dev_err(&indio_dev->dev, "Invalid channel %d\n", val); return -EINVAL; } + + /* + * Using of_property_read_u32_index(), smp value will only be + * modified if valid u32 value can be decoded. This allows to + * get either no value, 1 shared value for all indexes, or one + * value per channel. + */ + of_property_read_u32_index(node, "st,min-sample-time-nsecs", + scan_index, &smp); + stm32_adc_chan_init_one(indio_dev, &channels[scan_index], - &stm32f4_adc123_channels[val], - scan_index); + &adc_info->channels[val], + scan_index, smp); scan_index++; } @@ -990,7 +1731,7 @@ static int stm32_adc_dma_request(struct iio_dev *indio_dev) /* Configure DMA channel to read data register */ memset(&config, 0, sizeof(config)); config.src_addr = (dma_addr_t)adc->common->phys_base; - config.src_addr += adc->offset + STM32F4_ADC_DR; + config.src_addr += adc->offset + adc->cfg->regs->dr; config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; ret = dmaengine_slave_config(adc->dma_chan, &config); @@ -1011,6 +1752,7 @@ err_release: static int stm32_adc_probe(struct platform_device *pdev) { struct iio_dev *indio_dev; + struct device *dev = &pdev->dev; struct stm32_adc *adc; int ret; @@ -1025,12 +1767,14 @@ static int stm32_adc_probe(struct platform_device *pdev) adc->common = dev_get_drvdata(pdev->dev.parent); spin_lock_init(&adc->lock); init_completion(&adc->completion); + adc->cfg = (const struct stm32_adc_cfg *) + of_match_device(dev->driver->of_match_table, dev)->data; indio_dev->name = dev_name(&pdev->dev); indio_dev->dev.parent = &pdev->dev; indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->info = &stm32_adc_iio_info; - indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->modes = INDIO_DIRECT_MODE | INDIO_HARDWARE_TRIGGERED; platform_set_drvdata(pdev, adc); @@ -1055,14 +1799,21 @@ static int stm32_adc_probe(struct platform_device *pdev) adc->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(adc->clk)) { - dev_err(&pdev->dev, "Can't get clock\n"); - return PTR_ERR(adc->clk); + ret = PTR_ERR(adc->clk); + if (ret == -ENOENT && !adc->cfg->clk_required) { + adc->clk = NULL; + } else { + dev_err(&pdev->dev, "Can't get clock\n"); + return ret; + } } - ret = clk_prepare_enable(adc->clk); - if (ret < 0) { - dev_err(&pdev->dev, "clk enable failed\n"); - return ret; + if (adc->clk) { + ret = clk_prepare_enable(adc->clk); + if (ret < 0) { + dev_err(&pdev->dev, "clk enable failed\n"); + return ret; + } } ret = stm32_adc_of_get_resolution(indio_dev); @@ -1070,6 +1821,12 @@ static int stm32_adc_probe(struct platform_device *pdev) goto err_clk_disable; stm32_adc_set_res(adc); + if (adc->cfg->selfcalib) { + ret = adc->cfg->selfcalib(adc); + if (ret) + goto err_clk_disable; + } + ret = stm32_adc_chan_of_init(indio_dev); if (ret < 0) goto err_clk_disable; @@ -1106,7 +1863,8 @@ err_dma_disable: dma_release_channel(adc->dma_chan); } err_clk_disable: - clk_disable_unprepare(adc->clk); + if (adc->clk) + clk_disable_unprepare(adc->clk); return ret; } @@ -1124,13 +1882,37 @@ static int stm32_adc_remove(struct platform_device *pdev) adc->rx_buf, adc->rx_dma_buf); dma_release_channel(adc->dma_chan); } - clk_disable_unprepare(adc->clk); + if (adc->clk) + clk_disable_unprepare(adc->clk); return 0; } +static const struct stm32_adc_cfg stm32f4_adc_cfg = { + .regs = &stm32f4_adc_regspec, + .adc_info = &stm32f4_adc_info, + .trigs = stm32f4_adc_trigs, + .clk_required = true, + .start_conv = stm32f4_adc_start_conv, + .stop_conv = stm32f4_adc_stop_conv, + .smp_cycles = stm32f4_adc_smp_cycles, +}; + +static const struct stm32_adc_cfg stm32h7_adc_cfg = { + .regs = &stm32h7_adc_regspec, + .adc_info = &stm32h7_adc_info, + .trigs = stm32h7_adc_trigs, + .selfcalib = stm32h7_adc_selfcalib, + .start_conv = stm32h7_adc_start_conv, + .stop_conv = stm32h7_adc_stop_conv, + .prepare = stm32h7_adc_prepare, + .unprepare = stm32h7_adc_unprepare, + .smp_cycles = stm32h7_adc_smp_cycles, +}; + static const struct of_device_id stm32_adc_of_match[] = { - { .compatible = "st,stm32f4-adc" }, + { .compatible = "st,stm32f4-adc", .data = (void *)&stm32f4_adc_cfg }, + { .compatible = "st,stm32h7-adc", .data = (void *)&stm32h7_adc_cfg }, {}, }; MODULE_DEVICE_TABLE(of, stm32_adc_of_match); diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c index 81d4c39e414a..137f577d9432 100644 --- a/drivers/iio/adc/sun4i-gpadc-iio.c +++ b/drivers/iio/adc/sun4i-gpadc-iio.c @@ -256,6 +256,7 @@ static int sun4i_gpadc_read(struct iio_dev *indio_dev, int channel, int *val, err: pm_runtime_put_autosuspend(indio_dev->dev.parent); + disable_irq(irq); mutex_unlock(&info->mutex); return ret; @@ -365,7 +366,6 @@ static irqreturn_t sun4i_gpadc_temp_data_irq_handler(int irq, void *dev_id) complete(&info->completion); out: - disable_irq_nosync(info->temp_data_irq); return IRQ_HANDLED; } @@ -380,7 +380,6 @@ static irqreturn_t sun4i_gpadc_fifo_data_irq_handler(int irq, void *dev_id) complete(&info->completion); out: - disable_irq_nosync(info->fifo_data_irq); return IRQ_HANDLED; } diff --git a/drivers/iio/adc/ti-adc084s021.c b/drivers/iio/adc/ti-adc084s021.c new file mode 100644 index 000000000000..a355121c11a4 --- /dev/null +++ b/drivers/iio/adc/ti-adc084s021.c @@ -0,0 +1,275 @@ +/** + * Copyright (C) 2017 Axis Communications AB + * + * Driver for Texas Instruments' ADC084S021 ADC chip. + * Datasheets can be found here: + * http://www.ti.com/lit/ds/symlink/adc084s021.pdf + * + * 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. + */ + +#include <linux/err.h> +#include <linux/spi/spi.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/iio/iio.h> +#include <linux/iio/buffer.h> +#include <linux/iio/triggered_buffer.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/regulator/consumer.h> + +#define ADC084S021_DRIVER_NAME "adc084s021" + +struct adc084s021 { + struct spi_device *spi; + struct spi_message message; + struct spi_transfer spi_trans; + struct regulator *reg; + struct mutex lock; + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache line. + */ + u16 tx_buf[4] ____cacheline_aligned; + __be16 rx_buf[5]; /* First 16-bits are trash */ +}; + +#define ADC084S021_VOLTAGE_CHANNEL(num) \ + { \ + .type = IIO_VOLTAGE, \ + .channel = (num), \ + .indexed = 1, \ + .scan_index = (num), \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 8, \ + .storagebits = 16, \ + .shift = 4, \ + .endianness = IIO_BE, \ + }, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ + } + +static const struct iio_chan_spec adc084s021_channels[] = { + ADC084S021_VOLTAGE_CHANNEL(0), + ADC084S021_VOLTAGE_CHANNEL(1), + ADC084S021_VOLTAGE_CHANNEL(2), + ADC084S021_VOLTAGE_CHANNEL(3), + IIO_CHAN_SOFT_TIMESTAMP(4), +}; + +/** + * Read an ADC channel and return its value. + * + * @adc: The ADC SPI data. + * @data: Buffer for converted data. + */ +static int adc084s021_adc_conversion(struct adc084s021 *adc, void *data) +{ + int n_words = (adc->spi_trans.len >> 1) - 1; /* Discard first word */ + int ret, i = 0; + u16 *p = data; + + /* Do the transfer */ + ret = spi_sync(adc->spi, &adc->message); + if (ret < 0) + return ret; + + for (; i < n_words; i++) + *(p + i) = adc->rx_buf[i + 1]; + + return ret; +} + +static int adc084s021_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *channel, int *val, + int *val2, long mask) +{ + struct adc084s021 *adc = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret < 0) + return ret; + + ret = regulator_enable(adc->reg); + if (ret) { + iio_device_release_direct_mode(indio_dev); + return ret; + } + + adc->tx_buf[0] = channel->channel << 3; + ret = adc084s021_adc_conversion(adc, val); + iio_device_release_direct_mode(indio_dev); + regulator_disable(adc->reg); + if (ret < 0) + return ret; + + *val = be16_to_cpu(*val); + *val = (*val >> channel->scan_type.shift) & 0xff; + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + ret = regulator_enable(adc->reg); + if (ret) + return ret; + + ret = regulator_get_voltage(adc->reg); + regulator_disable(adc->reg); + if (ret < 0) + return ret; + + *val = ret / 1000; + + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +/** + * Read enabled ADC channels and push data to the buffer. + * + * @irq: The interrupt number (not used). + * @pollfunc: Pointer to the poll func. + */ +static irqreturn_t adc084s021_buffer_trigger_handler(int irq, void *pollfunc) +{ + struct iio_poll_func *pf = pollfunc; + struct iio_dev *indio_dev = pf->indio_dev; + struct adc084s021 *adc = iio_priv(indio_dev); + __be16 data[8] = {0}; /* 4 * 16-bit words of data + 8 bytes timestamp */ + + mutex_lock(&adc->lock); + + if (adc084s021_adc_conversion(adc, &data) < 0) + dev_err(&adc->spi->dev, "Failed to read data\n"); + + iio_push_to_buffers_with_timestamp(indio_dev, data, + iio_get_time_ns(indio_dev)); + mutex_unlock(&adc->lock); + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int adc084s021_buffer_preenable(struct iio_dev *indio_dev) +{ + struct adc084s021 *adc = iio_priv(indio_dev); + int scan_index; + int i = 0; + + for_each_set_bit(scan_index, indio_dev->active_scan_mask, + indio_dev->masklength) { + const struct iio_chan_spec *channel = + &indio_dev->channels[scan_index]; + adc->tx_buf[i++] = channel->channel << 3; + } + adc->spi_trans.len = 2 + (i * sizeof(__be16)); /* Trash + channels */ + + return regulator_enable(adc->reg); +} + +static int adc084s021_buffer_postdisable(struct iio_dev *indio_dev) +{ + struct adc084s021 *adc = iio_priv(indio_dev); + + adc->spi_trans.len = 4; /* Trash + single channel */ + + return regulator_disable(adc->reg); +} + +static const struct iio_info adc084s021_info = { + .read_raw = adc084s021_read_raw, + .driver_module = THIS_MODULE, +}; + +static const struct iio_buffer_setup_ops adc084s021_buffer_setup_ops = { + .preenable = adc084s021_buffer_preenable, + .postenable = iio_triggered_buffer_postenable, + .predisable = iio_triggered_buffer_predisable, + .postdisable = adc084s021_buffer_postdisable, +}; + +static int adc084s021_probe(struct spi_device *spi) +{ + struct iio_dev *indio_dev; + struct adc084s021 *adc; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc)); + if (!indio_dev) { + dev_err(&spi->dev, "Failed to allocate IIO device\n"); + return -ENOMEM; + } + + adc = iio_priv(indio_dev); + adc->spi = spi; + + /* Connect the SPI device and the iio dev */ + spi_set_drvdata(spi, indio_dev); + + /* Initiate the Industrial I/O device */ + indio_dev->dev.parent = &spi->dev; + indio_dev->dev.of_node = spi->dev.of_node; + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &adc084s021_info; + indio_dev->channels = adc084s021_channels; + indio_dev->num_channels = ARRAY_SIZE(adc084s021_channels); + + /* Create SPI transfer for channel reads */ + adc->spi_trans.tx_buf = adc->tx_buf; + adc->spi_trans.rx_buf = adc->rx_buf; + adc->spi_trans.len = 4; /* Trash + single channel */ + spi_message_init_with_transfers(&adc->message, &adc->spi_trans, 1); + + adc->reg = devm_regulator_get(&spi->dev, "vref"); + if (IS_ERR(adc->reg)) + return PTR_ERR(adc->reg); + + mutex_init(&adc->lock); + + /* Setup triggered buffer with pollfunction */ + ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, NULL, + adc084s021_buffer_trigger_handler, + &adc084s021_buffer_setup_ops); + if (ret) { + dev_err(&spi->dev, "Failed to setup triggered buffer\n"); + return ret; + } + + return devm_iio_device_register(&spi->dev, indio_dev); +} + +static const struct of_device_id adc084s021_of_match[] = { + { .compatible = "ti,adc084s021", }, + {}, +}; +MODULE_DEVICE_TABLE(of, adc084s021_of_match); + +static const struct spi_device_id adc084s021_id[] = { + { ADC084S021_DRIVER_NAME, 0}, + {} +}; +MODULE_DEVICE_TABLE(spi, adc084s021_id); + +static struct spi_driver adc084s021_driver = { + .driver = { + .name = ADC084S021_DRIVER_NAME, + .of_match_table = of_match_ptr(adc084s021_of_match), + }, + .probe = adc084s021_probe, + .id_table = adc084s021_id, +}; +module_spi_driver(adc084s021_driver); + +MODULE_AUTHOR("MÃ¥rten Lindahl <martenli@axis.com>"); +MODULE_DESCRIPTION("Texas Instruments ADC084S021"); +MODULE_LICENSE("GPL v2"); +MODULE_VERSION("1.0"); diff --git a/drivers/iio/adc/ti-adc108s102.c b/drivers/iio/adc/ti-adc108s102.c new file mode 100644 index 000000000000..de4e5ac98c6e --- /dev/null +++ b/drivers/iio/adc/ti-adc108s102.c @@ -0,0 +1,348 @@ +/* + * TI ADC108S102 SPI ADC driver + * + * Copyright (c) 2013-2015 Intel Corporation. + * Copyright (c) 2017 Siemens AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 for + * more details. + * + * This IIO device driver is designed to work with the following + * analog to digital converters from Texas Instruments: + * ADC108S102 + * ADC128S102 + * The communication with ADC chip is via the SPI bus (mode 3). + */ + +#include <linux/acpi.h> +#include <linux/iio/iio.h> +#include <linux/iio/buffer.h> +#include <linux/iio/types.h> +#include <linux/iio/triggered_buffer.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/property.h> +#include <linux/regulator/consumer.h> +#include <linux/spi/spi.h> + +/* + * In case of ACPI, we use the hard-wired 5000 mV of the Galileo and IOT2000 + * boards as default for the reference pin VA. Device tree users encode that + * via the vref-supply regulator. + */ +#define ADC108S102_VA_MV_ACPI_DEFAULT 5000 + +/* + * Defining the ADC resolution being 12 bits, we can use the same driver for + * both ADC108S102 (10 bits resolution) and ADC128S102 (12 bits resolution) + * chips. The ADC108S102 effectively returns a 12-bit result with the 2 + * least-significant bits unset. + */ +#define ADC108S102_BITS 12 +#define ADC108S102_MAX_CHANNELS 8 + +/* + * 16-bit SPI command format: + * [15:14] Ignored + * [13:11] 3-bit channel address + * [10:0] Ignored + */ +#define ADC108S102_CMD(ch) ((u16)(ch) << 11) + +/* + * 16-bit SPI response format: + * [15:12] Zeros + * [11:0] 12-bit ADC sample (for ADC108S102, [1:0] will always be 0). + */ +#define ADC108S102_RES_DATA(res) ((u16)res & GENMASK(11, 0)) + +struct adc108s102_state { + struct spi_device *spi; + struct regulator *reg; + u32 va_millivolt; + /* SPI transfer used by triggered buffer handler*/ + struct spi_transfer ring_xfer; + /* SPI transfer used by direct scan */ + struct spi_transfer scan_single_xfer; + /* SPI message used by ring_xfer SPI transfer */ + struct spi_message ring_msg; + /* SPI message used by scan_single_xfer SPI transfer */ + struct spi_message scan_single_msg; + + /* + * SPI message buffers: + * tx_buf: |C0|C1|C2|C3|C4|C5|C6|C7|XX| + * rx_buf: |XX|R0|R1|R2|R3|R4|R5|R6|R7|tt|tt|tt|tt| + * + * tx_buf: 8 channel read commands, plus 1 dummy command + * rx_buf: 1 dummy response, 8 channel responses, plus 64-bit timestamp + */ + __be16 rx_buf[13] ____cacheline_aligned; + __be16 tx_buf[9] ____cacheline_aligned; +}; + +#define ADC108S102_V_CHAN(index) \ + { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = index, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .address = index, \ + .scan_index = index, \ + .scan_type = { \ + .sign = 'u', \ + .realbits = ADC108S102_BITS, \ + .storagebits = 16, \ + .endianness = IIO_BE, \ + }, \ + } + +static const struct iio_chan_spec adc108s102_channels[] = { + ADC108S102_V_CHAN(0), + ADC108S102_V_CHAN(1), + ADC108S102_V_CHAN(2), + ADC108S102_V_CHAN(3), + ADC108S102_V_CHAN(4), + ADC108S102_V_CHAN(5), + ADC108S102_V_CHAN(6), + ADC108S102_V_CHAN(7), + IIO_CHAN_SOFT_TIMESTAMP(8), +}; + +static int adc108s102_update_scan_mode(struct iio_dev *indio_dev, + unsigned long const *active_scan_mask) +{ + struct adc108s102_state *st = iio_priv(indio_dev); + unsigned int bit, cmds; + + /* + * Fill in the first x shorts of tx_buf with the number of channels + * enabled for sampling by the triggered buffer. + */ + cmds = 0; + for_each_set_bit(bit, active_scan_mask, ADC108S102_MAX_CHANNELS) + st->tx_buf[cmds++] = cpu_to_be16(ADC108S102_CMD(bit)); + + /* One dummy command added, to clock in the last response */ + st->tx_buf[cmds++] = 0x00; + + /* build SPI ring message */ + st->ring_xfer.tx_buf = &st->tx_buf[0]; + st->ring_xfer.rx_buf = &st->rx_buf[0]; + st->ring_xfer.len = cmds * sizeof(st->tx_buf[0]); + + spi_message_init_with_transfers(&st->ring_msg, &st->ring_xfer, 1); + + return 0; +} + +static irqreturn_t adc108s102_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct adc108s102_state *st = iio_priv(indio_dev); + int ret; + + ret = spi_sync(st->spi, &st->ring_msg); + if (ret < 0) + goto out_notify; + + /* Skip the dummy response in the first slot */ + iio_push_to_buffers_with_timestamp(indio_dev, + (u8 *)&st->rx_buf[1], + iio_get_time_ns(indio_dev)); + +out_notify: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int adc108s102_scan_direct(struct adc108s102_state *st, unsigned int ch) +{ + int ret; + + st->tx_buf[0] = cpu_to_be16(ADC108S102_CMD(ch)); + ret = spi_sync(st->spi, &st->scan_single_msg); + if (ret) + return ret; + + /* Skip the dummy response in the first slot */ + return be16_to_cpu(st->rx_buf[1]); +} + +static int adc108s102_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long m) +{ + struct adc108s102_state *st = iio_priv(indio_dev); + int ret; + + switch (m) { + case IIO_CHAN_INFO_RAW: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + ret = adc108s102_scan_direct(st, chan->address); + + iio_device_release_direct_mode(indio_dev); + + if (ret < 0) + return ret; + + *val = ADC108S102_RES_DATA(ret); + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + if (chan->type != IIO_VOLTAGE) + break; + + *val = st->va_millivolt; + *val2 = chan->scan_type.realbits; + + return IIO_VAL_FRACTIONAL_LOG2; + default: + break; + } + + return -EINVAL; +} + +static const struct iio_info adc108s102_info = { + .read_raw = &adc108s102_read_raw, + .update_scan_mode = &adc108s102_update_scan_mode, + .driver_module = THIS_MODULE, +}; + +static int adc108s102_probe(struct spi_device *spi) +{ + struct adc108s102_state *st; + struct iio_dev *indio_dev; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st = iio_priv(indio_dev); + + if (ACPI_COMPANION(&spi->dev)) { + st->va_millivolt = ADC108S102_VA_MV_ACPI_DEFAULT; + } else { + st->reg = devm_regulator_get(&spi->dev, "vref"); + if (IS_ERR(st->reg)) + return PTR_ERR(st->reg); + + ret = regulator_enable(st->reg); + if (ret < 0) { + dev_err(&spi->dev, "Cannot enable vref regulator\n"); + return ret; + } + + ret = regulator_get_voltage(st->reg); + if (ret < 0) { + dev_err(&spi->dev, "vref get voltage failed\n"); + return ret; + } + + st->va_millivolt = ret / 1000; + } + + spi_set_drvdata(spi, indio_dev); + st->spi = spi; + + indio_dev->name = spi->modalias; + indio_dev->dev.parent = &spi->dev; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = adc108s102_channels; + indio_dev->num_channels = ARRAY_SIZE(adc108s102_channels); + indio_dev->info = &adc108s102_info; + + /* Setup default message */ + st->scan_single_xfer.tx_buf = st->tx_buf; + st->scan_single_xfer.rx_buf = st->rx_buf; + st->scan_single_xfer.len = 2 * sizeof(st->tx_buf[0]); + + spi_message_init_with_transfers(&st->scan_single_msg, + &st->scan_single_xfer, 1); + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + &adc108s102_trigger_handler, NULL); + if (ret) + goto error_disable_reg; + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&spi->dev, "Failed to register IIO device\n"); + goto error_cleanup_triggered_buffer; + } + return 0; + +error_cleanup_triggered_buffer: + iio_triggered_buffer_cleanup(indio_dev); + +error_disable_reg: + regulator_disable(st->reg); + + return ret; +} + +static int adc108s102_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct adc108s102_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + + regulator_disable(st->reg); + + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id adc108s102_of_match[] = { + { .compatible = "ti,adc108s102" }, + { } +}; +MODULE_DEVICE_TABLE(of, adc108s102_of_match); +#endif + +#ifdef CONFIG_ACPI +static const struct acpi_device_id adc108s102_acpi_ids[] = { + { "INT3495", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, adc108s102_acpi_ids); +#endif + +static const struct spi_device_id adc108s102_id[] = { + { "adc108s102", 0 }, + { } +}; +MODULE_DEVICE_TABLE(spi, adc108s102_id); + +static struct spi_driver adc108s102_driver = { + .driver = { + .name = "adc108s102", + .of_match_table = of_match_ptr(adc108s102_of_match), + .acpi_match_table = ACPI_PTR(adc108s102_acpi_ids), + }, + .probe = adc108s102_probe, + .remove = adc108s102_remove, + .id_table = adc108s102_id, +}; +module_spi_driver(adc108s102_driver); + +MODULE_AUTHOR("Bogdan Pricop <bogdan.pricop@emutex.com>"); +MODULE_DESCRIPTION("Texas Instruments ADC108S102 and ADC128S102 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c index f76d979fb7e8..e0dc20488335 100644 --- a/drivers/iio/adc/ti-ads1015.c +++ b/drivers/iio/adc/ti-ads1015.c @@ -17,17 +17,19 @@ #include <linux/module.h> #include <linux/of_device.h> #include <linux/init.h> +#include <linux/irq.h> #include <linux/i2c.h> #include <linux/regmap.h> #include <linux/pm_runtime.h> #include <linux/mutex.h> #include <linux/delay.h> -#include <linux/i2c/ads1015.h> +#include <linux/platform_data/ads1015.h> #include <linux/iio/iio.h> #include <linux/iio/types.h> #include <linux/iio/sysfs.h> +#include <linux/iio/events.h> #include <linux/iio/buffer.h> #include <linux/iio/triggered_buffer.h> #include <linux/iio/trigger_consumer.h> @@ -36,17 +38,38 @@ #define ADS1015_CONV_REG 0x00 #define ADS1015_CFG_REG 0x01 +#define ADS1015_LO_THRESH_REG 0x02 +#define ADS1015_HI_THRESH_REG 0x03 +#define ADS1015_CFG_COMP_QUE_SHIFT 0 +#define ADS1015_CFG_COMP_LAT_SHIFT 2 +#define ADS1015_CFG_COMP_POL_SHIFT 3 +#define ADS1015_CFG_COMP_MODE_SHIFT 4 #define ADS1015_CFG_DR_SHIFT 5 #define ADS1015_CFG_MOD_SHIFT 8 #define ADS1015_CFG_PGA_SHIFT 9 #define ADS1015_CFG_MUX_SHIFT 12 +#define ADS1015_CFG_COMP_QUE_MASK GENMASK(1, 0) +#define ADS1015_CFG_COMP_LAT_MASK BIT(2) +#define ADS1015_CFG_COMP_POL_MASK BIT(3) +#define ADS1015_CFG_COMP_MODE_MASK BIT(4) #define ADS1015_CFG_DR_MASK GENMASK(7, 5) #define ADS1015_CFG_MOD_MASK BIT(8) #define ADS1015_CFG_PGA_MASK GENMASK(11, 9) #define ADS1015_CFG_MUX_MASK GENMASK(14, 12) +/* Comparator queue and disable field */ +#define ADS1015_CFG_COMP_DISABLE 3 + +/* Comparator polarity field */ +#define ADS1015_CFG_COMP_POL_LOW 0 +#define ADS1015_CFG_COMP_POL_HIGH 1 + +/* Comparator mode field */ +#define ADS1015_CFG_COMP_MODE_TRAD 0 +#define ADS1015_CFG_COMP_MODE_WINDOW 1 + /* device operating modes */ #define ADS1015_CONTINUOUS 0 #define ADS1015_SINGLESHOT 1 @@ -81,18 +104,36 @@ static const unsigned int ads1115_data_rate[] = { 8, 16, 32, 64, 128, 250, 475, 860 }; -static const struct { - int scale; - int uscale; -} ads1015_scale[] = { - {3, 0}, - {2, 0}, - {1, 0}, - {0, 500000}, - {0, 250000}, - {0, 125000}, - {0, 125000}, - {0, 125000}, +/* + * Translation from PGA bits to full-scale positive and negative input voltage + * range in mV + */ +static int ads1015_fullscale_range[] = { + 6144, 4096, 2048, 1024, 512, 256, 256, 256 +}; + +/* + * Translation from COMP_QUE field value to the number of successive readings + * exceed the threshold values before an interrupt is generated + */ +static const int ads1015_comp_queue[] = { 1, 2, 4 }; + +static const struct iio_event_spec ads1015_events[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + }, { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_VALUE), + }, { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_EITHER, + .mask_separate = BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_PERIOD), + }, }; #define ADS1015_V_CHAN(_chan, _addr) { \ @@ -111,6 +152,8 @@ static const struct { .shift = 4, \ .endianness = IIO_CPU, \ }, \ + .event_spec = ads1015_events, \ + .num_event_specs = ARRAY_SIZE(ads1015_events), \ .datasheet_name = "AIN"#_chan, \ } @@ -132,6 +175,8 @@ static const struct { .shift = 4, \ .endianness = IIO_CPU, \ }, \ + .event_spec = ads1015_events, \ + .num_event_specs = ARRAY_SIZE(ads1015_events), \ .datasheet_name = "AIN"#_chan"-AIN"#_chan2, \ } @@ -150,6 +195,8 @@ static const struct { .storagebits = 16, \ .endianness = IIO_CPU, \ }, \ + .event_spec = ads1015_events, \ + .num_event_specs = ARRAY_SIZE(ads1015_events), \ .datasheet_name = "AIN"#_chan, \ } @@ -170,9 +217,17 @@ static const struct { .storagebits = 16, \ .endianness = IIO_CPU, \ }, \ + .event_spec = ads1015_events, \ + .num_event_specs = ARRAY_SIZE(ads1015_events), \ .datasheet_name = "AIN"#_chan"-AIN"#_chan2, \ } +struct ads1015_thresh_data { + unsigned int comp_queue; + int high_thresh; + int low_thresh; +}; + struct ads1015_data { struct regmap *regmap; /* @@ -182,18 +237,54 @@ struct ads1015_data { struct mutex lock; struct ads1015_channel_data channel_data[ADS1015_CHANNELS]; + unsigned int event_channel; + unsigned int comp_mode; + struct ads1015_thresh_data thresh_data[ADS1015_CHANNELS]; + unsigned int *data_rate; + /* + * Set to true when the ADC is switched to the continuous-conversion + * mode and exits from a power-down state. This flag is used to avoid + * getting the stale result from the conversion register. + */ + bool conv_invalid; }; +static bool ads1015_event_channel_enabled(struct ads1015_data *data) +{ + return (data->event_channel != ADS1015_CHANNELS); +} + +static void ads1015_event_channel_enable(struct ads1015_data *data, int chan, + int comp_mode) +{ + WARN_ON(ads1015_event_channel_enabled(data)); + + data->event_channel = chan; + data->comp_mode = comp_mode; +} + +static void ads1015_event_channel_disable(struct ads1015_data *data, int chan) +{ + data->event_channel = ADS1015_CHANNELS; +} + static bool ads1015_is_writeable_reg(struct device *dev, unsigned int reg) { - return (reg == ADS1015_CFG_REG); + switch (reg) { + case ADS1015_CFG_REG: + case ADS1015_LO_THRESH_REG: + case ADS1015_HI_THRESH_REG: + return true; + default: + return false; + } } static const struct regmap_config ads1015_regmap_config = { .reg_bits = 8, .val_bits = 16, - .max_register = ADS1015_CFG_REG, + .max_register = ADS1015_HI_THRESH_REG, .writeable_reg = ads1015_is_writeable_reg, }; @@ -235,33 +326,51 @@ static int ads1015_set_power_state(struct ads1015_data *data, bool on) ret = pm_runtime_put_autosuspend(dev); } - return ret; + return ret < 0 ? ret : 0; } static int ads1015_get_adc_result(struct ads1015_data *data, int chan, int *val) { int ret, pga, dr, conv_time; - bool change; + unsigned int old, mask, cfg; if (chan < 0 || chan >= ADS1015_CHANNELS) return -EINVAL; + ret = regmap_read(data->regmap, ADS1015_CFG_REG, &old); + if (ret) + return ret; + pga = data->channel_data[chan].pga; dr = data->channel_data[chan].data_rate; + mask = ADS1015_CFG_MUX_MASK | ADS1015_CFG_PGA_MASK | + ADS1015_CFG_DR_MASK; + cfg = chan << ADS1015_CFG_MUX_SHIFT | pga << ADS1015_CFG_PGA_SHIFT | + dr << ADS1015_CFG_DR_SHIFT; + + if (ads1015_event_channel_enabled(data)) { + mask |= ADS1015_CFG_COMP_QUE_MASK | ADS1015_CFG_COMP_MODE_MASK; + cfg |= data->thresh_data[chan].comp_queue << + ADS1015_CFG_COMP_QUE_SHIFT | + data->comp_mode << + ADS1015_CFG_COMP_MODE_SHIFT; + } - ret = regmap_update_bits_check(data->regmap, ADS1015_CFG_REG, - ADS1015_CFG_MUX_MASK | - ADS1015_CFG_PGA_MASK, - chan << ADS1015_CFG_MUX_SHIFT | - pga << ADS1015_CFG_PGA_SHIFT, - &change); - if (ret < 0) + cfg = (old & ~mask) | (cfg & mask); + + ret = regmap_write(data->regmap, ADS1015_CFG_REG, cfg); + if (ret) return ret; - if (change) { - conv_time = DIV_ROUND_UP(USEC_PER_SEC, data->data_rate[dr]); + if (old != cfg || data->conv_invalid) { + int dr_old = (old & ADS1015_CFG_DR_MASK) >> + ADS1015_CFG_DR_SHIFT; + + conv_time = DIV_ROUND_UP(USEC_PER_SEC, data->data_rate[dr_old]); + conv_time += DIV_ROUND_UP(USEC_PER_SEC, data->data_rate[dr]); usleep_range(conv_time, conv_time + 1); + data->conv_invalid = false; } return regmap_read(data->regmap, ADS1015_CONV_REG, val); @@ -298,52 +407,36 @@ err: return IRQ_HANDLED; } -static int ads1015_set_scale(struct ads1015_data *data, int chan, +static int ads1015_set_scale(struct ads1015_data *data, + struct iio_chan_spec const *chan, int scale, int uscale) { - int i, ret, rindex = -1; - - for (i = 0; i < ARRAY_SIZE(ads1015_scale); i++) - if (ads1015_scale[i].scale == scale && - ads1015_scale[i].uscale == uscale) { - rindex = i; - break; + int i; + int fullscale = div_s64((scale * 1000000LL + uscale) << + (chan->scan_type.realbits - 1), 1000000); + + for (i = 0; i < ARRAY_SIZE(ads1015_fullscale_range); i++) { + if (ads1015_fullscale_range[i] == fullscale) { + data->channel_data[chan->address].pga = i; + return 0; } - if (rindex < 0) - return -EINVAL; - - ret = regmap_update_bits(data->regmap, ADS1015_CFG_REG, - ADS1015_CFG_PGA_MASK, - rindex << ADS1015_CFG_PGA_SHIFT); - if (ret < 0) - return ret; - - data->channel_data[chan].pga = rindex; + } - return 0; + return -EINVAL; } static int ads1015_set_data_rate(struct ads1015_data *data, int chan, int rate) { - int i, ret, rindex = -1; + int i; - for (i = 0; i < ARRAY_SIZE(ads1015_data_rate); i++) + for (i = 0; i < ARRAY_SIZE(ads1015_data_rate); i++) { if (data->data_rate[i] == rate) { - rindex = i; - break; + data->channel_data[chan].data_rate = i; + return 0; } - if (rindex < 0) - return -EINVAL; - - ret = regmap_update_bits(data->regmap, ADS1015_CFG_REG, - ADS1015_CFG_DR_MASK, - rindex << ADS1015_CFG_DR_SHIFT); - if (ret < 0) - return ret; - - data->channel_data[chan].data_rate = rindex; + } - return 0; + return -EINVAL; } static int ads1015_read_raw(struct iio_dev *indio_dev, @@ -353,41 +446,47 @@ static int ads1015_read_raw(struct iio_dev *indio_dev, int ret, idx; struct ads1015_data *data = iio_priv(indio_dev); - mutex_lock(&indio_dev->mlock); mutex_lock(&data->lock); switch (mask) { case IIO_CHAN_INFO_RAW: { int shift = chan->scan_type.shift; - if (iio_buffer_enabled(indio_dev)) { - ret = -EBUSY; + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) break; + + if (ads1015_event_channel_enabled(data) && + data->event_channel != chan->address) { + ret = -EBUSY; + goto release_direct; } ret = ads1015_set_power_state(data, true); if (ret < 0) - break; + goto release_direct; ret = ads1015_get_adc_result(data, chan->address, val); if (ret < 0) { ads1015_set_power_state(data, false); - break; + goto release_direct; } *val = sign_extend32(*val >> shift, 15 - shift); ret = ads1015_set_power_state(data, false); if (ret < 0) - break; + goto release_direct; ret = IIO_VAL_INT; +release_direct: + iio_device_release_direct_mode(indio_dev); break; } case IIO_CHAN_INFO_SCALE: idx = data->channel_data[chan->address].pga; - *val = ads1015_scale[idx].scale; - *val2 = ads1015_scale[idx].uscale; - ret = IIO_VAL_INT_PLUS_MICRO; + *val = ads1015_fullscale_range[idx]; + *val2 = chan->scan_type.realbits - 1; + ret = IIO_VAL_FRACTIONAL_LOG2; break; case IIO_CHAN_INFO_SAMP_FREQ: idx = data->channel_data[chan->address].data_rate; @@ -399,7 +498,6 @@ static int ads1015_read_raw(struct iio_dev *indio_dev, break; } mutex_unlock(&data->lock); - mutex_unlock(&indio_dev->mlock); return ret; } @@ -414,7 +512,7 @@ static int ads1015_write_raw(struct iio_dev *indio_dev, mutex_lock(&data->lock); switch (mask) { case IIO_CHAN_INFO_SCALE: - ret = ads1015_set_scale(data, chan->address, val, val2); + ret = ads1015_set_scale(data, chan, val, val2); break; case IIO_CHAN_INFO_SAMP_FREQ: ret = ads1015_set_data_rate(data, chan->address, val); @@ -428,8 +526,254 @@ static int ads1015_write_raw(struct iio_dev *indio_dev, return ret; } +static int ads1015_read_event(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, enum iio_event_type type, + enum iio_event_direction dir, enum iio_event_info info, int *val, + int *val2) +{ + struct ads1015_data *data = iio_priv(indio_dev); + int ret; + unsigned int comp_queue; + int period; + int dr; + + mutex_lock(&data->lock); + + switch (info) { + case IIO_EV_INFO_VALUE: + *val = (dir == IIO_EV_DIR_RISING) ? + data->thresh_data[chan->address].high_thresh : + data->thresh_data[chan->address].low_thresh; + ret = IIO_VAL_INT; + break; + case IIO_EV_INFO_PERIOD: + dr = data->channel_data[chan->address].data_rate; + comp_queue = data->thresh_data[chan->address].comp_queue; + period = ads1015_comp_queue[comp_queue] * + USEC_PER_SEC / data->data_rate[dr]; + + *val = period / USEC_PER_SEC; + *val2 = period % USEC_PER_SEC; + ret = IIO_VAL_INT_PLUS_MICRO; + break; + default: + ret = -EINVAL; + break; + } + + mutex_unlock(&data->lock); + + return ret; +} + +static int ads1015_write_event(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, enum iio_event_type type, + enum iio_event_direction dir, enum iio_event_info info, int val, + int val2) +{ + struct ads1015_data *data = iio_priv(indio_dev); + int realbits = chan->scan_type.realbits; + int ret = 0; + long long period; + int i; + int dr; + + mutex_lock(&data->lock); + + switch (info) { + case IIO_EV_INFO_VALUE: + if (val >= 1 << (realbits - 1) || val < -1 << (realbits - 1)) { + ret = -EINVAL; + break; + } + if (dir == IIO_EV_DIR_RISING) + data->thresh_data[chan->address].high_thresh = val; + else + data->thresh_data[chan->address].low_thresh = val; + break; + case IIO_EV_INFO_PERIOD: + dr = data->channel_data[chan->address].data_rate; + period = val * USEC_PER_SEC + val2; + + for (i = 0; i < ARRAY_SIZE(ads1015_comp_queue) - 1; i++) { + if (period <= ads1015_comp_queue[i] * + USEC_PER_SEC / data->data_rate[dr]) + break; + } + data->thresh_data[chan->address].comp_queue = i; + break; + default: + ret = -EINVAL; + break; + } + + mutex_unlock(&data->lock); + + return ret; +} + +static int ads1015_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, enum iio_event_type type, + enum iio_event_direction dir) +{ + struct ads1015_data *data = iio_priv(indio_dev); + int ret = 0; + + mutex_lock(&data->lock); + if (data->event_channel == chan->address) { + switch (dir) { + case IIO_EV_DIR_RISING: + ret = 1; + break; + case IIO_EV_DIR_EITHER: + ret = (data->comp_mode == ADS1015_CFG_COMP_MODE_WINDOW); + break; + default: + ret = -EINVAL; + break; + } + } + mutex_unlock(&data->lock); + + return ret; +} + +static int ads1015_enable_event_config(struct ads1015_data *data, + const struct iio_chan_spec *chan, int comp_mode) +{ + int low_thresh = data->thresh_data[chan->address].low_thresh; + int high_thresh = data->thresh_data[chan->address].high_thresh; + int ret; + unsigned int val; + + if (ads1015_event_channel_enabled(data)) { + if (data->event_channel != chan->address || + (data->comp_mode == ADS1015_CFG_COMP_MODE_TRAD && + comp_mode == ADS1015_CFG_COMP_MODE_WINDOW)) + return -EBUSY; + + return 0; + } + + if (comp_mode == ADS1015_CFG_COMP_MODE_TRAD) { + low_thresh = max(-1 << (chan->scan_type.realbits - 1), + high_thresh - 1); + } + ret = regmap_write(data->regmap, ADS1015_LO_THRESH_REG, + low_thresh << chan->scan_type.shift); + if (ret) + return ret; + + ret = regmap_write(data->regmap, ADS1015_HI_THRESH_REG, + high_thresh << chan->scan_type.shift); + if (ret) + return ret; + + ret = ads1015_set_power_state(data, true); + if (ret < 0) + return ret; + + ads1015_event_channel_enable(data, chan->address, comp_mode); + + ret = ads1015_get_adc_result(data, chan->address, &val); + if (ret) { + ads1015_event_channel_disable(data, chan->address); + ads1015_set_power_state(data, false); + } + + return ret; +} + +static int ads1015_disable_event_config(struct ads1015_data *data, + const struct iio_chan_spec *chan, int comp_mode) +{ + int ret; + + if (!ads1015_event_channel_enabled(data)) + return 0; + + if (data->event_channel != chan->address) + return 0; + + if (data->comp_mode == ADS1015_CFG_COMP_MODE_TRAD && + comp_mode == ADS1015_CFG_COMP_MODE_WINDOW) + return 0; + + ret = regmap_update_bits(data->regmap, ADS1015_CFG_REG, + ADS1015_CFG_COMP_QUE_MASK, + ADS1015_CFG_COMP_DISABLE << + ADS1015_CFG_COMP_QUE_SHIFT); + if (ret) + return ret; + + ads1015_event_channel_disable(data, chan->address); + + return ads1015_set_power_state(data, false); +} + +static int ads1015_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, enum iio_event_type type, + enum iio_event_direction dir, int state) +{ + struct ads1015_data *data = iio_priv(indio_dev); + int ret; + int comp_mode = (dir == IIO_EV_DIR_EITHER) ? + ADS1015_CFG_COMP_MODE_WINDOW : ADS1015_CFG_COMP_MODE_TRAD; + + mutex_lock(&data->lock); + + /* Prevent from enabling both buffer and event at a time */ + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) { + mutex_unlock(&data->lock); + return ret; + } + + if (state) + ret = ads1015_enable_event_config(data, chan, comp_mode); + else + ret = ads1015_disable_event_config(data, chan, comp_mode); + + iio_device_release_direct_mode(indio_dev); + mutex_unlock(&data->lock); + + return ret; +} + +static irqreturn_t ads1015_event_handler(int irq, void *priv) +{ + struct iio_dev *indio_dev = priv; + struct ads1015_data *data = iio_priv(indio_dev); + int val; + int ret; + + /* Clear the latched ALERT/RDY pin */ + ret = regmap_read(data->regmap, ADS1015_CONV_REG, &val); + if (ret) + return IRQ_HANDLED; + + if (ads1015_event_channel_enabled(data)) { + enum iio_event_direction dir; + u64 code; + + dir = data->comp_mode == ADS1015_CFG_COMP_MODE_TRAD ? + IIO_EV_DIR_RISING : IIO_EV_DIR_EITHER; + code = IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, data->event_channel, + IIO_EV_TYPE_THRESH, dir); + iio_push_event(indio_dev, code, iio_get_time_ns(indio_dev)); + } + + return IRQ_HANDLED; +} + static int ads1015_buffer_preenable(struct iio_dev *indio_dev) { + struct ads1015_data *data = iio_priv(indio_dev); + + /* Prevent from enabling both buffer and event at a time */ + if (ads1015_event_channel_enabled(data)) + return -EBUSY; + return ads1015_set_power_state(iio_priv(indio_dev), true); } @@ -446,7 +790,10 @@ static const struct iio_buffer_setup_ops ads1015_buffer_setup_ops = { .validate_scan_mask = &iio_validate_scan_mask_onehot, }; -static IIO_CONST_ATTR(scale_available, "3 2 1 0.5 0.25 0.125"); +static IIO_CONST_ATTR_NAMED(ads1015_scale_available, scale_available, + "3 2 1 0.5 0.25 0.125"); +static IIO_CONST_ATTR_NAMED(ads1115_scale_available, scale_available, + "0.1875 0.125 0.0625 0.03125 0.015625 0.007813"); static IIO_CONST_ATTR_NAMED(ads1015_sampling_frequency_available, sampling_frequency_available, "128 250 490 920 1600 2400 3300"); @@ -454,7 +801,7 @@ 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_ads1015_scale_available.dev_attr.attr, &iio_const_attr_ads1015_sampling_frequency_available.dev_attr.attr, NULL, }; @@ -464,7 +811,7 @@ static const struct attribute_group ads1015_attribute_group = { }; static struct attribute *ads1115_attributes[] = { - &iio_const_attr_scale_available.dev_attr.attr, + &iio_const_attr_ads1115_scale_available.dev_attr.attr, &iio_const_attr_ads1115_sampling_frequency_available.dev_attr.attr, NULL, }; @@ -477,6 +824,10 @@ static const struct iio_info ads1015_info = { .driver_module = THIS_MODULE, .read_raw = ads1015_read_raw, .write_raw = ads1015_write_raw, + .read_event_value = ads1015_read_event, + .write_event_value = ads1015_write_event, + .read_event_config = ads1015_read_event_config, + .write_event_config = ads1015_write_event_config, .attrs = &ads1015_attribute_group, }; @@ -484,6 +835,10 @@ static const struct iio_info ads1115_info = { .driver_module = THIS_MODULE, .read_raw = ads1015_read_raw, .write_raw = ads1015_write_raw, + .read_event_value = ads1015_read_event, + .write_event_value = ads1015_write_event, + .read_event_config = ads1015_read_event_config, + .write_event_config = ads1015_write_event_config, .attrs = &ads1115_attribute_group, }; @@ -505,24 +860,24 @@ static int ads1015_get_channels_config_of(struct i2c_client *client) unsigned int data_rate = ADS1015_DEFAULT_DATA_RATE; if (of_property_read_u32(node, "reg", &pval)) { - dev_err(&client->dev, "invalid reg on %s\n", - node->full_name); + dev_err(&client->dev, "invalid reg on %pOF\n", + node); continue; } channel = pval; if (channel >= ADS1015_CHANNELS) { dev_err(&client->dev, - "invalid channel index %d on %s\n", - channel, node->full_name); + "invalid channel index %d on %pOF\n", + channel, node); continue; } if (!of_property_read_u32(node, "ti,gain", &pval)) { pga = pval; if (pga > 6) { - dev_err(&client->dev, "invalid gain on %s\n", - node->full_name); + dev_err(&client->dev, "invalid gain on %pOF\n", + node); of_node_put(node); return -EINVAL; } @@ -532,8 +887,8 @@ static int ads1015_get_channels_config_of(struct i2c_client *client) data_rate = pval; if (data_rate > 7) { dev_err(&client->dev, - "invalid data_rate on %s\n", - node->full_name); + "invalid data_rate on %pOF\n", + node); of_node_put(node); return -EINVAL; } @@ -573,6 +928,13 @@ static void ads1015_get_channels_config(struct i2c_client *client) } } +static int ads1015_set_conv_mode(struct ads1015_data *data, int mode) +{ + return regmap_update_bits(data->regmap, ADS1015_CFG_REG, + ADS1015_CFG_MOD_MASK, + mode << ADS1015_CFG_MOD_SHIFT); +} + static int ads1015_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -580,6 +942,7 @@ static int ads1015_probe(struct i2c_client *client, struct ads1015_data *data; int ret; enum chip_ids chip; + int i; indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); if (!indio_dev) @@ -614,6 +977,18 @@ static int ads1015_probe(struct i2c_client *client, break; } + data->event_channel = ADS1015_CHANNELS; + /* + * Set default lower and upper threshold to min and max value + * respectively. + */ + for (i = 0; i < ADS1015_CHANNELS; i++) { + int realbits = indio_dev->channels[i].scan_type.realbits; + + data->thresh_data[i].low_thresh = -1 << (realbits - 1); + data->thresh_data[i].high_thresh = (1 << (realbits - 1)) - 1; + } + /* we need to keep this ABI the same as used by hwmon ADS1015 driver */ ads1015_get_channels_config(client); @@ -623,16 +998,58 @@ static int ads1015_probe(struct i2c_client *client, return PTR_ERR(data->regmap); } - ret = iio_triggered_buffer_setup(indio_dev, NULL, - ads1015_trigger_handler, - &ads1015_buffer_setup_ops); + ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL, + ads1015_trigger_handler, + &ads1015_buffer_setup_ops); if (ret < 0) { dev_err(&client->dev, "iio triggered buffer setup failed\n"); return ret; } + + if (client->irq) { + unsigned long irq_trig = + irqd_get_trigger_type(irq_get_irq_data(client->irq)); + unsigned int cfg_comp_mask = ADS1015_CFG_COMP_QUE_MASK | + ADS1015_CFG_COMP_LAT_MASK | ADS1015_CFG_COMP_POL_MASK; + unsigned int cfg_comp = + ADS1015_CFG_COMP_DISABLE << ADS1015_CFG_COMP_QUE_SHIFT | + 1 << ADS1015_CFG_COMP_LAT_SHIFT; + + switch (irq_trig) { + case IRQF_TRIGGER_LOW: + cfg_comp |= ADS1015_CFG_COMP_POL_LOW << + ADS1015_CFG_COMP_POL_SHIFT; + break; + case IRQF_TRIGGER_HIGH: + cfg_comp |= ADS1015_CFG_COMP_POL_HIGH << + ADS1015_CFG_COMP_POL_SHIFT; + break; + default: + return -EINVAL; + } + + ret = regmap_update_bits(data->regmap, ADS1015_CFG_REG, + cfg_comp_mask, cfg_comp); + if (ret) + return ret; + + ret = devm_request_threaded_irq(&client->dev, client->irq, + NULL, ads1015_event_handler, + irq_trig | IRQF_ONESHOT, + client->name, indio_dev); + if (ret) + return ret; + } + + ret = ads1015_set_conv_mode(data, ADS1015_CONTINUOUS); + if (ret) + return ret; + + data->conv_invalid = true; + ret = pm_runtime_set_active(&client->dev); if (ret) - goto err_buffer_cleanup; + return ret; pm_runtime_set_autosuspend_delay(&client->dev, ADS1015_SLEEP_DELAY_MS); pm_runtime_use_autosuspend(&client->dev); pm_runtime_enable(&client->dev); @@ -640,15 +1057,10 @@ static int ads1015_probe(struct i2c_client *client, ret = iio_device_register(indio_dev); if (ret < 0) { dev_err(&client->dev, "Failed to register IIO device\n"); - goto err_buffer_cleanup; + return ret; } return 0; - -err_buffer_cleanup: - iio_triggered_buffer_cleanup(indio_dev); - - return ret; } static int ads1015_remove(struct i2c_client *client) @@ -662,12 +1074,8 @@ static int ads1015_remove(struct i2c_client *client) pm_runtime_set_suspended(&client->dev); pm_runtime_put_noidle(&client->dev); - iio_triggered_buffer_cleanup(indio_dev); - /* power down single shot mode */ - return regmap_update_bits(data->regmap, ADS1015_CFG_REG, - ADS1015_CFG_MOD_MASK, - ADS1015_SINGLESHOT << ADS1015_CFG_MOD_SHIFT); + return ads1015_set_conv_mode(data, ADS1015_SINGLESHOT); } #ifdef CONFIG_PM @@ -676,19 +1084,20 @@ static int ads1015_runtime_suspend(struct device *dev) struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); struct ads1015_data *data = iio_priv(indio_dev); - return regmap_update_bits(data->regmap, ADS1015_CFG_REG, - ADS1015_CFG_MOD_MASK, - ADS1015_SINGLESHOT << ADS1015_CFG_MOD_SHIFT); + return ads1015_set_conv_mode(data, ADS1015_SINGLESHOT); } static int ads1015_runtime_resume(struct device *dev) { struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); struct ads1015_data *data = iio_priv(indio_dev); + int ret; - return regmap_update_bits(data->regmap, ADS1015_CFG_REG, - ADS1015_CFG_MOD_MASK, - ADS1015_CONTINUOUS << ADS1015_CFG_MOD_SHIFT); + ret = ads1015_set_conv_mode(data, ADS1015_CONTINUOUS); + if (!ret) + data->conv_invalid = true; + + return ret; } #endif diff --git a/drivers/iio/adc/ti-ads7950.c b/drivers/iio/adc/ti-ads7950.c index 16a06633332c..a376190914ad 100644 --- a/drivers/iio/adc/ti-ads7950.c +++ b/drivers/iio/adc/ti-ads7950.c @@ -21,6 +21,7 @@ * GNU General Public License for more details. */ +#include <linux/acpi.h> #include <linux/bitops.h> #include <linux/device.h> #include <linux/err.h> @@ -37,6 +38,12 @@ #include <linux/iio/trigger_consumer.h> #include <linux/iio/triggered_buffer.h> +/* + * In case of ACPI, we use the 5000 mV as default for the reference pin. + * Device tree users encode that via the vref-supply regulator. + */ +#define TI_ADS7950_VA_MV_ACPI_DEFAULT 5000 + #define TI_ADS7950_CR_MANUAL BIT(12) #define TI_ADS7950_CR_WRITE BIT(11) #define TI_ADS7950_CR_CHAN(ch) ((ch) << 7) @@ -58,6 +65,7 @@ struct ti_ads7950_state { struct spi_message scan_single_msg; struct regulator *reg; + unsigned int vref_mv; unsigned int settings; @@ -305,11 +313,15 @@ static int ti_ads7950_get_range(struct ti_ads7950_state *st) { int vref; - vref = regulator_get_voltage(st->reg); - if (vref < 0) - return vref; + if (st->vref_mv) { + vref = st->vref_mv; + } else { + vref = regulator_get_voltage(st->reg); + if (vref < 0) + return vref; - vref /= 1000; + vref /= 1000; + } if (st->settings & TI_ADS7950_CR_RANGE_5V) vref *= 2; @@ -411,6 +423,10 @@ static int ti_ads7950_probe(struct spi_device *spi) spi_message_init_with_transfers(&st->scan_single_msg, st->scan_single_xfer, 3); + /* Use hard coded value for reference voltage in ACPI case */ + if (ACPI_COMPANION(&spi->dev)) + st->vref_mv = TI_ADS7950_VA_MV_ACPI_DEFAULT; + st->reg = devm_regulator_get(&spi->dev, "vref"); if (IS_ERR(st->reg)) { dev_err(&spi->dev, "Failed get get regulator \"vref\"\n"); @@ -475,9 +491,27 @@ static const struct spi_device_id ti_ads7950_id[] = { }; MODULE_DEVICE_TABLE(spi, ti_ads7950_id); +static const struct of_device_id ads7950_of_table[] = { + { .compatible = "ti,ads7950", .data = &ti_ads7950_chip_info[TI_ADS7950] }, + { .compatible = "ti,ads7951", .data = &ti_ads7950_chip_info[TI_ADS7951] }, + { .compatible = "ti,ads7952", .data = &ti_ads7950_chip_info[TI_ADS7952] }, + { .compatible = "ti,ads7953", .data = &ti_ads7950_chip_info[TI_ADS7953] }, + { .compatible = "ti,ads7954", .data = &ti_ads7950_chip_info[TI_ADS7954] }, + { .compatible = "ti,ads7955", .data = &ti_ads7950_chip_info[TI_ADS7955] }, + { .compatible = "ti,ads7956", .data = &ti_ads7950_chip_info[TI_ADS7956] }, + { .compatible = "ti,ads7957", .data = &ti_ads7950_chip_info[TI_ADS7957] }, + { .compatible = "ti,ads7958", .data = &ti_ads7950_chip_info[TI_ADS7958] }, + { .compatible = "ti,ads7959", .data = &ti_ads7950_chip_info[TI_ADS7959] }, + { .compatible = "ti,ads7960", .data = &ti_ads7950_chip_info[TI_ADS7960] }, + { .compatible = "ti,ads7961", .data = &ti_ads7950_chip_info[TI_ADS7961] }, + { }, +}; +MODULE_DEVICE_TABLE(of, ads7950_of_table); + static struct spi_driver ti_ads7950_driver = { .driver = { .name = "ads7950", + .of_match_table = ads7950_of_table, }, .probe = ti_ads7950_probe, .remove = ti_ads7950_remove, diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c index 0c74869a540a..e3cfb91bffc6 100644 --- a/drivers/iio/adc/twl4030-madc.c +++ b/drivers/iio/adc/twl4030-madc.c @@ -35,8 +35,7 @@ #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/slab.h> -#include <linux/i2c/twl.h> -#include <linux/i2c/twl4030-madc.h> +#include <linux/mfd/twl.h> #include <linux/module.h> #include <linux/stddef.h> #include <linux/mutex.h> @@ -49,9 +48,121 @@ #include <linux/iio/iio.h> +#define TWL4030_MADC_MAX_CHANNELS 16 + +#define TWL4030_MADC_CTRL1 0x00 +#define TWL4030_MADC_CTRL2 0x01 + +#define TWL4030_MADC_RTSELECT_LSB 0x02 +#define TWL4030_MADC_SW1SELECT_LSB 0x06 +#define TWL4030_MADC_SW2SELECT_LSB 0x0A + +#define TWL4030_MADC_RTAVERAGE_LSB 0x04 +#define TWL4030_MADC_SW1AVERAGE_LSB 0x08 +#define TWL4030_MADC_SW2AVERAGE_LSB 0x0C + +#define TWL4030_MADC_CTRL_SW1 0x12 +#define TWL4030_MADC_CTRL_SW2 0x13 + +#define TWL4030_MADC_RTCH0_LSB 0x17 +#define TWL4030_MADC_GPCH0_LSB 0x37 + +#define TWL4030_MADC_MADCON (1 << 0) /* MADC power on */ +#define TWL4030_MADC_BUSY (1 << 0) /* MADC busy */ +/* MADC conversion completion */ +#define TWL4030_MADC_EOC_SW (1 << 1) +/* MADC SWx start conversion */ +#define TWL4030_MADC_SW_START (1 << 5) +#define TWL4030_MADC_ADCIN0 (1 << 0) +#define TWL4030_MADC_ADCIN1 (1 << 1) +#define TWL4030_MADC_ADCIN2 (1 << 2) +#define TWL4030_MADC_ADCIN3 (1 << 3) +#define TWL4030_MADC_ADCIN4 (1 << 4) +#define TWL4030_MADC_ADCIN5 (1 << 5) +#define TWL4030_MADC_ADCIN6 (1 << 6) +#define TWL4030_MADC_ADCIN7 (1 << 7) +#define TWL4030_MADC_ADCIN8 (1 << 8) +#define TWL4030_MADC_ADCIN9 (1 << 9) +#define TWL4030_MADC_ADCIN10 (1 << 10) +#define TWL4030_MADC_ADCIN11 (1 << 11) +#define TWL4030_MADC_ADCIN12 (1 << 12) +#define TWL4030_MADC_ADCIN13 (1 << 13) +#define TWL4030_MADC_ADCIN14 (1 << 14) +#define TWL4030_MADC_ADCIN15 (1 << 15) + +/* Fixed channels */ +#define TWL4030_MADC_BTEMP TWL4030_MADC_ADCIN1 +#define TWL4030_MADC_VBUS TWL4030_MADC_ADCIN8 +#define TWL4030_MADC_VBKB TWL4030_MADC_ADCIN9 +#define TWL4030_MADC_ICHG TWL4030_MADC_ADCIN10 +#define TWL4030_MADC_VCHG TWL4030_MADC_ADCIN11 +#define TWL4030_MADC_VBAT TWL4030_MADC_ADCIN12 + +/* Step size and prescaler ratio */ +#define TEMP_STEP_SIZE 147 +#define TEMP_PSR_R 100 +#define CURR_STEP_SIZE 147 +#define CURR_PSR_R1 44 +#define CURR_PSR_R2 88 + +#define TWL4030_BCI_BCICTL1 0x23 +#define TWL4030_BCI_CGAIN 0x020 +#define TWL4030_BCI_MESBAT (1 << 1) +#define TWL4030_BCI_TYPEN (1 << 4) +#define TWL4030_BCI_ITHEN (1 << 3) + +#define REG_BCICTL2 0x024 +#define TWL4030_BCI_ITHSENS 0x007 + +/* Register and bits for GPBR1 register */ +#define TWL4030_REG_GPBR1 0x0c +#define TWL4030_GPBR1_MADC_HFCLK_EN (1 << 7) + #define TWL4030_USB_SEL_MADC_MCPC (1<<3) #define TWL4030_USB_CARKIT_ANA_CTRL 0xBB +struct twl4030_madc_conversion_method { + u8 sel; + u8 avg; + u8 rbase; + u8 ctrl; +}; + +/** + * struct twl4030_madc_request - madc request packet for channel conversion + * @channels: 16 bit bitmap for individual channels + * @do_avg: sample the input channel for 4 consecutive cycles + * @method: RT, SW1, SW2 + * @type: Polling or interrupt based method + * @active: Flag if request is active + * @result_pending: Flag from irq handler, that result is ready + * @raw: Return raw value, do not convert it + * @rbuf: Result buffer + */ +struct twl4030_madc_request { + unsigned long channels; + bool do_avg; + u16 method; + u16 type; + bool active; + bool result_pending; + bool raw; + int rbuf[TWL4030_MADC_MAX_CHANNELS]; +}; + +enum conversion_methods { + TWL4030_MADC_RT, + TWL4030_MADC_SW1, + TWL4030_MADC_SW2, + TWL4030_MADC_NUM_METHODS +}; + +enum sample_type { + TWL4030_MADC_WAIT, + TWL4030_MADC_IRQ_ONESHOT, + TWL4030_MADC_IRQ_REARM +}; + /** * struct twl4030_madc_data - a container for madc info * @dev: Pointer to device structure for madc @@ -72,6 +183,8 @@ struct twl4030_madc_data { u8 isr; }; +static int twl4030_madc_conversion(struct twl4030_madc_request *req); + static int twl4030_madc_read(struct iio_dev *iio_dev, const struct iio_chan_spec *chan, int *val, int *val2, long mask) @@ -84,7 +197,6 @@ static int twl4030_madc_read(struct iio_dev *iio_dev, req.channels = BIT(chan->channel); req.active = false; - req.func_cb = NULL; req.type = TWL4030_MADC_WAIT; req.raw = !(mask == IIO_CHAN_INFO_PROCESSED); req.do_avg = (mask == IIO_CHAN_INFO_AVERAGE_RAW); @@ -341,37 +453,6 @@ static int twl4030_madc_read_channels(struct twl4030_madc_data *madc, } /* - * Enables irq. - * @madc - pointer to twl4030_madc_data struct - * @id - irq number to be enabled - * can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2 - * corresponding to RT, SW1, SW2 conversion requests. - * If the i2c read fails it returns an error else returns 0. - */ -static int twl4030_madc_enable_irq(struct twl4030_madc_data *madc, u8 id) -{ - u8 val; - int ret; - - ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, madc->imr); - if (ret) { - dev_err(madc->dev, "unable to read imr register 0x%X\n", - madc->imr); - return ret; - } - - val &= ~(1 << id); - ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr); - if (ret) { - dev_err(madc->dev, - "unable to write imr register 0x%X\n", madc->imr); - return ret; - } - - return 0; -} - -/* * Disables irq. * @madc - pointer to twl4030_madc_data struct * @id - irq number to be disabled @@ -440,11 +521,6 @@ static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc) /* Read results */ len = twl4030_madc_read_channels(madc, method->rbase, r->channels, r->rbuf, r->raw); - /* Return results to caller */ - if (r->func_cb != NULL) { - r->func_cb(len, r->channels, r->rbuf); - r->func_cb = NULL; - } /* Free request */ r->result_pending = 0; r->active = 0; @@ -466,11 +542,6 @@ err_i2c: /* Read results */ len = twl4030_madc_read_channels(madc, method->rbase, r->channels, r->rbuf, r->raw); - /* Return results to caller */ - if (r->func_cb != NULL) { - r->func_cb(len, r->channels, r->rbuf); - r->func_cb = NULL; - } /* Free request */ r->result_pending = 0; r->active = 0; @@ -480,23 +551,6 @@ err_i2c: return IRQ_HANDLED; } -static int twl4030_madc_set_irq(struct twl4030_madc_data *madc, - struct twl4030_madc_request *req) -{ - struct twl4030_madc_request *p; - int ret; - - p = &madc->requests[req->method]; - memcpy(p, req, sizeof(*req)); - ret = twl4030_madc_enable_irq(madc, req->method); - if (ret < 0) { - dev_err(madc->dev, "enable irq failed!!\n"); - return ret; - } - - return 0; -} - /* * Function which enables the madc conversion * by writing to the control register. @@ -568,7 +622,7 @@ static int twl4030_madc_wait_conversion_ready(struct twl4030_madc_data *madc, * be a negative error value in the corresponding array element. * returns 0 if succeeds else error value */ -int twl4030_madc_conversion(struct twl4030_madc_request *req) +static int twl4030_madc_conversion(struct twl4030_madc_request *req) { const struct twl4030_madc_conversion_method *method; int ret; @@ -605,17 +659,6 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req) goto out; } } - if (req->type == TWL4030_MADC_IRQ_ONESHOT && req->func_cb != NULL) { - ret = twl4030_madc_set_irq(twl4030_madc, req); - if (ret < 0) - goto out; - ret = twl4030_madc_start_conversion(twl4030_madc, req->method); - if (ret < 0) - goto out; - twl4030_madc->requests[req->method].active = 1; - ret = 0; - goto out; - } /* With RT method we should not be here anymore */ if (req->method == TWL4030_MADC_RT) { ret = -EINVAL; @@ -640,28 +683,6 @@ out: return ret; } -EXPORT_SYMBOL_GPL(twl4030_madc_conversion); - -int twl4030_get_madc_conversion(int channel_no) -{ - struct twl4030_madc_request req; - int temp = 0; - int ret; - - req.channels = (1 << channel_no); - req.method = TWL4030_MADC_SW2; - req.active = 0; - req.raw = 0; - req.func_cb = NULL; - ret = twl4030_madc_conversion(&req); - if (ret < 0) - return ret; - if (req.rbuf[channel_no] > 0) - temp = req.rbuf[channel_no]; - - return temp; -} -EXPORT_SYMBOL_GPL(twl4030_get_madc_conversion); /** * twl4030_madc_set_current_generator() - setup bias current @@ -866,21 +887,27 @@ static int twl4030_madc_probe(struct platform_device *pdev) /* Enable 3v1 bias regulator for MADC[3:6] */ madc->usb3v1 = devm_regulator_get(madc->dev, "vusb3v1"); - if (IS_ERR(madc->usb3v1)) - return -ENODEV; + if (IS_ERR(madc->usb3v1)) { + ret = -ENODEV; + goto err_i2c; + } ret = regulator_enable(madc->usb3v1); - if (ret) + if (ret) { dev_err(madc->dev, "could not enable 3v1 bias regulator\n"); + goto err_i2c; + } ret = iio_device_register(iio_dev); if (ret) { dev_err(&pdev->dev, "could not register iio device\n"); - goto err_i2c; + goto err_usb3v1; } return 0; +err_usb3v1: + regulator_disable(madc->usb3v1); err_i2c: twl4030_madc_set_current_generator(madc, 0, 0); err_current_generator: diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c index becbb0aef232..bc0e60b9da45 100644 --- a/drivers/iio/adc/twl6030-gpadc.c +++ b/drivers/iio/adc/twl6030-gpadc.c @@ -33,7 +33,7 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/of_platform.h> -#include <linux/i2c/twl.h> +#include <linux/mfd/twl.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c index 01fc76f7d660..c168e0db329a 100644 --- a/drivers/iio/adc/vf610_adc.c +++ b/drivers/iio/adc/vf610_adc.c @@ -77,7 +77,7 @@ #define VF610_ADC_ADSTS_MASK 0x300 #define VF610_ADC_ADLPC_EN 0x80 #define VF610_ADC_ADHSC_EN 0x400 -#define VF610_ADC_REFSEL_VALT 0x100 +#define VF610_ADC_REFSEL_VALT 0x800 #define VF610_ADC_REFSEL_VBG 0x1000 #define VF610_ADC_ADTRG_HARD 0x2000 #define VF610_ADC_AVGS_8 0x4000 diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c index 56cf5907a5f0..4a60497a1f19 100644 --- a/drivers/iio/adc/xilinx-xadc-core.c +++ b/drivers/iio/adc/xilinx-xadc-core.c @@ -1204,7 +1204,10 @@ static int xadc_probe(struct platform_device *pdev) ret = PTR_ERR(xadc->clk); goto err_free_samplerate_trigger; } - clk_prepare_enable(xadc->clk); + + ret = clk_prepare_enable(xadc->clk); + if (ret) + goto err_free_samplerate_trigger; ret = xadc->ops->setup(pdev, indio_dev, irq); if (ret) diff --git a/drivers/iio/adc/xilinx-xadc-events.c b/drivers/iio/adc/xilinx-xadc-events.c index 6d5c2a6f4e6e..dc0670308253 100644 --- a/drivers/iio/adc/xilinx-xadc-events.c +++ b/drivers/iio/adc/xilinx-xadc-events.c @@ -68,7 +68,7 @@ void xadc_handle_events(struct iio_dev *indio_dev, unsigned long events) xadc_handle_event(indio_dev, i); } -static unsigned xadc_get_threshold_offset(const struct iio_chan_spec *chan, +static unsigned int xadc_get_threshold_offset(const struct iio_chan_spec *chan, enum iio_event_direction dir) { unsigned int offset; @@ -90,26 +90,24 @@ static unsigned xadc_get_threshold_offset(const struct iio_chan_spec *chan, static unsigned int xadc_get_alarm_mask(const struct iio_chan_spec *chan) { - if (chan->type == IIO_TEMP) { + if (chan->type == IIO_TEMP) return XADC_ALARM_OT_MASK; - } else { - switch (chan->channel) { - case 0: - return XADC_ALARM_VCCINT_MASK; - case 1: - return XADC_ALARM_VCCAUX_MASK; - case 2: - return XADC_ALARM_VCCBRAM_MASK; - case 3: - return XADC_ALARM_VCCPINT_MASK; - case 4: - return XADC_ALARM_VCCPAUX_MASK; - case 5: - return XADC_ALARM_VCCODDR_MASK; - default: - /* We will never get here */ - return 0; - } + switch (chan->channel) { + case 0: + return XADC_ALARM_VCCINT_MASK; + case 1: + return XADC_ALARM_VCCAUX_MASK; + case 2: + return XADC_ALARM_VCCBRAM_MASK; + case 3: + return XADC_ALARM_VCCPINT_MASK; + case 4: + return XADC_ALARM_VCCPAUX_MASK; + case 5: + return XADC_ALARM_VCCODDR_MASK; + default: + /* We will never get here */ + return 0; } } diff --git a/drivers/iio/adc/xilinx-xadc.h b/drivers/iio/adc/xilinx-xadc.h index f6f081965647..62edbdae1244 100644 --- a/drivers/iio/adc/xilinx-xadc.h +++ b/drivers/iio/adc/xilinx-xadc.h @@ -71,13 +71,13 @@ struct xadc { }; struct xadc_ops { - int (*read)(struct xadc *, unsigned int, uint16_t *); - int (*write)(struct xadc *, unsigned int, uint16_t); + int (*read)(struct xadc *xadc, unsigned int reg, uint16_t *val); + int (*write)(struct xadc *xadc, unsigned int reg, uint16_t val); int (*setup)(struct platform_device *pdev, struct iio_dev *indio_dev, int irq); - void (*update_alarm)(struct xadc *, unsigned int); - unsigned long (*get_dclk_rate)(struct xadc *); - irqreturn_t (*interrupt_handler)(int, void *); + void (*update_alarm)(struct xadc *xadc, unsigned int alarm); + unsigned long (*get_dclk_rate)(struct xadc *xadc); + irqreturn_t (*interrupt_handler)(int irq, void *devid); unsigned int flags; }; |